函数计算两个坐标之间的距离

我目前正在使用下面的功能,它不能正常工作。根据谷歌地图,这些坐标(从59.3293371,13.487747259.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/

259793 次浏览

我以前写过一个类似的方程-测试了它,也得到了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;
}

你所使用的被称为半正矢公式,它计算球体像乌鸦一样飞上两点之间的距离。您提供的谷歌Maps链接显示距离为2.2公里,因为它不是一条直线。

Wolfram Alpha是一个很好的地理计算资源,也显示了这两点之间有1.652公里的距离。

驾车距离vs.直线距离(红线我的)。

如果您正在寻找直线距离(如crow文件),则您的函数工作正常。如果你想要的是驾驶距离(或骑自行车距离或公共交通距离或步行距离),你必须使用一个映射API (谷歌必应是最流行的)来获得适当的路线,其中将包括距离。

顺便说一句,谷歌Maps API在它的google.maps.geometry.spherical名称空间(查找computeDistanceBetween)中提供了一个用于球面距离的打包方法。这可能比你自己卷更好(首先,它使用了更精确的地球半径值)。

对于我们这些挑剔的人来说,当我说“直线距离”时,我指的是“球面上的直线”,这实际上是一条曲线(即大圆距离)。

试试这个。它在VB.net中,您需要将其转换为Javascript。此函数接受十进制分钟的参数。

    Private Function calculateDistance(ByVal long1 As String, ByVal lat1 As String, ByVal long2 As String, ByVal lat2 As String) As Double
long1 = Double.Parse(long1)
lat1 = Double.Parse(lat1)
long2 = Double.Parse(long2)
lat2 = Double.Parse(lat2)


'conversion to radian
lat1 = (lat1 * 2.0 * Math.PI) / 60.0 / 360.0
long1 = (long1 * 2.0 * Math.PI) / 60.0 / 360.0
lat2 = (lat2 * 2.0 * Math.PI) / 60.0 / 360.0
long2 = (long2 * 2.0 * Math.PI) / 60.0 / 360.0


' use to different earth axis length
Dim a As Double = 6378137.0        ' Earth Major Axis (WGS84)
Dim b As Double = 6356752.3142     ' Minor Axis
Dim f As Double = (a - b) / a        ' "Flattening"
Dim e As Double = 2.0 * f - f * f      ' "Eccentricity"


Dim beta As Double = (a / Math.Sqrt(1.0 - e * Math.Sin(lat1) * Math.Sin(lat1)))
Dim cos As Double = Math.Cos(lat1)
Dim x As Double = beta * cos * Math.Cos(long1)
Dim y As Double = beta * cos * Math.Sin(long1)
Dim z As Double = beta * (1 - e) * Math.Sin(lat1)


beta = (a / Math.Sqrt(1.0 - e * Math.Sin(lat2) * Math.Sin(lat2)))
cos = Math.Cos(lat2)
x -= (beta * cos * Math.Cos(long2))
y -= (beta * cos * Math.Sin(long2))
z -= (beta * (1 - e) * Math.Sin(lat2))


Return Math.Sqrt((x * x) + (y * y) + (z * z))
End Function

< b >编辑 javascript中的转换函数

function calculateDistance(lat1, long1, lat2, long2)
{


//radians
lat1 = (lat1 * 2.0 * Math.PI) / 60.0 / 360.0;
long1 = (long1 * 2.0 * Math.PI) / 60.0 / 360.0;
lat2 = (lat2 * 2.0 * Math.PI) / 60.0 / 360.0;
long2 = (long2 * 2.0 * Math.PI) / 60.0 / 360.0;




// use to different earth axis length
var a = 6378137.0;        // Earth Major Axis (WGS84)
var b = 6356752.3142;     // Minor Axis
var f = (a-b) / a;        // "Flattening"
var e = 2.0*f - f*f;      // "Eccentricity"


var beta = (a / Math.sqrt( 1.0 - e * Math.sin( lat1 ) * Math.sin( lat1 )));
var cos = Math.cos( lat1 );
var x = beta * cos * Math.cos( long1 );
var y = beta * cos * Math.sin( long1 );
var z = beta * ( 1 - e ) * Math.sin( lat1 );


beta = ( a / Math.sqrt( 1.0 -  e * Math.sin( lat2 ) * Math.sin( lat2 )));
cos = Math.cos( lat2 );
x -= (beta * cos * Math.cos( long2 ));
y -= (beta * cos * Math.sin( long2 ));
z -= (beta * (1 - e) * Math.sin( lat2 ));


return (Math.sqrt( (x*x) + (y*y) + (z*z) )/1000);
}

Derek的解决方案对我来说很好,我只是简单地将其转换为PHP,希望它能帮助到一些人!

