Sort list of lon\lat points, start with nearest

2019-01-22 15:48发布

I have location from GPS (lon_base, lat_base). I have a list of locations (lon1, lat1|lon2, lat2|lon3, lat3...) This list is very long and is around the world.

My questions are: 1. How do I get from that list only the lon\lat that are 1 mile from my lon_base\lat_base? 2. How do I sort them from closest to farthest?

Thanks in advance!

5条回答
We Are One
2楼-- · 2019-01-22 16:24

You want to define your own Comparator that, in general, looks something like this:

LonLat myHouse = /* whatever */ ;
Comparable comp = new Comparable () {
    LonLat a;
    int compareTo (Object b) {
        int aDist = calcDistance(a, myHouse) ;
        int bDist = calcDistance(b, myHouse) ;
        return aDist - bDist;
    }
};
myLonLatList.sort(lonLatList, comp);

where calcDistance() simply calculates the distance between the two points. If you're on Android, I think Google Maps has a function somewhere in their API that will do this for you.

EDIT : You'll want your calcDistance() function to look like ChrisJ's distance function.

-tjw

查看更多
迷人小祖宗
3楼-- · 2019-01-22 16:30
public static List<Location> sortLocations(List<Location> locations, final double myLatitude,final double myLongitude) {
    Comparator comp = new Comparator<Location>() {
        @Override
        public int compare(Location o, Location o2) {
            float[] result1 = new float[3];
            android.location.Location.distanceBetween(myLatitude, myLongitude, o.Lat, o.Long, result1);
            Float distance1 = result1[0];

            float[] result2 = new float[3];
            android.location.Location.distanceBetween(myLatitude, myLongitude, o2.Lat, o2.Long, result2);
            Float distance2 = result2[0];

            return distance1.compareTo(distance2);
        }
    };


    Collections.sort(locations, comp);
    return locations;
}

Where the List of Locations is a list containing your own Location class, not the android.location.Location.

查看更多
姐就是有狂的资本
4楼-- · 2019-01-22 16:35

You can use followig approximation (since 1 mile is much smaller than the radius of the earth) to calculate the distances from your base:

dx = cos(phi_base) * (theta - theta_base)
dy = phi - phi_base

dist = sqrt(dx*dx+dy*dy) 

with: phi = latitude and theta = longitude

The result is in units of 60 nautical miles if theta and phi are given in degrees. The results will be quite wrong for points that have a latitude that is much different from your base latitude, but this doesn't matter if you just want to know wich points are about 1 mile from your base.

For most programming languages you have to convert phi_base to radians (multiply by pi/180) in order to use it for cos().

(Attention: You have to take special care if your base longitude is very close to 180° or -180°, but probably that is not the case :-)

Use the calculated distances as sorting key to sort your points.

If you have to be more exact (e.g. if you want to know all points that are about 2000 miles from your home), than you must use the formula for Great Circle Distance to calculate the exact distance of two points on a sphere.

查看更多
Bombasti
5楼-- · 2019-01-22 16:39

You may use the great circle distance to calculate the distance between two points whose you know the latitude-longitude coordinates. The formulae are quite easy to code:

static 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;
}
查看更多
狗以群分
6楼-- · 2019-01-22 16:45

According to this link i made working method. The answer above was wrong, because it doesn't convert lat/lng degrees to radians.

    private double getDistance(double fromLat, double fromLon, double toLat, double toLon){
        double radius = 6371;   // Earth radius in km
        double deltaLat = Math.toRadians(toLat - fromLat);
        double deltaLon = Math.toRadians(toLon - fromLon);
        double lat1 = Math.toRadians(fromLat);
        double lat2 = Math.toRadians(toLat);
        double aVal = Math.sin(deltaLat/2) * Math.sin(deltaLat/2) +
            Math.sin(deltaLon/2) * Math.sin(deltaLon/2) * Math.cos(lat1) * Math.cos(lat2);
        double cVal = 2*Math.atan2(Math.sqrt(aVal), Math.sqrt(1-aVal));  

        double distance = radius*cVal;
        Log.d("distance","radius * angle = " +distance);
        return distance;
    }
查看更多
登录 后发表回答