Есть ли быстрый и эффективный способ получить высоту (возвышение) по долготе и широте на платформе Android?
Получить высоту по долготе и широте в Android
Ответы (7)
Мой подход заключается в использовании веб-службы запроса высоты USGS:
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 ограничено 2500 запросами геолокации в день. (Пользователь Google Maps API Premier может выполнять до 100 000 запросов в день.) Это ограничение введено для предотвращения злоупотреблений и/или повторного использования API геокодирования, и это ограничение может быть изменено в будущем без предварительного уведомления. Кроме того, мы применяем ограничение частоты запросов, чтобы предотвратить злоупотребление службой. Если вы превысите 24-часовой лимит или иным образом злоупотребите службой, API геокодирования может временно перестать работать для вас. Если вы продолжите превышать этот лимит, ваш доступ к API геокодирования может быть заблокирован. Примечание. API геокодирования можно использовать только в сочетании с картой Google; результаты геокодирования без отображения их на карте запрещены. Полную информацию о разрешенном использовании см. в Условиях использования Maps API. Лицензионные ограничения.
Изменение кода Макса Гонтара выше для API Google дает следующее, с возвращаемой высотой, указанной в футах:
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() а>функция.
Высота – это расстояние от местной поверхности до уровня моря; гораздо чаще используется и часто ошибочно именуется высотой.
При этом для США Геологическая служба США предоставила более новые HTTP-запросы POST и GET, которые могут возвращать Значения XML или JSON для высоты в футах или метрах. Для глобального повышения вы можете использовать API Google Elevation.
Если вы используете устройство Android с GPS Recever, тогда существует метод 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());
Карты Google имеют высоту, вам нужен этот код
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;
}
Идея использовать Google Elevation API хороша, но парсинг XML с помощью строковых функций — нет. Кроме того, HttpClient теперь устарел, так как использует небезопасные соединения.
Лучшее решение смотрите здесь: https://github.com/M66B/BackPackTrackII/blob/master/app/src/main/java/eu/faircode/backpacktrack2/GoogleElevationApi.java