我目前正在使用下面的功能,它不能正常工作。根据谷歌Maps,这些坐标之间的距离(从59.3293371,13.4877472到59.3225525,13.4619422)是2.2公里,而函数返回1.6公里。我怎样才能使这个函数返回正确的距离?
function getDistanceFromLatLonInKm(lat1, lon1, lat2, lon2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}
function deg2rad(deg) {
return deg * (Math.PI/180)
}
jsFiddle: http://jsfiddle.net/edgren/gAHJB/
我以前写过一个类似的方程-测试了它,也得到了1.6 km。
你的谷歌地图显示了驾驶距离。
你的函数是按照直线距离计算的。
alert(calcCrow(59.3293371,13.4877472,59.3225525,13.4619422).toFixed(1));
//This function takes in latitude and longitude of two location and returns the distance between them as the crow flies (in km)
function calcCrow(lat1, lon1, lat2, lon2)
{
var R = 6371; // km
var dLat = toRad(lat2-lat1);
var dLon = toRad(lon2-lon1);
var lat1 = toRad(lat1);
var lat2 = toRad(lat2);
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
// Converts numeric degrees to radians
function toRad(Value)
{
return Value * Math.PI / 180;
}
使用Haversine公式,源代码:
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::: :::
//::: This routine calculates the distance between two points (given the :::
//::: latitude/longitude of those points). It is being used to calculate :::
//::: the distance between two locations using GeoDataSource (TM) prodducts :::
//::: :::
//::: Definitions: :::
//::: South latitudes are negative, east longitudes are positive :::
//::: :::
//::: Passed to function: :::
//::: lat1, lon1 = Latitude and Longitude of point 1 (in decimal degrees) :::
//::: lat2, lon2 = Latitude and Longitude of point 2 (in decimal degrees) :::
//::: unit = the unit you desire for results :::
//::: where: 'M' is statute miles (default) :::
//::: 'K' is kilometers :::
//::: 'N' is nautical miles :::
//::: :::
//::: Worldwide cities and other features databases with latitude longitude :::
//::: are available at https://www.geodatasource.com :::
//::: :::
//::: For enquiries, please contact sales@geodatasource.com :::
//::: :::
//::: Official Web site: https://www.geodatasource.com :::
//::: :::
//::: GeoDataSource.com (C) All Rights Reserved 2018 :::
//::: :::
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
function distance(lat1, lon1, lat2, lon2, unit) {
if ((lat1 == lat2) && (lon1 == lon2)) {
return 0;
}
else {
var radlat1 = Math.PI * lat1/180;
var radlat2 = Math.PI * lat2/180;
var theta = lon1-lon2;
var radtheta = Math.PI * theta/180;
var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
if (dist > 1) {
dist = 1;
}
dist = Math.acos(dist);
dist = dist * 180/Math.PI;
dist = dist * 60 * 1.1515;
if (unit=="K") { dist = dist * 1.609344 }
if (unit=="N") { dist = dist * 0.8684 }
return dist;
}
}
样例代码是根据LGPLv3许可的。
你使用的是哈弗辛公式,它计算了当乌鸦飞行时球面上两点之间的距离。您提供的谷歌Maps链接显示距离为2.2公里,因为它不是一条直线。
Wolfram Alpha是进行地理计算的一个很好的资源,它还显示了这两点之间的距离为1.652公里。
如果您正在寻找直线距离(如crow文件),则您的函数工作正常。如果你想要的是开车距离(或骑自行车距离、公共交通距离或步行距离),你必须使用一个映射API(谷歌或Bing是最流行的)来获得适当的路线,其中将包括距离。
顺便提一下,谷歌Maps API在其Google . Maps .geometry.spherical命名空间(查找computeDistanceBetween)中提供了一个打包的球面距离方法。这可能比你自己卷更好(首先,它使用了更精确的地球半径值)。
对于挑剔的我们来说,我说的“直线距离”,指的是“球面上的直线”,实际上当然是一条曲线(即大圆距离)。
如前所述,函数是计算到目标点的直线距离。如果你想要行车距离/路线,你可以使用谷歌地图距离矩阵服务:
getDrivingDistanceBetweenTwoLatLong(origin, destination) {
return new Observable(subscriber => {
let service = new google.maps.DistanceMatrixService();
service.getDistanceMatrix(
{
origins: [new google.maps.LatLng(origin.lat, origin.long)],
destinations: [new google.maps.LatLng(destination.lat, destination.long)],
travelMode: 'DRIVING'
}, (response, status) => {
if (status !== google.maps.DistanceMatrixStatus.OK) {
console.log('Error:', status);
subscriber.error({error: status, status: status});
} else {
console.log(response);
try {
let valueInMeters = response.rows[0].elements[0].distance.value;
let valueInKms = valueInMeters / 1000;
subscriber.next(valueInKms);
subscriber.complete();
}
catch(error) {
subscriber.error({error: error, status: status});
}
}
});
});
}