admin管理员组文章数量:1129027
I'm currently using the function below and it doesn't work properly. According to Google Maps, the distance between these coordinates (from 59.3293371,13.4877472
to 59.3225525,13.4619422
) are 2.2
kilometres while the function returns 1.6
kilometres. How can I make this function return the correct distance?
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: /
I'm currently using the function below and it doesn't work properly. According to Google Maps, the distance between these coordinates (from 59.3293371,13.4877472
to 59.3225525,13.4619422
) are 2.2
kilometres while the function returns 1.6
kilometres. How can I make this function return the correct distance?
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/
Share Improve this question edited Feb 12, 2019 at 1:04 Neuron 5,7935 gold badges43 silver badges62 bronze badges asked Sep 18, 2013 at 22:50 AirikrAirikr 6,43615 gold badges64 silver badges111 bronze badges 2- 3 possible duplicate of How do I calculate distance between two latitude-longitude points? – Phillip Commented May 10, 2015 at 3:53
- @Phillip Airikr's question is uniquely Javascript-specific. – lefrost Commented Aug 1, 2024 at 10:35
16 Answers
Reset to default 321What you're using is called the haversine formula, which calculates the distance between two points on a sphere as the crow flies. The Google Maps link you provided shows the distance as 2.2 km because it's not a straight line.
Wolfram Alpha is a great resource for doing geographic calculations, and also shows a distance of 1.652 km between these two points.
If you're looking for straight-line distance (as the crow files), your function is working correctly. If what you want is driving distance (or biking distance or public transportation distance or walking distance), you'll have to use a mapping API (Google or Bing being the most popular) to get the appropriate route, which will include the distance.
Incidentally, the Google Maps API provides a packaged method for spherical distance, in its google.maps.geometry.spherical
namespace (look for computeDistanceBetween
). It's probably better than rolling your own (for starters, it uses a more precise value for the Earth's radius).
For the picky among us, when I say "as the crow flies" or "straight-line distance", I'm referring to a "straight line on a sphere", which is actually a curved line (i.e. the great-circle distance), of course.
I have written a similar equation before - tested it and also got 1.6 km.
Your google maps was showing the DRIVING distance.
Your function is calculating as the crow flies (straight line distance).
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;
}
Derek's solution worked fine for me, and I've just simply converted it to PHP, hope it helps somebody out there !
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;
}
Using Haversine formula, source of the code:
//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//::: :::
//::: 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 [email protected] :::
//::: :::
//::: 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;
}
}
The sample code is licensed under LGPLv3.
Adding this for Node.JS users. You can use the haversine-distance
module to do this so you won't need to handle the calculations on your own. See the npm page for more information.
To install:
npm install --save haversine-distance
You can use the module as follows:
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");
Update: i created a npm package that implements the algorithm below: https://www.npmjs.com/package/calculate-distance-between-coordinates
I implemeneted this algorithm in typescript and ES6
export type Coordinate = {
lat: number;
lon: number;
};
get the distance between two points:
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;
}
get the distance between an array of coordinates
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);
}
Calculate the Distance between Two Points in 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
}
For more details refer this: Reference Link
You could use a module too:
Install:
$ npm install geolib
Usage:
import { getDistance } from 'geolib'
const distance = getDistance(
{ latitude: 51.5103, longitude: 7.49347 },
{ latitude: "51° 31' N", longitude: "7° 28' E" }
)
console.log(distance)
Documentation: https://www.npmjs.com/package/geolib
Try this. It is in VB.net and you need to convert it to Javascript. This function accepts parameters in decimal minutes.
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
Edit The converted function in 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);
}
I have written the function to find distance between two coordinates. It will return distance in meter.
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;
}
Visit this address. https://www.movable-type.co.uk/scripts/latlong.html You can use this code:
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
Great-circle distance - From chord length
Here's an elegant solution applying the strategy design pattern; I hope it's readable enough.
TwoPointsDistanceCalculatorStrategy.js:
module.exports = () =>
class TwoPointsDistanceCalculatorStrategy {
constructor() {}
calculateDistance({ point1Coordinates, point2Coordinates }) {}
};
GreatCircleTwoPointsDistanceCalculatorStrategy.js:
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;
}
convert-degrees-to-radians.js:
module.exports = function convertDegreesToRadians({ degrees }) {
return degrees * Math.PI / 180;
};
This's following the Great-circle distance - From chord length, documented here.
The answer from google
https://cloud.google.com/blog/products/maps-platform/how-calculate-distances-map-maps-javascript-api
And the check from three part.
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)))
}
As said before, your function is calculating a straight line distance to the destination point. If you want the driving distance/route, you can use Google Maps Distance Matrix Service:
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});
}
}
});
});
}
I try to make the code a little bit understandable by naming the variables, I hope this can help
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;
}
Using the haversine-distance
library:
import haversine from 'haversine-distance';
const a = { lat: 59.3293371, lon: 13.4877472 }
const b = { lat: 59.3225525, lon: 13.4619422 }
console.log(haversine(a, b)); // 1648.6380822066644 (in meters)
本文标签: javascriptFunction to calculate distance between two coordinatesStack Overflow
版权声明:本文标题:javascript - Function to calculate distance between two coordinates - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736706262a1948693.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论