@@ -11,6 +11,20 @@ if (!Number.prototype.toRad) {
11
11
12
12
}
13
13
14
+ if ( ! Number . prototype . toDeg ) {
15
+ Number . prototype . toDeg = function ( ) {
16
+ return this * 180 / Math . PI ;
17
+ } ;
18
+
19
+ }
20
+
21
+ if ( ! Number . prototype . roundTo ) {
22
+ Number . prototype . roundTo = function ( place ) {
23
+ var exp = Math . pow ( 10 , place ) ;
24
+ return Math . round ( this * exp ) / exp ;
25
+ } ;
26
+ }
27
+
14
28
var greatCircleRadius = {
15
29
miles : 3956 ,
16
30
km : 6367
@@ -20,11 +34,12 @@ var greatCircleRadius = {
20
34
* Calculates the distance between the two points using the haversine method.
21
35
* @param {number } lat1 The latitude of the first point.
22
36
* @param {number } lon1 The longtitude of the first point.
23
- * @param {number } lat2 The latitude of the first point.
24
- * @param {number } lon2 The longtitude of the first point.
25
- * @returns {number } The distance in miles between the two points.
37
+ * @param {number } lat2 The latitude of the second point.
38
+ * @param {number } lon2 The longtitude of the second point.
39
+ * @param {boolean } [inMiles=False] Specifies if result should be in miles.
40
+ * @returns {number } The distance in kilometers (or miles) between the two points.
26
41
**/
27
- exports . calculateDistance = function ( lat1 , lon1 , lat2 , lon2 ) {
42
+ exports . calculateDistance = function ( lat1 , lon1 , lat2 , lon2 , inMiles ) {
28
43
var dLat = ( lat2 - lat1 ) . toRad ( ) ,
29
44
dLon = ( lon2 - lon1 ) . toRad ( ) ;
30
45
@@ -34,26 +49,47 @@ exports.calculateDistance = function(lat1, lon1, lat2, lon2) {
34
49
var a = Math . sin ( dLat / 2 ) * Math . sin ( dLat / 2 ) +
35
50
Math . sin ( dLon / 2 ) * Math . sin ( dLon / 2 ) * Math . cos ( lat1 ) * Math . cos ( lat2 ) ;
36
51
var c = 2 * Math . atan2 ( Math . sqrt ( a ) , Math . sqrt ( 1 - a ) ) ;
37
- return greatCircleRadius . km * c ;
52
+ return ( inMiles ? greatCircleRadius . miles : greatCircleRadius . km ) * c ;
38
53
} ;
39
54
40
55
/**
41
- * Calcuates the midpoint between the two points passed in.
56
+ * Calculates the midpoint between the two points passed in.
42
57
* @param {number } lat1 The latitude of the first point.
43
58
* @param {number } lon1 The longtitude of the first point.
44
- * @param {number } lat2 The latitude of the first point.
45
- * @param {number } lon2 The longtitude of the first point.
59
+ * @param {number } lat2 The latitude of the second point.
60
+ * @param {number } lon2 The longtitude of the second point.
61
+ * @returns {Array<number> } An array of lat and lon values of the midpoint, rounded to 8th dec place.
46
62
*/
47
63
exports . calculateMidpoint = function ( lat1 , lon1 , lat2 , lon2 ) {
48
- var dLat = ( lat2 - lat1 ) . toRad ( ) ,
49
- dLon = ( lon2 - lon1 ) . toRad ( ) ;
50
-
51
- lat1 = lat1 . toRad ( ) ;
64
+ var dLon = ( lon2 - lon1 ) . toRad ( ) ;
65
+
66
+ lat1 = lat1 . toRad ( ) ;
52
67
lat2 = lat2 . toRad ( ) ;
53
-
54
- var Bx = Math . cos ( lat2 ) * Math . cos ( dLon ) ;
68
+
69
+ var Bx = Math . cos ( lat2 ) * Math . cos ( dLon ) ;
55
70
var By = Math . cos ( lat2 ) * Math . sin ( dLon ) ;
56
- var lat3 = Math . atan2 ( Math . sin ( lat1 ) + Math . sin ( lat2 ) ,
57
- Math . sqrt ( ( Math . cos ( lat1 ) + Bx ) * ( Math . cos ( lat1 ) + Bx ) + By * By ) ) ;
58
- var lon3 = lon1 + Math . atan2 ( By , Math . cos ( lat1 ) + Bx ) ;
71
+
72
+ var lat3 = ( Math . atan2 ( Math . sin ( lat1 ) + Math . sin ( lat2 ) ,
73
+ Math . sqrt ( ( Math . cos ( lat1 ) + Bx ) * ( Math . cos ( lat1 ) + Bx ) + By * By ) ) ) . toDeg ( ) ;
74
+ var lon3 = lon1 + Math . atan2 ( By , Math . cos ( lat1 ) + Bx ) . toDeg ( ) ;
75
+ return [ lat3 . roundTo ( 8 ) , lon3 . roundTo ( 8 ) ] ; //rounding also solves f-point precision issues
59
76
} ;
77
+
78
+ /*
79
+ Calculates bearing from the first point to the second point passed in.
80
+ * @param {number } lat1 The latitude of the first point.
81
+ * @param {number } lon1 The longtitude of the first point.
82
+ * @param {number } lat2 The latitude of the second point.
83
+ * @param {number } lon2 The longtitude of the second point.
84
+ * @returns {number } Initial compass (0 ... 360) bearing in decimal degrees.
85
+ */
86
+ exports . calculateBearing = function ( lat1 , lon1 , lat2 , lon2 ) {
87
+ var dLon = ( lon2 - lon1 ) . toRad ( ) ;
88
+
89
+ lat1 = lat1 . toRad ( ) ;
90
+ lat2 = lat2 . toRad ( ) ;
91
+
92
+ var bearing = Math . atan2 ( Math . sin ( dLon ) * Math . cos ( lat2 ) , Math . cos ( lat1 ) * Math . sin ( lat2 ) -
93
+ Math . sin ( lat1 ) * Math . cos ( lat2 ) * Math . cos ( dLon ) ) ;
94
+ return ( ( bearing . toDeg ( ) + 360 ) % 360 ) . roundTo ( 9 ) ; // converts from 180 .. -180 range
95
+ }
0 commit comments