我有来自 GPS 的位置(lon_base,lat_base)。我有一个位置列表(lon1、lat1|lon2、lat2|lon3、lat3...)这个列表很长,遍布世界各地。
我的问题是: 1. 我如何从该列表中仅获取距离我的 lon_base\lat_base 1 英里的 lon\lat?2. 我如何从最近到最远对它们进行排序?
提前致谢!
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;
}
位置列表是包含您自己的位置类的列表,而不是 android.location.Location。
您可以使用大圆距离来计算您知道经纬度坐标的两点之间的距离。这些公式很容易编码:
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;
}
您想定义自己的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 Maps 在其 API 中的某处有一个功能可以为您执行此操作。
编辑:你会希望你的calcDistance()
函数看起来像 ChrisJ 的distance
函数。
-tjw
您可以使用 followig 近似值(因为 1 英里远小于地球的半径)来计算距您的基地的距离:
dx = cos(phi_base) * (theta - theta_base)
dy = phi - phi_base
dist = sqrt(dx*dx+dy*dy)
其中:phi
= 纬度和theta
= 经度
theta
如果和phi
以度为单位,则结果以 60 海里为单位。对于纬度与您的基本纬度相差很大的点,结果将是完全错误的,但如果您只想知道哪些点距离您的基地约 1 英里,这并不重要。
对于大多数编程语言,您必须将其转换phi_base
为弧度(乘以 pi/180)才能将其用于cos()
.
(注意:如果您的基经非常接近 180° 或 -180°,则必须特别小心,但可能并非如此 :-)
使用计算出的距离作为排序键对点进行排序。
如果您必须更精确(例如,如果您想知道距离您家大约 2000 英里的所有点),则必须使用大圆距离公式来计算球体上两点的精确距离。
根据这个链接 我制定了工作方法。上面的答案是错误的,因为它不会将纬度/经度转换为弧度。
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;
}