Comparing version 0.1.1 to 0.1.2
@@ -1,2 +0,9 @@ | ||
* _2016-06-19_: Updated the main docs. (HEAD -> master, origin/master) [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/a171ffc59f861201b5fb9378e5b0daea43396d37">view commit</a> | ||
* _2016-06-19_: Updated version. (HEAD -> master, origin/master) [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/cfa79d01b02c84a29fc3dad8db462e98a164f5d3">view commit</a> | ||
* _2016-06-19_: Doing more testing. Also testing exception cases. [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/fc1cf8f4314777e9aef445f5be1c7a49f63b68d2">view commit</a> | ||
* _2016-06-19_: Added more input checking. [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/6addcba5556a310bbb4af54844435d4a57426093">view commit</a> | ||
* _2016-06-19_: Cleaned up unused stuff. [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/152988c4709956c30bf6a07b9457c01d734a6336">view commit</a> | ||
* _2016-06-19_: Added more docs. [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/7aa7d58c44f037efe0ea352f43634c60c775664c">view commit</a> | ||
* _2016-06-19_: Added function to check if a point is inside a polygon. [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/885004070cb0a4102712c1bd0cad79f1db59090a">view commit</a> | ||
* _2016-06-19_: Updated changelog. [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/9e7df9916cc170989d65a47a8e0cda5dad8c6b77">view commit</a> | ||
* _2016-06-19_: Updated the main docs. [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/a171ffc59f861201b5fb9378e5b0daea43396d37">view commit</a> | ||
* _2016-06-19_: Added changelog. [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/f1129dce007cdaf9cff99dcc8050186d6d58fa6c">view commit</a> | ||
@@ -3,0 +10,0 @@ * _2016-06-19_: Bumped version. [Øistein Sørensen] <a href="http://github.com/5orenso/geo-lib/commit/3db04ea427e9afdd8e64822a69275d712aaf6559">view commit</a> |
@@ -9,7 +9,3 @@ /* | ||
function MyDate(opt) { | ||
var opts = opt || {}; | ||
if (opts.debug) { | ||
console.log(opts); | ||
} | ||
function MyDate() { | ||
} | ||
@@ -16,0 +12,0 @@ |
@@ -14,11 +14,5 @@ /* | ||
* Module dealing with geo stuff. | ||
* @param {hash} opt - Constructor options. | ||
* @property {string} [config={}] The config files. | ||
* @constructor | ||
*/ | ||
function GeoLib(opt) { | ||
this.opts = opt || {}; | ||
if (this.opts.debug) { | ||
console.log(this.opts); | ||
} | ||
function GeoLib() { | ||
} | ||
@@ -54,15 +48,21 @@ | ||
* @type Object | ||
* @property {number} distance The distance value | ||
* @property {string} unit The unit for the distance | ||
* @property {number} distance The distance value | ||
* @property {string} unit The unit for the distance | ||
* @property {string} method The method used to find the distance. (haversine, vincenty) | ||
* @property {number} speedKph The speed in Km/hour | ||
* @property {number} speedMph The speed in Miles/hour | ||
* @property {string} speedMpk The speed in Minutes Per Km. | ||
* @property {number} timeUsedInSeconds Time in seconds used between points. | ||
*/ | ||
/** | ||
* Get distance between 2 geo points. | ||
* @param {object} opt - Input object. | ||
* @property {object} p1 Latitude, longitude for start point. { lat: number, lon: number}. | ||
* @property {object} p2 Latitude, longitude for destination point. { lat: number, lon: number}. | ||
* @property {string} [unit] Distance unit. | ||
* @param {object} opts Input object. | ||
* @property {object} p1 Latitude, longitude for start point. { lat: number, lon: number}. | ||
* @property {object} p2 Latitude, longitude for destination point. { lat: number, lon: number}. | ||
* @property {string} [unit] Distance unit. | ||
* @property {string} [method] Calculation method. (haversine, vincenty) | ||
* | ||
* @example | ||
* var res = geo.distance({ | ||
* let geo = require(appPath + 'lib/geo-lib'); | ||
* let res = geo.distance({ | ||
* lat1: 70.3369224, lon1: 30.3411273, | ||
@@ -77,3 +77,26 @@ * lat2: 59.8939528, lon2: 10.6450348, | ||
*/ | ||
GeoLib.prototype.distance = function(opt) { | ||
GeoLib.prototype.distance = function distance(opts) { | ||
let opt; | ||
// Check the input to see if it's in one of the allowed formats. | ||
if (Array.isArray(opts) && Array.isArray(opts[0])) { | ||
//console.log('array of array'); | ||
opt = { | ||
p1: { lat: opts[0][0], lon: opts[0][1]}, | ||
p2: { lat: opts[1][0], lon: opts[1][1]} | ||
}; | ||
} else if (Array.isArray(opts) && typeof opts[0] === 'object') { | ||
//console.log('array of objects'); | ||
opt = { | ||
p1: {lat: opts[0].lat, lon: opts[0].lon}, | ||
p2: {lat: opts[1].lat, lon: opts[1].lon} | ||
}; | ||
} else if (Array.isArray(opts) && typeof opts[0] === 'number') { | ||
//console.log('array of numbers'); | ||
opt = { | ||
p1: { lat: opts[0], lon: opts[1]}, | ||
p2: { lat: opts[2], lon: opts[3]} | ||
}; | ||
} else { | ||
opt = Object.assign({}, opts); | ||
} | ||
if (typeof opt.p1 !== 'object') { | ||
@@ -84,2 +107,3 @@ throw new TypeError('p1 is not object'); | ||
} | ||
// Start the magic. | ||
let distance; | ||
@@ -115,2 +139,73 @@ let method = 'haversine'; | ||
/* | ||
Inspired by: | ||
https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html | ||
*/ | ||
/** | ||
* @param {array} inputPolygon Input polygon. | ||
* @property {object} x Latitude for start point. | ||
* @property {object} y Longitude for destination point. | ||
* @param {object} inputPoint Input point. | ||
* | ||
* @example | ||
* let geo = require(appPath + 'lib/geo-lib'); | ||
* let result = geo.pointIsInsidePoly([ | ||
* { x: 70.403203, y: 31.055603 }, | ||
* { x: 70.364476, y: 31.089935 }, | ||
* { x: 70.361707, y: 31.107788 }, | ||
* { x: 70.363091, y: 31.132507 }, | ||
* { x: 70.367244, y: 31.140747 }, | ||
* { x: 70.375087, y: 31.154480 }, | ||
* { x: 70.379699, y: 31.172333 }, | ||
* { x: 70.387536, y: 31.179199 }, | ||
* { x: 70.397214, y: 31.164093 }, | ||
* { x: 70.403203, y: 31.129761 }, | ||
* { x: 70.405506, y: 31.100922 }, | ||
* { x: 70.405506, y: 31.062469 }, | ||
* { x: 70.403663, y: 31.056976 } | ||
* ], {x: 70.374164, y: 31.117401}); | ||
* | ||
* @returns {boolean} isInside - True or false. | ||
*/ | ||
GeoLib.prototype.pointIsInsidePoly = function pointIsInsidePoly(inputPolygon, inputPoint) { | ||
let polygon = [], | ||
point = {}; | ||
// Check if we have an array of arrays as input. If so make it an | ||
// array of objects. | ||
if (Array.isArray(inputPolygon) && Array.isArray(inputPolygon[0])) { | ||
for (let i = 0; i < inputPolygon.length; i++) { | ||
let p = { | ||
x: inputPolygon[i][0], | ||
y: inputPolygon[i][1] | ||
}; | ||
polygon.push(p); | ||
} | ||
} else { | ||
polygon = inputPolygon.slice(); | ||
} | ||
// Check if we have an array as input. If so, make it an object. | ||
if (Array.isArray(inputPoint)) { | ||
point = { | ||
x: inputPoint[0], | ||
y: inputPoint[1] | ||
}; | ||
} else { | ||
point = Object.assign({}, inputPoint); | ||
} | ||
// Start the magic. | ||
let i, | ||
nvert = polygon.length, | ||
j = nvert - 1, | ||
c = false; | ||
for (i = 0; i < nvert; j = i++) { | ||
if (((polygon[i].y > point.y) !== (polygon[j].y > point.y)) && | ||
(point.x < (polygon[j].x - polygon[i].x) * (point.y - polygon[i].y) / | ||
(polygon[j].y - polygon[i].y) + polygon[i].x)) { | ||
c = !c; | ||
//console.log(i, j, polygon[i].y, '>', point.y, c); | ||
} | ||
} | ||
return c; | ||
}; | ||
module.exports = new GeoLib(); |
@@ -212,4 +212,8 @@ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | ||
GeoVincenty.prototype.destinationPoint = function(p1, distance, initialBearing) { | ||
if (typeof p1 !== 'object') { | ||
throw new TypeError('p1 is not object'); | ||
if (typeof p1 !== 'object' || typeof p1.lat !== 'number' || typeof p1.lon !== 'number') { | ||
throw new TypeError('p1 is not object or is in wrong format. Input JSON: ', JSON.stringify(p1)); | ||
} else if (typeof distance !== 'number') { | ||
throw new TypeError('distance is not a number'); | ||
} else if (typeof initialBearing !== 'number') { | ||
throw new TypeError('initialBearing is not a number'); | ||
} | ||
@@ -236,4 +240,8 @@ return this.direct(p1, Number(distance), Number(initialBearing)).point; | ||
GeoVincenty.prototype.finalBearingOn = function(p1, distance, initialBearing) { | ||
if (typeof p1 !== 'object') { | ||
throw new TypeError('p1 is not object'); | ||
if (typeof p1 !== 'object' || typeof p1.lat !== 'number' || typeof p1.lon !== 'number') { | ||
throw new TypeError('p1 is not object or is in wrong format. Input JSON: ', JSON.stringify(p1)); | ||
} else if (typeof distance !== 'number') { | ||
throw new TypeError('distance is not a number'); | ||
} else if (typeof initialBearing !== 'number') { | ||
throw new TypeError('initialBearing is not a number'); | ||
} | ||
@@ -240,0 +248,0 @@ return this.direct(p1, Number(distance), Number(initialBearing)).finalBearing; |
{ | ||
"name": "geo-lib", | ||
"description": "A Node.js module with useful geo functions. Made with performance in mind.", | ||
"version": "0.1.1", | ||
"version": "0.1.2", | ||
"homepage": "https://github.com/5orenso/geo-lib", | ||
@@ -6,0 +6,0 @@ "repository": { |
@@ -34,2 +34,16 @@ # Geo-lib module for fast calculations of distance, speed and heading | ||
Or even in a simpler way: | ||
```javascript | ||
let geoLib = require('geo-lib'); | ||
let result = geoLib.distance([ | ||
[70.3369224, 30.3411273], | ||
[59.8939528, 10.6450348] | ||
]); | ||
// result = { | ||
// distance: 1468.28, | ||
// unit: 'km', | ||
// method: 'haversine' | ||
// } | ||
``` | ||
To find the distance and speed between 2 geo points: | ||
@@ -54,3 +68,24 @@ ```javascript | ||
To check if a point is inside a polygon: | ||
```javascript | ||
let geoLib = require('geo-lib'); | ||
let result = geoLib.pointIsInsidePoly([ | ||
[70.403203, 31.055603], | ||
[70.364476, 31.089935], | ||
[70.361707, 31.107788], | ||
[70.363091, 31.132507], | ||
[70.367244, 31.140747], | ||
[70.375087, 31.154480], | ||
[70.379699, 31.172333], | ||
[70.387536, 31.179199], | ||
[70.397214, 31.164093], | ||
[70.403203, 31.129761], | ||
[70.405506, 31.100922], | ||
[70.405506, 31.062469], | ||
[70.403663, 31.056976] | ||
], [70.374164, 31.117401]); | ||
// result = true | ||
``` | ||
---------- | ||
@@ -57,0 +92,0 @@ |
@@ -21,3 +21,3 @@ /* | ||
'Calculate distance': { | ||
'with haversine': () => { | ||
'with haversine regular object input': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
@@ -35,2 +35,41 @@ let result = myapp.distance({ | ||
'with haversine array of arrays input': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
let result = myapp.distance([ | ||
[70.3369224, 30.3411273], | ||
[59.8939528, 10.6450348] | ||
]); | ||
assert.equals(result, { | ||
distance: 1468.28, | ||
unit: 'km', | ||
method: 'haversine' | ||
}); | ||
}, | ||
'with haversine array of objects input': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
let result = myapp.distance([ | ||
{ lat: 70.3369224, lon: 30.3411273 }, | ||
{ lat: 59.8939528, lon: 10.6450348 } | ||
]); | ||
assert.equals(result, { | ||
distance: 1468.28, | ||
unit: 'km', | ||
method: 'haversine' | ||
}); | ||
}, | ||
'with haversine array of numbers input': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
let result = myapp.distance([ | ||
70.3369224, 30.3411273, | ||
59.8939528, 10.6450348 | ||
]); | ||
assert.equals(result, { | ||
distance: 1468.28, | ||
unit: 'km', | ||
method: 'haversine' | ||
}); | ||
}, | ||
'with vincenty': () => { | ||
@@ -67,4 +106,110 @@ let myapp = require(appPath + 'lib/geo-lib'); | ||
} | ||
}, | ||
'Calculate distance failures': { | ||
'with haversine failure with missing p1': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
assert.exception(function() { | ||
myapp.distance({ | ||
p2: {lat: 59.8939528, lon: 10.6450348} | ||
}); | ||
}, 'typeError'); | ||
}, | ||
'with haversine failure with missing p2': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
assert.exception(function() { | ||
myapp.distance({ | ||
p1: {lat: 59.8939528, lon: 10.6450348} | ||
}); | ||
}, 'typeError'); | ||
}, | ||
'with haversine failure with missing p1 and p2': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
assert.exception(function() { | ||
myapp.distance(); | ||
}, 'typeError'); | ||
} | ||
}, | ||
'Points and polygons': { | ||
'isPointInPoly where point is inside poly': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
let result = myapp.pointIsInsidePoly([ | ||
{ x: 70.403203, y: 31.055603 }, | ||
{ x: 70.364476, y: 31.089935 }, | ||
{ x: 70.361707, y: 31.107788 }, | ||
{ x: 70.363091, y: 31.132507 }, | ||
{ x: 70.367244, y: 31.140747 }, | ||
{ x: 70.375087, y: 31.154480 }, | ||
{ x: 70.379699, y: 31.172333 }, | ||
{ x: 70.387536, y: 31.179199 }, | ||
{ x: 70.397214, y: 31.164093 }, | ||
{ x: 70.403203, y: 31.129761 }, | ||
{ x: 70.405506, y: 31.100922 }, | ||
{ x: 70.405506, y: 31.062469 }, | ||
{ x: 70.403663, y: 31.056976 } | ||
], { x: 70.374164, y: 31.117401 }); | ||
assert.equals(result, true); | ||
}, | ||
'isPointInPoly where point is inside poly with poly as array of arrays': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
let result = myapp.pointIsInsidePoly([ | ||
[70.403203, 31.055603], | ||
[70.364476, 31.089935], | ||
[70.361707, 31.107788], | ||
[70.363091, 31.132507], | ||
[70.367244, 31.140747], | ||
[70.375087, 31.154480], | ||
[70.379699, 31.172333], | ||
[70.387536, 31.179199], | ||
[70.397214, 31.164093], | ||
[70.403203, 31.129761], | ||
[70.405506, 31.100922], | ||
[70.405506, 31.062469], | ||
[70.403663, 31.056976] | ||
], { x: 70.374164, y: 31.117401 }); | ||
assert.equals(result, true); | ||
}, | ||
'isPointInPoly where point is inside poly with point as array': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
let result = myapp.pointIsInsidePoly([ | ||
[70.403203, 31.055603], | ||
[70.364476, 31.089935], | ||
[70.361707, 31.107788], | ||
[70.363091, 31.132507], | ||
[70.367244, 31.140747], | ||
[70.375087, 31.154480], | ||
[70.379699, 31.172333], | ||
[70.387536, 31.179199], | ||
[70.397214, 31.164093], | ||
[70.403203, 31.129761], | ||
[70.405506, 31.100922], | ||
[70.405506, 31.062469], | ||
[70.403663, 31.056976] | ||
], [70.374164, 31.117401]); | ||
assert.equals(result, true); | ||
}, | ||
'isPointInPoly where point is outside poly': () => { | ||
let myapp = require(appPath + 'lib/geo-lib'); | ||
let result = myapp.pointIsInsidePoly([ | ||
{ x: 70.403203, y: 31.055603 }, | ||
{ x: 70.364476, y: 31.089935 }, | ||
{ x: 70.361707, y: 31.107788 }, | ||
{ x: 70.363091, y: 31.132507 }, | ||
{ x: 70.367244, y: 31.140747 }, | ||
{ x: 70.375087, y: 31.154480 }, | ||
{ x: 70.379699, y: 31.172333 }, | ||
{ x: 70.387536, y: 31.179199 }, | ||
{ x: 70.397214, y: 31.164093 }, | ||
{ x: 70.403203, y: 31.129761 }, | ||
{ x: 70.405506, y: 31.100922 }, | ||
{ x: 70.405506, y: 31.062469 }, | ||
{ x: 70.403663, y: 31.056976 } | ||
], {x: 59.8939528, y: 10.6450348}); | ||
assert.equals(result, false); | ||
} | ||
} | ||
}); |
@@ -65,3 +65,96 @@ /* | ||
} | ||
}, | ||
'module functions failures': { | ||
'distance between p1 and p2 in meters with missing point p2': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.distance( | ||
{ lat: 70.3369224, lon: 30.3411273 } | ||
); | ||
}, 'typeError'); | ||
}, | ||
'distance between p1 and p2 in meters with missing point p1': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.distance(); | ||
}, 'typeError'); | ||
}, | ||
'initialBearing between p1 and p2 in degrees with missing point p2': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.initialBearing( | ||
{ lat: 70.3369224, lon: 30.3411273 } | ||
); | ||
}, 'typeError'); | ||
}, | ||
'initialBearing between p1 and p2 in degrees with missing point p1': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.initialBearing(); | ||
}, 'typeError'); | ||
}, | ||
'finalBearing between p1 and p2 in degrees with missing point p2': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.finalBearing( | ||
{ lat: 70.3369224, lon: 30.3411273 } | ||
); | ||
}, 'typeError'); | ||
}, | ||
'finalBearing between p1 and p2 in degrees with missing point p1': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.finalBearing(); | ||
}, 'typeError'); | ||
}, | ||
'destinationPoint from p1 with distance and bearing with missing point p1': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.destinationPoint({}, 10000, 360); | ||
}, 'typeError'); | ||
}, | ||
'destinationPoint from p1 with distance and bearing with wrong distance': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.destinationPoint({ lat: 70.3369224, lon: 30.3411273 }, null, 360); | ||
}, 'typeError'); | ||
}, | ||
'destinationPoint from p1 with distance and bearing with wrong initialBearing': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.destinationPoint({ lat: 70.3369224, lon: 30.3411273 }, 10000, null); | ||
}, 'typeError'); | ||
}, | ||
'finalBearingOn from p1 with distance and bearing with missing point p1': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.finalBearingOn({}, 10000, 360); | ||
}, 'typeError'); | ||
}, | ||
'finalBearingOn from p1 with distance and bearing with wrong distance': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.finalBearingOn({ lat: 70.3369224, lon: 30.3411273 }, null, 360); | ||
}, 'typeError'); | ||
}, | ||
'finalBearingOn from p1 with distance and bearing with wrong initialBearing': () => { | ||
let geo = require(appPath + 'lib/geo-vincenty'); | ||
assert.exception(function() { | ||
geo.finalBearingOn({ lat: 70.3369224, lon: 30.3411273 }, 10000, null); | ||
}, 'typeError'); | ||
} | ||
} | ||
}); |
65146
1146
151
37