Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Sort Geo-points according to the distance from current location in Android

I have a "Place" object with a LatLng coordinate for each:

import com.google.android.gms.maps.model.LatLng;

public class Place{
    public String name;
    public LatLng latlng;

    public Restaurant(String name, LatLng latlng) {
        this.name = name;
        this.latlng = latlng;
    }
}

and I have an ArrayList of these Places, something like this:

    ArrayList<Place> places = new ArrayList<Place>();
    places.add("Place 1", LatLng(90.0,90.0));
    places.add("Place 2", LatLng(93.0,93.0));
    places.add("Place 3", LatLng(83.0,92.0));
    places.add("Place 4", LatLng(93.0,91.0));

and I have "my" LatLng:

    LatLng myLocation = new LatLng(10.0,10.0);

How can I sort these objects according to closest to me? Thanks for the help

like image 233
user1282637 Avatar asked Apr 18 '15 01:04

user1282637


People also ask

How do I get GPS coordinates from an app?

Google Maps For Android users, Google Maps is the simplest way to either enter latitude and longitude coordinates or to find out your current coordinates. If you want to find your current coordinates, zoom into your location and hold down on the touchpad screen in the map.


2 Answers

Taking the algorithm from this answer from the question posted by @shieldstroy, that uses the Great Circle Distance, I got this example working.

Here is the Comparator:

public class SortPlaces implements Comparator<Place> {
    LatLng currentLoc;

    public SortPlaces(LatLng current){
        currentLoc = current;
    }
    @Override
    public int compare(final Place place1, final Place place2) {
        double lat1 = place1.latlng.latitude;
        double lon1 = place1.latlng.longitude;
        double lat2 = place2.latlng.latitude;
        double lon2 = place2.latlng.longitude;

        double distanceToPlace1 = distance(currentLoc.latitude, currentLoc.longitude, lat1, lon1);
        double distanceToPlace2 = distance(currentLoc.latitude, currentLoc.longitude, lat2, lon2);
        return (int) (distanceToPlace1 - distanceToPlace2);
    }

    public double distance(double fromLat, double fromLon, double toLat, double toLon) {
        double radius = 6378137;   // approximate Earth radius, *in meters*
        double deltaLat = toLat - fromLat;
        double deltaLon = toLon - fromLon;
        double angle = 2 * Math.asin( Math.sqrt(
                Math.pow(Math.sin(deltaLat/2), 2) +
                        Math.cos(fromLat) * Math.cos(toLat) *
                                Math.pow(Math.sin(deltaLon/2), 2) ) );
        return radius * angle;
    }
}

Here is the high level code, I just put this in onCreate():

        //My location, San Francisco
        double lat = 37.77657;
        double lng = -122.417506;
        LatLng latLng = new LatLng(lat, lng);

        //set up list
        ArrayList<Place> places = new ArrayList<Place>();

        places.add(new Place("New York", new LatLng(40.571256,73.98369)));
        places.add(new Place("Colorado", new LatLng(39.260658,-105.101615)));
        places.add(new Place("Los Angeles", new LatLng(33.986816,118.473819)));

        for (Place p: places){
            Log.i("Places before sorting", "Place: " + p.name);
        }

        //sort the list, give the Comparator the current location
        Collections.sort(places, new SortPlaces(latLng));

        for (Place p: places){
            Log.i("Places after sorting", "Place: " + p.name);
        }

Here is the log output:

04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places before sorting﹕ Place: New York
04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places before sorting﹕ Place: Colorado
04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places before sorting﹕ Place: Los Angeles
04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places after sorting﹕ Place: Los Angeles
04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places after sorting﹕ Place: Colorado
04-17 23:04:16.074  12963-12963/com.maptest.daniel.maptest I/Places after sorting﹕ Place: New York
like image 170
Daniel Nugent Avatar answered Oct 13 '22 01:10

Daniel Nugent


For calculating the distance there are different methods available. A quite simple one is the Haversine Formula (http://rosettacode.org/wiki/Haversine_formula#Java). A more accurate calculation would be the Vincenty Formula. If the two locations are not far away, the Haversine solution is quite sufficient.

After calculating the distance, you just sort your array using a comparator, like:

Collections.sort(places, new Comparator<Place>() {
    public int compare(Place p1, Place p2) {
        return Double.compare(p1.getDistance(), p2.getDistance());
    }
});
like image 35
Manu Lanner Avatar answered Oct 13 '22 01:10

Manu Lanner