Reputation: 16233
Given a defined (lat, lon)
geo-point I'm trying to find in which polygon this point lies in. I suppose iterating over all the polygons is not efficient. Is there available any function or library for NodeJS that does this?
const polygon = getPolygonFromPoint(FeatureCollection, x, y);
There are no overlapping polygons, actually I'm using this to detect in which district of a certain country a defined GPS coordinates point lies in.
Upvotes: 3
Views: 2970
Reputation: 19319
For a simple point in polygon test you can check turf
which has a booleanPointInPolygon
. Turf works in node but you should check for differences between v5 and v6+ around how to use npm accordingly. Points should be long/ lat (not lat/ long) and the polygon can be easily pulled out of the feature geometry of your feature collection.
For a more complex use case where you have many points and many polygons within which to locate them you should consider using rbush
.
Note that the rbush library constructs an r-tree out of the bounding boxes of the polygons and not the polygons themselves, so use of an r-tree is just a way to vastly reduce the number of polygons you need to test with booleanPointInPolygon
.
Example code for rbush
:
const RBush = require("rbush");
const turfBbox = require("@turf/bbox").default;
const geo = {} // your feature collection...
const maxEntriesPerNode = 50; // check the doco
const tree = new RBush(maxEntriesPerNode);
const bbox2Object = (keys, bbox) => ["minX", "minY", "maxX", "maxY"].reduce((o, k, i) => ({...o, [k]: bbox[i]}), {})
// create rtree from feature collection
geo.features.forEach(feature => {
const leaf = bbox2Object(bboxKeys, turfBbox(feature)); // use bbox of feature
leaf["id"] = feature.properties.SOME_ID; // add some custom properties
tree.insert(leaf);
});
// test a random point from your data
const [x, y] = [123, 456]; // should be long, lat
const test = tree.search({minX: x, minY: y, maxX: x, maxY: y});
// test should have an array of leaves per the tree.insert above
You can then perform the booleanPointInPolygon
test on this reduced set of polygons.
Upvotes: 4
Reputation: 16233
I implemented that with the library polygon-lookup
const PolygonLookup = require('polygon-lookup')
const featureCollection = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
properties: { id: 'bar' },
geometry: {
type: 'Polygon',
coordinates: [ [ [ 0, 1 ], [ 2, 1 ], [ 3, 4 ], [ 1, 5 ] ] ]
}
}]
}
var lookup = new PolygonLookup(featureCollection)
var poly = lookup.search(1, 2)
console.log(poly.properties.id) // bar
Upvotes: 2