如何计算由经纬度指定的两点之间的距离?
为了澄清,我想用千米来表示距离;这些点使用WGS84系统,我想了解可用方法的相对准确性。
如何计算由经纬度指定的两点之间的距离?
为了澄清,我想用千米来表示距离;这些点使用WGS84系统,我想了解可用方法的相对准确性。
当前回答
function getDistanceFromLatLonInKm(position1, position2) {
"use strict";
var deg2rad = function (deg) { return deg * (Math.PI / 180); },
R = 6371,
dLat = deg2rad(position2.lat - position1.lat),
dLng = deg2rad(position2.lng - position1.lng),
a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(deg2rad(position1.lat))
* Math.cos(deg2rad(position2.lat))
* Math.sin(dLng / 2) * Math.sin(dLng / 2),
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
console.log(getDistanceFromLatLonInKm(
{lat: 48.7931459, lng: 1.9483572},
{lat: 48.827167, lng: 2.2459745}
));
其他回答
要计算球体上两点之间的距离,你需要做大圆计算。
如果你需要将距离重新投影到平面上,MapTools中有许多C/ c++库可以帮助你进行地图投影。要做到这一点,你需要不同坐标系的投影字符串。
你可能还会发现MapWindow是一个可视化点的有用工具。此外,由于它是开源的,它是如何使用project.dll库的有用指南,它似乎是核心的开源投影库。
下面是一个Scala实现:
def calculateHaversineDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double = {
val long2 = lon2 * math.Pi / 180
val lat2 = lat2 * math.Pi / 180
val long1 = lon1 * math.Pi / 180
val lat1 = lat1 * math.Pi / 180
val dlon = long2 - long1
val dlat = lat2 - lat1
val a = math.pow(math.sin(dlat / 2), 2) + math.cos(lat1) * math.cos(lat2) * math.pow(math.sin(dlon / 2), 2)
val c = 2 * math.atan2(Math.sqrt(a), math.sqrt(1 - a))
val haversineDistance = 3961 * c // 3961 = radius of earth in miles
haversineDistance
}
下面是移植到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);
}
这是一个简单的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
});
}
下面是另一个转换为Ruby代码的代码:
include Math
#Note: from/to = [lat, long]
def get_distance_in_km(from, to)
radians = lambda { |deg| deg * Math.PI / 180 }
radius = 6371 # Radius of the earth in kilometer
dLat = radians[to[0]-from[0]]
dLon = radians[to[1]-from[1]]
cosines_product = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(radians[from[0]]) * Math.cos(radians[to[1]]) * Math.sin(dLon/2) * Math.sin(dLon/2)
c = 2 * Math.atan2(Math.sqrt(cosines_product), Math.sqrt(1-cosines_product))
return radius * c # Distance in kilometer
end