function calcCrow($lat1, $lon1, $lat2, $lon2){
$R = 6371; // km
$dLat = toRad($lat2-$lat1);
$dLon = toRad($lon2-$lon1);
$lat1 = toRad($lat1);
$lat2 = toRad($lat2);


$a = sin($dLat/2) * sin($dLat/2) +sin($dLon/2) * sin($dLon/2) * cos($lat1) * cos($lat2);
$c = 2 * atan2(sqrt($a), sqrt(1-$a));
$d = $R * $c;
return $d;
}


// Converts numeric degrees to radians
function toRad($Value)
{
return $Value * pi() / 180;
}

用javascript计算两点之间的距离

function distance(lat1, lon1, lat2, lon2, unit) {
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);
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
}

有关更多详细信息,请参阅此:参考链接

我写出了求两个坐标之间距离的函数。它将返回以米为单位的距离。

 function findDistance() {
var R = 6371e3; // R is earth’s radius
var lat1 = 23.18489670753479; // starting point lat
var lat2 = 32.726601;         // ending point lat
var lon1 = 72.62524545192719; // starting point lon
var lon2 = 74.857025;         // ending point lon
var lat1radians = toRadians(lat1);
var lat2radians = toRadians(lat2);


var latRadians = toRadians(lat2-lat1);
var lonRadians = toRadians(lon2-lon1);


var a = Math.sin(latRadians/2) * Math.sin(latRadians/2) +
Math.cos(lat1radians) * Math.cos(lat2radians) *
Math.sin(lonRadians/2) * Math.sin(lonRadians/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));


var d = R * c;


console.log(d)
}


function toRadians(val){
var PI = 3.1415926535;
return val / 180.0 * PI;
}

使用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许可的。

大圆距离-从弦长开始

这里有一个应用策略设计模式的优雅解决方案;我希望它有足够的可读性。

< em > TwoPointsDistanceCalculatorStrategy.js < / em >:

module.exports = () =>


class TwoPointsDistanceCalculatorStrategy {


constructor() {}


calculateDistance({ point1Coordinates, point2Coordinates }) {}
};

< em > GreatCircleTwoPointsDistanceCalculatorStrategy.js: < / em >

module.exports = ({ TwoPointsDistanceCalculatorStrategy }) =>


class GreatCircleTwoPointsDistanceCalculatorStrategy extends TwoPointsDistanceCalculatorStrategy {


constructor() {
super();
}


/**
* Following the algorithm documented here:
* https://en.wikipedia.org/wiki/Great-circle_distance#Computational_formulas
*
* @param {object} inputs
* @param {array} inputs.point1Coordinates
* @param {array} inputs.point2Coordinates
*
* @returns {decimal} distance in kelometers
*/
calculateDistance({ point1Coordinates, point2Coordinates }) {


const convertDegreesToRadians = require('../convert-degrees-to-radians');
const EARTH_RADIUS = 6371;   // in kelometers


const [lat1 = 0, lon1 = 0] = point1Coordinates;
const [lat2 = 0, lon2 = 0] = point2Coordinates;


const radianLat1 = convertDegreesToRadians({ degrees: lat1 });
const radianLon1 = convertDegreesToRadians({ degrees: lon1 });
const radianLat2 = convertDegreesToRadians({ degrees: lat2 });
const radianLon2 = convertDegreesToRadians({ degrees: lon2 });


const centralAngle = _computeCentralAngle({
lat1: radianLat1, lon1: radianLon1,
lat2: radianLat2, lon2: radianLon2,
});


const distance = EARTH_RADIUS * centralAngle;


return distance;
}
};




/**
*
* @param {object} inputs
* @param {decimal} inputs.lat1
* @param {decimal} inputs.lon1
* @param {decimal} inputs.lat2
* @param {decimal} inputs.lon2
*
* @returns {decimal} centralAngle
*/
function _computeCentralAngle({ lat1, lon1, lat2, lon2 }) {


const chordLength = _computeChordLength({ lat1, lon1, lat2, lon2 });
const centralAngle = 2 * Math.asin(chordLength / 2);


return centralAngle;
}




/**
*
* @param {object} inputs
* @param {decimal} inputs.lat1
* @param {decimal} inputs.lon1
* @param {decimal} inputs.lat2
* @param {decimal} inputs.lon2
*
* @returns {decimal} chordLength
*/
function _computeChordLength({ lat1, lon1, lat2, lon2 }) {


const { sin, cos, pow, sqrt } = Math;


const ΔX = cos(lat2) * cos(lon2) - cos(lat1) * cos(lon1);
const ΔY = cos(lat2) * sin(lon2) - cos(lat1) * sin(lon1);
const ΔZ = sin(lat2) - sin(lat1);


const ΔXSquare = pow(ΔX, 2);
const ΔYSquare = pow(ΔY, 2);
const ΔZSquare = pow(ΔZ, 2);


const chordLength = sqrt(ΔXSquare + ΔYSquare + ΔZSquare);


return chordLength;
}

