排序lon \ lat点列表,从最近的点开始

时间:2011-03-22 18:47:10

标签: android sorting gps distance point

我有来自GPS(lon_base,lat_base)的位置。 我有一个位置列表(lon1,lat1 | lon2,lat2 | lon3,lat3 ...) 这份清单很长,遍布世界各地。

我的问题是: 1.如何从该列表中仅获取距离我的lon_base \ lat_base 1英里的lon \ lat? 2.我如何从最近到最远的方式对它们进行排序?

提前致谢!

5 个答案:

答案 0 :(得分:16)

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;
}

其中Locations是一个包含您自己的Location类的列表,而不是android.location.Location。

答案 1 :(得分:6)

您可以使用great circle distance计算您知道纬度 - 经度坐标的两个点之间的距离。 formulae非常容易编码:

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;
}

答案 2 :(得分:3)

您想要定义自己的Comparator,通常看起来像这样:

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);

其中calcDistance()只计算两点之间的距离。如果您使用的是Android,我认为Google地图在其API中的某处可以为您执行此操作。

编辑:您希望calcDistance()函数看起来像ChrisJ的distance函数。

-tjw

答案 3 :(得分:1)

你可以使用跟随近似(因为1英里远小于地球的半径)来计算与基地的距离:

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

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

phi =纬度和theta =经度

如果thetaphi以度为单位,则结果以60海里为单位。 对于纬度与您的基本纬度差别很大的点,结果将是非常错误的,但如果您只是想知道哪个点离您的基地大约1英里,则无关紧要。

对于大多数编程语言,您必须将phi_base转换为弧度(乘以pi / 180)才能将其用于cos()

(注意:如果您的基本经度非常接近180°或-180°,您必须特别小心,但可能情况并非如此:-)

使用计算出的距离作为排序键对点进行排序。

如果你必须更精确(例如,如果你想知道离你家大约2000英里的所有点),你必须使用Great Circle Distance的公式来计算两点的确切距离。一个球体。

答案 4 :(得分:0)

根据这个link 我做了工作方法。上面的答案是错误的,因为它没有将lat / lng度转换为弧度。

    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;
    }