Androidプラットフォームで経度と緯度によって高度(標高)を取得するための迅速かつ効率的な方法はありますか?
7 に答える
私のアプローチは、USGS ElevationQueryWebサービスを使用することです。
private double getAltitude(Double longitude, Double latitude) {
double result = Double.NaN;
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
String url = "http://gisdata.usgs.gov/"
+ "xmlwebservices2/elevation_service.asmx/"
+ "getElevation?X_Value=" + String.valueOf(longitude)
+ "&Y_Value=" + String.valueOf(latitude)
+ "&Elevation_Units=METERS&Source_Layer=-1&Elevation_Only=true";
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(httpGet, localContext);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
int r = -1;
StringBuffer respStr = new StringBuffer();
while ((r = instream.read()) != -1)
respStr.append((char) r);
String tagOpen = "<double>";
String tagClose = "</double>";
if (respStr.indexOf(tagOpen) != -1) {
int start = respStr.indexOf(tagOpen) + tagOpen.length();
int end = respStr.indexOf(tagClose);
String value = respStr.substring(start, end);
result = Double.parseDouble(value);
}
instream.close();
}
} catch (ClientProtocolException e) {}
catch (IOException e) {}
return result;
}
そして使用例(HelloMapViewクラスで):
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
linearLayout = (LinearLayout) findViewById(R.id.zoomview);
mapView = (MapView) findViewById(R.id.mapview);
mZoom = (ZoomControls) mapView.getZoomControls();
linearLayout.addView(mZoom);
mapView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == 1) {
final GeoPoint p = mapView.getProjection().fromPixels(
(int) event.getX(), (int) event.getY());
final StringBuilder msg = new StringBuilder();
new Thread(new Runnable() {
public void run() {
final double lon = p.getLongitudeE6() / 1E6;
final double lat = p.getLatitudeE6() / 1E6;
final double alt = getAltitude(lon, lat);
msg.append("Lon: ");
msg.append(lon);
msg.append(" Lat: ");
msg.append(lat);
msg.append(" Alt: ");
msg.append(alt);
}
}).run();
Toast.makeText(getBaseContext(), msg, Toast.LENGTH_SHORT)
.show();
}
return false;
}
});
}
Google Elevation API を使用することもできます。そのオンライン ドキュメントは、 https ://developers.google.com/maps/documentation/elevation/ にあります。
上記の API ページから次の点に注意してください。
使用制限: Google Geocoding API の使用には、1 日あたり 2,500 件のジオロケーション リクエストのクエリ制限が適用されます。(Google Maps API Premier のユーザーは、1 日あたり最大 100,000 のリクエストを実行できます。) この制限は、Geocoding API の悪用や転用を防ぐために適用されます。この制限は、将来予告なしに変更される可能性があります。さらに、サービスの悪用を防ぐためにリクエスト レート制限を適用します。24 時間の制限を超えるか、サービスを悪用すると、Geocoding API が一時的に機能しなくなる可能性があります。この制限を超え続けると、Geocoding API へのアクセスがブロックされる可能性があります。注: Geocoding API は、Google マップと組み合わせてのみ使用できます。結果を地図上に表示せずにジオコーディングすることは禁止されています。許可されている使用方法の詳細については、
上記の Max Gontar のコードを Google API 用に変更すると、次のようになります。返される標高はフィート単位で示されます。
private double getElevationFromGoogleMaps(double longitude, double latitude) {
double result = Double.NaN;
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
String url = "http://maps.googleapis.com/maps/api/elevation/"
+ "xml?locations=" + String.valueOf(latitude)
+ "," + String.valueOf(longitude)
+ "&sensor=true";
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(httpGet, localContext);
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instream = entity.getContent();
int r = -1;
StringBuffer respStr = new StringBuffer();
while ((r = instream.read()) != -1)
respStr.append((char) r);
String tagOpen = "<elevation>";
String tagClose = "</elevation>";
if (respStr.indexOf(tagOpen) != -1) {
int start = respStr.indexOf(tagOpen) + tagOpen.length();
int end = respStr.indexOf(tagClose);
String value = respStr.substring(start, end);
result = (double)(Double.parseDouble(value)*3.2808399); // convert from meters to feet
}
instream.close();
}
} catch (ClientProtocolException e) {}
catch (IOException e) {}
return result;
}
まず高度と標高を区別することが重要です。
高度は、ポイントからローカル サーフェスまでの距離です。それが陸であろうと水であろうと。この測定は、主に航空に使用されます。
高度はLocation.getAltitude()関数を使用して取得できます。
標高は、ローカル サーフェスから海面までの距離です。はるかに頻繁に使用され、しばしば誤って高度と呼ばれます。
そうは言っても、米国の場合、USGS は、フィートまたはメートルで標高の XML または JSON 値を返すことができる新しい HTTP POST および GET クエリを提供しています。全世界の標高については、Google Elevation APIを使用できます。
GPS Recever を備えた Android デバイスを使用している場合は、標高によって高度を取得できるgetAltitude()メソッドがあります。
私が作成したものを試してみてください: https://algorithmia.com/algorithms/Gaploid/Elevation
Java の例を次に示します。
import com.algorithmia.*;
import com.algorithmia.algo.*;
String input = "{\"lat\": \"50.2111\", \"lon\": \"18.1233\"}";
AlgorithmiaClient client = Algorithmia.client("YOUR_API_KEY");
Algorithm algo = client.algo("algo://Gaploid/Elevation/0.3.0");
AlgoResponse result = algo.pipeJson(input);
System.out.println(result.asJson());