-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
123 lines (116 loc) · 3.98 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
var invariant = require('turf-invariant');
//http://en.wikipedia.org/wiki/Vincenty%27s_formulae
//https://gist.github.com/mathiasbynens/354587
/**
* Calculates the distance between two {@link Point|points} in degress, radians,
* miles, or kilometers. This uses the
* [Vincenty's Formulae](https://en.wikipedia.org/wiki/Vincenty%27s_formulae)
* to account for global curvature.
*
* @module turf/vincenty-inverse
* @category measurement
* @param {Feature<Point>} from origin point
* @param {Feature<Point>} to destination point
* @param {String} [units=kilometers] can be degrees, radians, miles, or kilometers
* @return {Number} distance between the two points
* @example
* var point1 = {
* "type": "Feature",
* "properties": {},
* "geometry": {
* "type": "Point",
* "coordinates": [-75.343, 39.984]
* }
* };
* var point2 = {
* "type": "Feature",
* "properties": {},
* "geometry": {
* "type": "Point",
* "coordinates": [-75.534, 39.123]
* }
* };
* var units = "miles";
*
* var points = {
* "type": "FeatureCollection",
* "features": [point1, point2]
* };
*
* //=points
*
* var distance = turf.distance(point1, point2, units);
*
* //=distance
*/
module.exports = function(point1, point2, units) {
invariant.featureOf(point1, 'Point', 'distance');
invariant.featureOf(point2, 'Point', 'distance');
var coordinates1 = point1.geometry.coordinates;
var coordinates2 = point2.geometry.coordinates;
var R;
switch (units) {
case 'miles':
R = 3960;
break;
case 'kilometers':
R = 6373;
break;
case 'degrees':
R = 57.2957795;
break;
case 'radians':
R = 1;
break;
case undefined:
R = 6373;
break;
default:
throw new Error('unknown option given to "units"');
}
var a = 6378137, // length of semi-major axis of the ellipsoid (radius at equator); (6378137.0 metres in WGS-84)
b = 6356752.3142, // length of semi-minor axis of the ellipsoid (radius at the poles); (6356752.314245 meters in WGS-84)
f = 1 / 298.257223563, // flattening of the ellipsoid; (1/298.257223563 in WGS-84)
L = toRad(coordinates2[0] - coordinates1[0]),
U1 = Math.atan((1 - f) * Math.tan(toRad(coordinates1[1]))),
U2 = Math.atan((1 - f) * Math.tan(toRad(coordinates2[1]))),
sinU1 = Math.sin(U1),
cosU1 = Math.cos(U1),
sinU2 = Math.sin(U2),
cosU2 = Math.cos(U2),
lambda = L,
lambdaP,
iterLimit = 100;
do {
var sinLambda = Math.sin(lambda),
cosLambda = Math.cos(lambda),
sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
if (0 === sinSigma) {
return 0; // co-incident points
}
var cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda,
sigma = Math.atan2(sinSigma, cosSigma),
sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma,
cosSqAlpha = 1 - sinAlpha * sinAlpha,
cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha,
C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
if (isNaN(cos2SigmaM)) {
cos2SigmaM = 0; // equatorial line: cosSqAlpha = 0 (§6)
}
lambdaP = lambda;
lambda = L + (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
} while (Math.abs(lambda - lambdaP) > 1e-12 && --iterLimit > 0);
if (!iterLimit) {
return NaN; // formula failed to converge
}
var uSq = cosSqAlpha * (a * a - b * b) / (b * b),
A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq))),
B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq))),
deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM))),
s = b * A * (sigma - deltaSigma);
distance = s * R; // unit conversion
return distance;
};
function toRad(degree) {
return degree * Math.PI / 180;
}