在Android中通过经度和纬度获取高度
Posted
技术标签:
【中文标题】在Android中通过经度和纬度获取高度【英文标题】:Get altitude by longitude and latitude in Android 【发布时间】:2011-01-01 01:06:38 【问题描述】:有没有在android平台上通过经纬度快速高效获取海拔(海拔)的方法?
【问题讨论】:
【参考方案1】:我的做法是使用USGS Elevation Query Web Service:
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;
);
【讨论】:
放大这一点:你需要做这样的事情(使用网络上的服务)的原因有两个:第一,GPS 在高度上不是很好,垂直误差在 150 左右有时英尺,第二,任何合理的高分辨率世界海拔模型都是巨大的,太大而无法安装在手机上。如果您在自己的服务器上作为 Web 应用程序或 GIS 的一部分执行此操作,则可以改为下载高程模型(来自 NASA)并直接查询;速度更快,但会占用大量存储空间。 澄清一下,这实际上是获取海拔高度而不是纬度/经度点的高度。 澄清更多:高度是由设备测量的,例如,它可以在飞机上飞行。高程是指地面,不会改变。当然,只能从数据库中获取海拔高度。 除非你们比我高很多,或者开着带有可笑悬架的汽车,否则高度和海拔实际上是一回事在这种情况下。 gisdata.usgs.gov 网络服务不再工作。它重定向到nationalmap.gov 网站。但我发现没有休息服务在那里做同样的事情。【参考方案2】:您还可以使用 Google Elevation API。它的在线文档位于: https://developers.google.com/maps/documentation/elevation/
请注意上述 API 页面中的以下内容:
使用限制:使用 Google 地理编码 API 受查询 2,500 个地理定位请求的限制 每天。 (谷歌地图 API 用户 Premier 最多可以执行 100,000 每天的请求。)这个限制是 强制执行以防止滥用和/或 重新利用地理编码 API,以及 此限制可能会在 未来恕不另行通知。此外, 我们强制执行请求速率限制 防止滥用服务。如果你 超过 24 小时限制或其他 滥用服务,Geocoding API 可能会暂时停止为您工作。 如果你继续超过这个限制, 您对 Geocoding API 的访问可能 被阻止。注意:地理编码 API 只能与 谷歌地图;地理编码结果没有 在地图上显示它们是 禁止。有关完整的详细信息 允许使用,请参阅 Maps API 服务许可限制条款。
为 Google API 更改上面的 Max Gontar's 代码会得到以下结果,返回的高度以英尺为单位:
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;
【讨论】:
【参考方案3】:如果您使用的是具有 GPS 接收器的 android 设备,那么有一个方法 getAltitude() 通过使用该方法您可以通过海拔获取高度。
【讨论】:
该方法分配给哪个对象类型。你不能只给别人一半的蛋糕。 Location 对象,当使用 Play Services 的融合位置 API 时 您可以在 onLocationChanged(Location location)location.getAltitude() 中使用它,但它总是返回 0.0【参考方案4】:使用 Google Elevation API 的想法很好,但使用字符串函数解析 XML 则不然。此外,HttpClient 现在已被弃用,因为它使用了不安全的连接。
查看这里以获得更好的解决方案: https://github.com/M66B/BackPackTrackII/blob/master/app/src/main/java/eu/faircode/backpacktrack2/GoogleElevationApi.java
【讨论】:
【参考方案5】:谷歌地图有海拔,你需要的是这段代码
altitude="";
var init = function()
var elevator = new google.maps.ElevationService;
map.on('mousemove', function(event)
getLocationElevation(event.latlng, elevator);
document.getElementsByClassName("altitudeClass")[0].innerhtml = "Altitude: "+ getAltitude();
//console.debug(getAltitude());
);
var getLocationElevation = function (location, elevator)
// Initiate the location request
elevator.getElevationForLocations(
'locations': [location]
, function(results, status)
if (status === google.maps.ElevationStatus.OK)
// Retrieve the first result
if (results[0])
// Open the infowindow indicating the elevation at the clicked position.
setAltitude(parseFloat(results[0].elevation).toFixed(2));
else
setAltitude('No results found');
else
setAltitude('Elevation service failed due to: ' + status);
);
function setAltitude(a)
altitude = a;
function getAltitude()
return altitude;
【讨论】:
谷歌地图有海拔,你需要的就是这个代码 另外,该服务不再免费。【参考方案6】:试试我建的这个: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());
【讨论】:
【参考方案7】:首先区分海拔高度很重要。
高度是从一个点到当地表面的距离;无论是陆地还是水。这种测量主要用于航空。
高度可以通过Location.getAltitude()函数获取。
海拔是当地表面到海平面的距离;更经常使用,并且经常被错误地称为高度。
话虽如此,对于美国,USGS 提供了一个newer HTTP POST and GET queries,它可以返回 XML 或 JSON 值,以英尺或米为单位。对于全球海拔,您可以使用Google Elevation API。
【讨论】:
以上是关于在Android中通过经度和纬度获取高度的主要内容,如果未能解决你的问题,请参考以下文章
如何在sql server中通过给定的邮政编码和以英里为单位的半径从附近的表中获取所有其他邮政编码或(纬度和经度)?