Skip to content

Commit 2c2468b

Browse files
authored
Merge pull request #22 from pavloDeshko/base
utils changes
2 parents eac2a4a + cac0759 commit 2c2468b

File tree

2 files changed

+74
-20
lines changed

2 files changed

+74
-20
lines changed

lib/geomUtils.js

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,20 @@ if (!Number.prototype.toRad) {
1111

1212
}
1313

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+
1428
var greatCircleRadius = {
1529
miles: 3956,
1630
km: 6367
@@ -20,11 +34,12 @@ var greatCircleRadius = {
2034
* Calculates the distance between the two points using the haversine method.
2135
* @param {number} lat1 The latitude of the first point.
2236
* @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.
2641
**/
27-
exports.calculateDistance = function(lat1, lon1, lat2, lon2) {
42+
exports.calculateDistance = function(lat1, lon1, lat2, lon2, inMiles) {
2843
var dLat = (lat2 - lat1).toRad(),
2944
dLon = (lon2 - lon1).toRad();
3045

@@ -34,26 +49,47 @@ exports.calculateDistance = function(lat1, lon1, lat2, lon2) {
3449
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
3550
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
3651
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;
3853
};
3954

4055
/**
41-
* Calcuates the midpoint between the two points passed in.
56+
* Calculates the midpoint between the two points passed in.
4257
* @param {number} lat1 The latitude of the first point.
4358
* @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.
4662
*/
4763
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();
5267
lat2 = lat2.toRad();
53-
54-
var Bx = Math.cos(lat2) * Math.cos(dLon);
68+
69+
var Bx = Math.cos(lat2) * Math.cos(dLon);
5570
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
5976
};
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+
}

tests/utils-tests.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,31 @@ module.exports = {
1111
},
1212

1313
"Should calculate the distance between two points": function(test) {
14-
var distance = geomUtils.calculateDistance(4.367, 5.6745, -40.4556, 39.34345);
15-
test.equal(distance, 6045.97811789512);
14+
var distanceInKm = geomUtils.calculateDistance(4.367, 5.6745, -40.4556, 39.34345);
15+
var distanceInMiles = geomUtils.calculateDistance(4.367, 5.6745, -40.4556, 39.34345, true);
16+
17+
test.equal(distanceInKm, 6045.97811789512);
18+
test.equal(distanceInMiles, distanceInKm/1.609453993933266 );
1619
test.done();
1720
},
1821

1922
"Should calculate the midpoint between two points" : function(test) {
20-
geomUtils.calculateMidpoint(4.367, 5.6745, -40.4556, 39.34345);
23+
var midpoint = geomUtils.calculateMidpoint(4.367, 5.6745, -40.4556, 39.34345);
24+
test.deepEqual(midpoint, [-18.78213486, 20.18113593]);
25+
test.done();
26+
},
27+
28+
"Should calculate bearing from one point to other" : function(test){
29+
var bearingWest = geomUtils.calculateBearing(0, 40, 0, 50);
30+
test.equal(bearingWest, 90);
31+
32+
var bearingNorth= geomUtils.calculateBearing(-50, -40, 50, -40);
33+
test.equal(bearingNorth, 0);
34+
35+
var bearing = geomUtils.calculateBearing(4.367, 5.6745, -40.4556, 39.34345);
36+
test.equal(bearing, 148.750703805);
37+
2138
test.done();
2239
}
2340
};
41+

0 commit comments

Comments
 (0)