< em > convert-degrees-to-radians.js: < / em >

module.exports = function convertDegreesToRadians({ degrees }) {


return degrees * Math.PI / 180;
};

这是遵循大圆距离-从和弦长度,文档这里

访问这个地址。 https://www.movable-type.co.uk/scripts/latlong.html 你可以使用下面的代码:

JavaScript:


const R = 6371e3; // metres
const φ1 = lat1 * Math.PI/180; // φ, λ in radians
const φ2 = lat2 * Math.PI/180;
const Δφ = (lat2-lat1) * Math.PI/180;
const Δλ = (lon2-lon1) * Math.PI/180;


const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));


const d = R * c; // in metres

为Node.JS用户添加这个。你可以使用haversine-distance模块来做到这一点,这样你就不需要自己处理计算。参见更多信息请访问NPM页面

如何安装:

NPM安装——保存haversine-distance

该模块的使用方法如下:

var haversine = require("haversine-distance");


//First point in your haversine calculation
var point1 = { lat: 6.1754, lng: 106.8272 }


//Second point in your haversine calculation
var point2 = { lat: 6.1352, lng: 106.8133 }


var haversine_m = haversine(point1, point2); //Results in meters (default)
var haversine_km = haversine_m /1000; //Results in kilometers


console.log("distance (in meters): " + haversine_m + "m");
console.log("distance (in kilometers): " + haversine_km + "km");

如前所述,函数是计算到目标点的直线距离。如果你想要驾驶距离/路线,你可以使用谷歌映射距离矩阵服务:

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});
}
}
});
});
}

我在typescript和ES6中实现了这个算法

export type Coordinate = {
lat: number;
lon: number;
};

求两点之间的距离:

function getDistanceBetweenTwoPoints(cord1: Coordinate, cord2: Coordinate) {
if (cord1.lat == cord2.lat && cord1.lon == cord2.lon) {
return 0;
}


const radlat1 = (Math.PI * cord1.lat) / 180;
const radlat2 = (Math.PI * cord2.lat) / 180;


const theta = cord1.lon - cord2.lon;
const radtheta = (Math.PI * theta) / 180;


let 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;
dist = dist * 1.609344; //convert miles to km
  

return dist;
}

获取坐标数组之间的距离

export function getTotalDistance(coordinates: Coordinate[]) {
coordinates = coordinates.filter((cord) => {
if (cord.lat && cord.lon) {
return true;
}
});
  

let totalDistance = 0;


if (!coordinates) {
return 0;
}


if (coordinates.length < 2) {
return 0;
}


for (let i = 0; i < coordinates.length - 2; i++) {
if (
!coordinates[i].lon ||
!coordinates[i].lat ||
!coordinates[i + 1].lon ||
!coordinates[i + 1].lat
) {
totalDistance = totalDistance;
}
totalDistance =
totalDistance +
getDistanceBetweenTwoPoints(coordinates[i], coordinates[i + 1]);
}


return totalDistance.toFixed(2);
}


我试图通过命名变量来让代码更容易理解, 我希望这可以帮助

function getDistanceFromLatLonInKm(point1, point2) {


const [lat1, lon1] = point1;
const [lat2, lon2] = point2;
const earthRadius = 6371;
const dLat = convertDegToRad(lat2 - lat1);
const dLon = convertDegToRad(lon2 - lon1);
const squarehalfChordLength =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(convertDegToRad(lat1)) * Math.cos(convertDegToRad(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);


const angularDistance = 2 * Math.atan2(Math.sqrt(squarehalfChordLength), Math.sqrt(1 - squarehalfChordLength));
const distance = earthRadius * angularDistance;
return distance;


}

你也可以使用一个模块:

安装:

$ npm install geolib

用法:

import { getDistance } from 'geolib'


const distance = getDistance(
{ latitude: 51.5103, longitude: 7.49347 },
{ latitude: "51° 31' N", longitude: "7° 28' E" }
)


console.log(distance)

文档:https://www.npmjs.com/package/geolib

谷歌的答案

https://cloud.google.com/blog/products/maps-platform/how-calculate-distances-map-maps-javascript-api

支票由三部分组成。

https://www.distancefromto.net/

static distance({ x: x1, y: y1 }, { x: x2, y: y2 }) {
function toRadians(value) {
return value * Math.PI / 180
}


var R = 6371.0710
var rlat1 = toRadians(x1) // Convert degrees to radians
var rlat2 = toRadians(x2) // Convert degrees to radians
var difflat = rlat2 - rlat1 // Radian difference (latitudes)
var difflon = toRadians(y2 - y1) // Radian difference (longitudes)
return 2 * R * Math.asin(Math.sqrt(Math.sin(difflat / 2) * Math.sin(difflat / 2) + Math.cos(rlat1) * Math.cos(rlat2) * Math.sin(difflon / 2) * Math.sin(difflon / 2)))
}