views:

2143

answers:

3

Hi there!
Do you know some quick and sufficient way to get altitude (elevation) by longitude and latitude, that would be easy to use on Android platform?

While this is a self-learning question, my approach is still time-consuming ('coz it's web-service etc), so I would like to receive any alternatives or possible improvement suggestions!

Thank you!

+15  A: 

elevation app screen

My approach is to use 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;
}

And example of use (right in HelloMapView class):

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;
            }
        });
    }
Max Gontar
As somewhat GIS interested I find this very interesting
JaanusSiim
To amplify on this: the reason you need to do something like that (use a service on the network) is twofold: one, the GPS isn't very good at altitude, vertical errors are around 150 ft at times, and two, any reasonably high-resolution world elevation model is enormous, much too big to install on the phone.If you were doing this on your own server as part of a web app or GIS, you could instead download the elevation model (from NASA) and query it directly; faster, but uses a lot of storage.
Andrew McGregor
Andrew thanks for you feedback, it's great!
Max Gontar
To clarify, this actually grabs the elevation and NOT the altitude of a lat/long point.
Austyn Mahoney
A: 

I am amazed. I always thought that the GPS measures all 3 dimensions with roughly the same accuracy. The same goes for the old transit satellite navigation system as well. And besides, getAltitude( ) only gives you the 'altitude' of the ground surface, not the receiver, I guess. While typing this, I am asking myself, what 'altitude' does the GPS really calculate? Isn't it the altitude relative to a reference ellipsoid? I guess the receiver just has a simple model of the shape of the earth, a smooth 'ellipsoid', or does it really know about the major wrinkles of the earth?

Any gps coordinate is found by lining it up with distance from a few satellites (with particular accuracy). Since the satellites are much closer vertically than horizontal, it's difficult to get an accurate read.getAltitude seems like the best option - unless the reported altitude is far away from original altitude report (maybe the receiver is in an airplane or on a bridge).
BankStrong
To get decent, accurate altitude information, a GPS receiver with WAAS is required.
Brian Knoblauch
A: 

Max I used your code. and same longitude, latitude. but I get alititude like -1.79769313486231E+308. it's not 326.0 why?

yun.j
Max Gontar
Also, please keep it in comments when responding to someone answer :) thanks!
Max Gontar
"If unable to find data at the requested point, this service returns an extremely large, negative value (-1.79769313486231E+308)."http://gisdata.usgs.gov/xmlwebservices2/elevation_service.asmx
Austyn Mahoney