Skip to content

Commit

Permalink
Merge pull request #6 from kuzzleio/1.1.0-proposal
Browse files Browse the repository at this point in the history
# [1.1.0](https://github.com/kuzzleio/boost-geospatial-index/releases/tag/1.1.0) (2020-08-06)


#### New features

- [ [#5](#5) ] New "queryIntersect" method, allowing to retrieve shapes matching a given polygon   ([aswinsreedhar](https://github.com/aswinsreedhar))
---
  • Loading branch information
scottinet committed Aug 6, 2020
2 parents 25f6199 + 9b2a8c7 commit 88481b0
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 2 deletions.
22 changes: 22 additions & 0 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This library is used by [Kuzzle](http://kuzzle.io)'s real-time engine and is foc
- [addPolygon(id, points)](#addpolygonid-points)
- [Querying the index](#querying-the-index)
- [queryPoint(lat, lon)](#querypointlat-lon)
- [queryIntersect(points)](#queryintersecpoints)
- [Removing a shape from the index](#removing-a-shape-from-the-index)
- [remove(id)](#removeid)
- [Example](#example)
Expand Down Expand Up @@ -110,6 +111,18 @@ If no shape match, an empty array is returned.
| `lat` | number | y coordinate |
| `lon` | number | x coordinate |

##### queryIntersect(points)

Gets all shapes intersecting the polygon created from the list of point coordinates provided. Shapes partially covered by the polygon also returned.

If no shape match, an empty array is returned.

**Returns:** `array of shape ids`

| Argument | Type | Description |
|----------|------|-------------|
| `points` | array | array of arrays of [lat, lon] points |

# Removing a shape from the index

##### remove(id)
Expand Down Expand Up @@ -144,13 +157,22 @@ bsi.addCircle('Montpellier Airport', 43.5764455, 3.948711, 2000);

console.log('Querying Kuzzle HQ: ', bsi.queryPoint(43.6073913, 3.9109057));
console.log('Kuzzle team favorite pub:', bsi.queryPoint(43.6002203, 3.897105));
console.log('Hangout spots:', bsi.queryIntersect([
[43.6072203, 3.9],
[43.607,5.900],
[44.609000, 5.90000],
[44.605,3.9]
]));
```

Result:

```
Querying Kuzzle HQ: [ 'Montpellier, France', 'Montpellier Millenaire' ]
Kuzzle team favorite pub: [ 'Montpellier, France', 'Around Kuzzle HQ' ]
Hangout spots: [ 'Montpellier, France',
'Montpellier Millenaire',
'Around Kuzzle HQ' ]
```

# TODO
Expand Down
33 changes: 33 additions & 0 deletions index.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,39 @@ BoostSpatialIndex.prototype.queryPoint = function queryPoint(lat, lon) {
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
*
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "boost-geospatial-index",
"main": "index.js",
"version": "1.0.5",
"version": "1.1.0",
"author": "The Kuzzle Team <support@kuzzle.io>",
"description": "A bridge to the C++ boost::geometry library, allowing to index and query geospatial shapes",
"keywords": [
Expand Down
46 changes: 46 additions & 0 deletions src/spatialIndex.cc
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ NAN_MODULE_INIT(SpatialIndex::init) {
Nan::SetPrototypeMethod(tpl, "addAnnulus", addAnnulus);
Nan::SetPrototypeMethod(tpl, "addPolygon", addPolygon);
Nan::SetPrototypeMethod(tpl, "queryPoint", queryPoint);
Nan::SetPrototypeMethod(tpl, "queryIntersect", queryIntersect);
Nan::SetPrototypeMethod(tpl, "remove", remove);

constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
Expand Down Expand Up @@ -225,6 +226,51 @@ NAN_METHOD(SpatialIndex::queryPoint) {
info.GetReturnValue().Set(result);
}

/*
* Gets all ids embedding the provided point coordinates
* queryIntersect([[lat, lon], [lat, lon], [lat, lon], ...]])
*
* Returns an array of matching ids as strings
*/
NAN_METHOD(SpatialIndex::queryIntersect) {
Nan::HandleScope scope;
SpatialIndex *spi = Nan::ObjectWrap::Unwrap<SpatialIndex>(info.This());

v8::Local<v8::Array> result = Nan::New<v8::Array>();

// Checks the coordinates parameters validity
if (info[0]->IsUndefined() || !info[0]->IsArray()) {
info.GetReturnValue().Set(result);
return;
}

v8::Local<v8::Array> points = info[0].As<v8::Array>();
polygon queryPoly;

// note: flip coordinates from lat,long to long,lat to abide by boost
v8::Local<v8::Context> context = info.GetIsolate()->GetCurrentContext();
for(unsigned int i = 0; i < points->Length(); i++) {
v8::Local<v8::Array> p = points->Get(context, i)
.ToLocalChecked()
.As<v8::Array>();

queryPoly.outer().push_back(
point(
Nan::To<double>(p->Get(context, 1).ToLocalChecked()).FromJust(),
Nan::To<double>(p->Get(context, 0).ToLocalChecked()).FromJust()));
}

std::vector<treeValue> found;
//calling intersects here, pure inside polygon check would be covered_by
spi->rtree.query(bgi::intersects(queryPoly), std::back_inserter(found));

for(std::vector<treeValue>::iterator it = found.begin(); it != found.end(); ++it) {
Nan::Set(result, result->Length(), Nan::New(it->second->getId()).ToLocalChecked());
}

info.GetReturnValue().Set(result);
}

/*
* Removes an object from the index
* remove(id)
Expand Down
3 changes: 3 additions & 0 deletions src/spatialIndex.hpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <string>
#include <boost/geometry.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include "shape.hpp"

typedef std::pair<box, std::shared_ptr<Shape>> treeValue;
Expand Down Expand Up @@ -41,6 +43,7 @@ class SpatialIndex : public Nan::ObjectWrap {
static NAN_METHOD(addAnnulus);
static NAN_METHOD(addPolygon);
static NAN_METHOD(queryPoint);
static NAN_METHOD(queryIntersect);
static NAN_METHOD(remove);


Expand Down

0 comments on commit 88481b0

Please sign in to comment.