我使用以下算法计算两点之间的距离,但它产生了不合理的结果。我哪里错了?
private static double distFrom(double latA, double lngA, double latB, double lngB) {
double pk = 180/3.14169;
double a1 = latA / pk;
double a2 = lngA / pk;
double b1 = latB / pk;
double b2 = lngB / pk;
double t1 = Math.cos(a1)*Math.cos(a2)*Math.cos(b1)*Math.cos(b2);
double t2 = Math.cos(a1)*Math.sin(a2)*Math.cos(b1)*Math.sin(b2);
double t3 = Math.sin(a1)*Math.sin(b1);
double tt = Math.acos(t1 + t2 + t3);
return 3959*tt;
}
答案 0 :(得分:7)
使用Math.PI替换3.14169会有所改善,因为PI的第一个数字是3.141 5 9
此外,还有很多算法。尝试http://www.geodatasource.com/developers/java,它会给你一个英里,公里和海里的答案。
答案 1 :(得分:1)
更好地使用标准字母 - 经度为L,纬度为B.您使用的http://en.wikipedia.org/wiki/Great-circle_distance方法的公式很奇怪。根据维基,它将是:
double B1 = latA / pk;
double B2 = latB / pk;
double dL = (lngA-lngB) / pk;
double t1 = Math.cos(B1)*Math.cos(B2)*Math.cos(dL);
double t2 = Math.sin(B1)*Math.sin(B2);
double tt = Math.acos(t1 + t2);
减少计算 - >减少舍入错误。
但请注意,这个基于acos的公式在数学上是正确的,但不是计算上的 - 它在短距离内具有低浮点精度!在提到的page上,有更好的计算公式,基于asin用于短距离和基于atan的通用算法。选择其中一个。
答案 2 :(得分:0)
这是 http://en.wikipedia.org/wiki/Great-circle_distance 的 atan 版本(“文森蒂公式的特殊情况”)的实现,它“对所有距离都准确”:
/**
* Mean earth radius in Kilometers (KM) as defined in WGS84
*/
public static final double EARTH_RADIUS_KM = 6371.0087714;
/**
* Mean earth radius in US Miles, converted from Kilometers
*/
public static final double EARTH_RADIUS_MI = EARTH_RADIUS_KM * 0.621371192;
/**
* Mean earth radius in Nautical Miles, converted from Kilometers
*/
public static final double EARTH_RADIUS_NM = EARTH_RADIUS_KM * 0.539956803;
/**
* Calculates the distance between two points on a sphere using a "special
* case of the Vincenty formula" for accuracy. This uses more trigonometric
* calls than other formulas, but is more accurate for all distances.
* <p/>
*
* For more details, see <a href=
* "https://en.wikipedia.org/wiki/Great-circle_distance">https://en.wikipedia.org/wiki/Great-circle_distance</a>.
*
* @param startLat
* The starting point's latitude
* @param startLon
* The starting point's longitude
* @param endLat
* The ending point's latitude
* @param endLon
* The ending point's longitude
* @param radius
* The radius of the spherical earth to be used
*
* @return The distance between the points for the given radius
*/
public static double greatCircleDistance( double startLat, double startLon, double endLat, double endLon, double radius )
{
// convert to radians
double lonDelta = Math.toRadians( startLon - endLon );
double lat1 = Math.toRadians( startLat );
double lat2 = Math.toRadians( endLat );
// compute repeatedly used values
double cos1 = Math.cos( lat1 );
double sin1 = Math.sin( lat1 );
double cos2 = Math.cos( lat2 );
double sin2 = Math.sin( lat2 );
double cosDelta = Math.cos( lonDelta );
double top1 = cos2 * Math.sin( lonDelta );
top1 *= top1; // squared
double top2 = (cos1 * sin2) - (sin1 * cos2 * cosDelta);
top2 *= top2; // squared
double top = Math.sqrt( top1 + top2 );
double bottom = (sin1 * sin2) + (cos1 * cos2 * cosDelta);
double rad = Math.atan( top / bottom );
return radius * rad;
}
为地球半径选择不同的值可设置所需的单位。这适用于任何半径的任何球体,因此只要您知道起点和终点的纬度/经度,就可以使用 3389.5 公里的半径计算火星上的距离。