boost-geospatial-index
Version:
A bridge to the C++ boost::geometry library, allowing to index and query geospatial shapes
193 lines (162 loc) • 5.26 kB
JavaScript
var BSI = require('bindings')('BoostSpatialIndex');
/**
* @constructor
*/
function BoostSpatialIndex() {
this.spatialIndex = new BSI.SpatialIndex();
return this;
}
/**
* Adds a bounding box shape to the index
*
* @param {string} id - bounding box identifier
* @param {Number} min_lat
* @param {Number} min_lon
* @param {Number} max_lat
* @param {Number} max_lon
* @return {boolean}
*/
BoostSpatialIndex.prototype.addBoundingBox = function addBoundingBox(id, min_lat, min_lon, max_lat, max_lon) {
if (!id || typeof id !== 'string' || id.length === 0) {
throw new Error('Invalid "id" parameter: must be a non-empty string');
}
if ([min_lat, min_lon, max_lat, max_lon].findIndex(v => typeof v !== 'number') !== -1) {
throw new Error('Invalid coordinates parameter');
}
if (min_lat >= max_lat) {
throw new Error('min_lat argument cannot be greater or equal max_lat')
}
if (min_lon >= max_lon) {
throw new Error('min_lon argument cannot be greater or equal max_lon')
}
return this.spatialIndex.addBBox(id, min_lat, min_lon, max_lat, max_lon);
}
/**
* Adds a circle shape to the index
*
* @param {string} id - circle identifier
* @param {Number} lat
* @param {Number} lon
* @param {Number} radius in meters
* @return {boolean}
*/
BoostSpatialIndex.prototype.addCircle = function addCircle(id, lat, lon, radius) {
if (!id || typeof id !== 'string' || id.length === 0) {
throw new Error('Invalid "id" parameter: must be a non-empty string');
}
if ([lat, lon, radius].findIndex(v => typeof v !== 'number') !== -1) {
throw new Error('Invalid coordinates parameter');
}
return this.spatialIndex.addCircle(id, lat, lon, radius);
}
/**
* Adds an annulus shape to the index
*
* @param {string} id - annulus identifier
* @param {Number} lat
* @param {Number} lon
* @param {Number} outerRadius in meters
* @param {Number} innerRadius in meters
* @return {boolean}
*/
BoostSpatialIndex.prototype.addAnnulus = function addAnnulus(id, lat, lon, outer, inner) {
if (!id || typeof id !== 'string' || id.length === 0) {
throw new Error('Invalid "id" parameter: must be a non-empty string');
}
if ([lat, lon, outer, inner].findIndex(v => typeof v !== 'number') !== -1) {
throw new Error('Invalid coordinates parameter');
}
if (outer <= inner) {
throw new Error('Outer radius must be strictly greater than the inner one');
}
return this.spatialIndex.addAnnulus(id, lat, lon, outer, inner);
}
/**
* Adds a polygon shape to the index
* The polygon is open (automatically closed)
*
* The "points" argument is an array of array of coordinates.
* Example:
* [[lat, lon], [lat, lon], [lat, lon], ...]
*
* @param {string} id - polygon identifier
* @param {Array<Array<Number>>} points
* @return {boolean}
*/
BoostSpatialIndex.prototype.addPolygon = function addPolygon(id, points) {
var idx;
if (!id || typeof id !== 'string' || id.length === 0) {
throw new Error('Invalid "id" parameter: must be a non-empty string');
}
if (!points || typeof points !== 'object' || !Array.isArray(points)) {
throw new Error('Invalid points arguments');
}
idx = points.findIndex(v => {
return !v ||
typeof v !== 'object' ||
!Array.isArray(v) ||
v.length !== 2 ||
v.find(coord => typeof coord !== 'number');
});
if (idx !== -1) {
throw new Error('points arguments must only contain arrays, each one being a point coordinates');
}
return this.spatialIndex.addPolygon(id, points);
}
/**
* Gets all shapes identifiers covering the provided coordinates
*
* @param {Number} lat
* @param {Number} lon
* @return {Array<string>}
*/
BoostSpatialIndex.prototype.queryPoint = function queryPoint(lat, lon) {
if (typeof lat !== 'number') {
throw new Error('Invalid lat parameter');
}
if (typeof lon !== 'number') {
throw new Error('Invalid lon parameter');
}
return this.spatialIndex.queryPoint(lat, lon);
}
/**
* Gets all shape identifiers intersecting the polygon
* created using the "points" argument
* The polygon is open (automatically closed)
*
* The "points" argument is an array of array of coordinates.
* Example:
* [[lat, lon], [lat, lon], [lat, lon], ...]
*
* @param {Array<Array<Number>>} points
* @return {Array<string>}
*/
BoostSpatialIndex.prototype.queryIntersect = function queryIntersect(points) {
if (!points || typeof points !== 'object' || !Array.isArray(points)) {
throw new Error('Invalid points arguments');
}
idx = points.findIndex(v => {
return !v ||
typeof v !== 'object' ||
!Array.isArray(v) ||
v.length !== 2 ||
v.find(coord => typeof coord !== 'number');
});
if (idx !== -1) {
throw new Error('points arguments must only contain arrays, each one being point coordinates');
}
return this.spatialIndex.queryIntersect(points);
}
/**
* Removes an id from the spatial index
*
* @param {string} id - shape identifier to remove
* @return {boolean}
*/
BoostSpatialIndex.prototype.remove = function remove(id) {
if (!id || typeof id !== 'string' || id.length === 0) {
throw new Error('Invalid id parameter');
}
return this.spatialIndex.remove(id);
}
module.exports = BoostSpatialIndex;