如何计算由经纬度指定的两点之间的距离?
为了澄清,我想用千米来表示距离;这些点使用WGS84系统,我想了解可用方法的相对准确性。
如何计算由经纬度指定的两点之间的距离?
为了澄清,我想用千米来表示距离;这些点使用WGS84系统,我想了解可用方法的相对准确性。
当前回答
这个脚本[在PHP中]计算两点之间的距离。
public static function getDistanceOfTwoPoints($source, $dest, $unit='K') {
$lat1 = $source[0];
$lon1 = $source[1];
$lat2 = $dest[0];
$lon2 = $dest[1];
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$unit = strtoupper($unit);
if ($unit == "K") {
return ($miles * 1.609344);
}
else if ($unit == "M")
{
return ($miles * 1.609344 * 1000);
}
else if ($unit == "N") {
return ($miles * 0.8684);
}
else {
return $miles;
}
}
其他回答
这是一个简单的javascript函数,从这个链接可能是有用的。不知何故相关,但我们使用谷歌地球javascript插件而不是地图
function getApproximateDistanceUnits(point1, point2) {
var xs = 0;
var ys = 0;
xs = point2.getX() - point1.getX();
xs = xs * xs;
ys = point2.getY() - point1.getY();
ys = ys * ys;
return Math.sqrt(xs + ys);
}
单位不是距离,而是相对于坐标的比率。还有其他相关的计算,你可以在这里代替getApproximateDistanceUnits函数链接
然后我使用这个函数来查看经纬度是否在半径内
function isMapPlacemarkInRadius(point1, point2, radi) {
if (point1 && point2) {
return getApproximateDistanceUnits(point1, point2) <= radi;
} else {
return 0;
}
}
点可以定义为
$$.getPoint = function(lati, longi) {
var location = {
x: 0,
y: 0,
getX: function() { return location.x; },
getY: function() { return location.y; }
};
location.x = lati;
location.y = longi;
return location;
};
然后你可以做你的事情,看看一个点是否在一个半径范围内,比如:
//put it on the map if within the range of a specified radi assuming 100,000,000 units
var iconpoint = Map.getPoint(pp.latitude, pp.longitude);
var centerpoint = Map.getPoint(Settings.CenterLatitude, Settings.CenterLongitude);
//approx ~200 units to show only half of the globe from the default center radius
if (isMapPlacemarkInRadius(centerpoint, iconpoint, 120)) {
addPlacemark(pp.latitude, pp.longitude, pp.name);
}
else {
otherSidePlacemarks.push({
latitude: pp.latitude,
longitude: pp.longitude,
name: pp.name
});
}
哈弗辛公式在大多数情况下都是很好的公式,其他答案已经包含了它所以我就不占用空间了。但重要的是要注意,无论使用什么公式(是的,不仅仅是一个)。因为可能的精度范围很大,以及所需的计算时间。公式的选择需要更多的思考,而不是简单的无脑答案。
这个帖子来自nasa的一个人,是我在讨论这些选项时发现的最好的一个
http://www.cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
例如,如果您只是在100英里半径内按距离对行进行排序。地平公式比哈弗辛公式快得多。
HalfPi = 1.5707963;
R = 3956; /* the radius gives you the measurement unit*/
a = HalfPi - latoriginrad;
b = HalfPi - latdestrad;
u = a * a + b * b;
v = - 2 * a * b * cos(longdestrad - longoriginrad);
c = sqrt(abs(u + v));
return R * c;
注意这里只有一个余弦和一个平方根。在哈弗辛公式中有9个。
下面是移植到Java的已接受的答案实现,以备任何人需要。
package com.project529.garage.util;
/**
* Mean radius.
*/
private static double EARTH_RADIUS = 6371;
/**
* Returns the distance between two sets of latitudes and longitudes in meters.
* <p/>
* Based from the following JavaScript SO answer:
* http://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula,
* which is based on https://en.wikipedia.org/wiki/Haversine_formula (error rate: ~0.55%).
*/
public double getDistanceBetween(double lat1, double lon1, double lat2, double lon2) {
double dLat = toRadians(lat2 - lat1);
double dLon = toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = EARTH_RADIUS * c;
return d;
}
public double toRadians(double degrees) {
return degrees * (Math.PI / 180);
}
下面是postgres SQL中的一个示例(以公里为单位,为英里版本,将1.609344替换为0.8684版本)
CREATE OR REPLACE FUNCTION public.geodistance(alat float, alng float, blat
float, blng float)
RETURNS float AS
$BODY$
DECLARE
v_distance float;
BEGIN
v_distance = asin( sqrt(
sin(radians(blat-alat)/2)^2
+ (
(sin(radians(blng-alng)/2)^2) *
cos(radians(alat)) *
cos(radians(blat))
)
)
) * cast('7926.3352' as float) * cast('1.609344' as float) ;
RETURN v_distance;
END
$BODY$
language plpgsql VOLATILE SECURITY DEFINER;
alter function geodistance(alat float, alng float, blat float, blng float)
owner to postgres;
FSharp版本,使用里程:
let radialDistanceHaversine location1 location2 : float =
let degreeToRadian degrees = degrees * System.Math.PI / 180.0
let earthRadius = 3959.0
let deltaLat = location2.Latitude - location1.Latitude |> degreeToRadian
let deltaLong = location2.Longitude - location1.Longitude |> degreeToRadian
let a =
(deltaLat / 2.0 |> sin) ** 2.0
+ (location1.Latitude |> degreeToRadian |> cos)
* (location2.Latitude |> degreeToRadian |> cos)
* (deltaLong / 2.0 |> sin) ** 2.0
atan2 (a |> sqrt) (1.0 - a |> sqrt)
* 2.0
* earthRadius