diff --git a/packages/turf-geojson-rbush/LICENSE b/packages/turf-geojson-rbush/LICENSE new file mode 100644 index 0000000000..96ce51b76f --- /dev/null +++ b/packages/turf-geojson-rbush/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2017 TurfJS + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/turf-geojson-rbush/README.md b/packages/turf-geojson-rbush/README.md new file mode 100644 index 0000000000..2c843d9289 --- /dev/null +++ b/packages/turf-geojson-rbush/README.md @@ -0,0 +1,211 @@ +# GeoJSON RBush used in TurfJS + +[![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/DenisCarriere/geojson-rbush/master/LICENSE) + +GeoJSON implementation of [RBush](https://github.com/mourner/rbush) — a high-performance JavaScript R-tree-based 2D spatial index for points and rectangles. + +## Install + +**npm** + +```bash +$ npm install --save geojson-rbush +``` + +## API + + + +#### Table of Contents + +- [rbush](#rbush) +- [insert](#insert) +- [load](#load) +- [remove](#remove) +- [clear](#clear) +- [search](#search) +- [collides](#collides) +- [all](#all) +- [toJSON](#tojson) +- [fromJSON](#fromjson) + +### rbush + +GeoJSON implementation of [RBush](https://github.com/mourner/rbush#rbush) spatial index. + +**Parameters** + +- `maxEntries` **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** defines the maximum number of entries in a tree node. 9 (used by default) is a + reasonable choice for most applications. Higher value means faster insertion and slower search, and vice versa. (optional, default `9`) + +**Examples** + +```javascript +var geojsonRbush = require('geojson-rbush').default; +var tree = geojsonRbush(); +``` + +Returns **RBush** GeoJSON RBush + +### insert + +[insert](https://github.com/mourner/rbush#data-format) + +**Parameters** + +- `feature` **Feature** insert single GeoJSON Feature + +**Examples** + +```javascript +var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]); +tree.insert(poly) +``` + +Returns **RBush** GeoJSON RBush + +### load + +[load](https://github.com/mourner/rbush#bulk-inserting-data) + +**Parameters** + +- `features` **(FeatureCollection | [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<Feature>)** load entire GeoJSON FeatureCollection + +**Examples** + +```javascript +var polys = turf.polygons([ + [[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]], + [[[-93, 32], [-83, 32], [-83, 39], [-93, 39], [-93, 32]]] +]); +tree.load(polys); +``` + +Returns **RBush** GeoJSON RBush + +### remove + +[remove](https://github.com/mourner/rbush#removing-data) + +**Parameters** + +- `feature` **Feature** remove single GeoJSON Feature +- `equals` **[Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** Pass a custom equals function to compare by value for removal. + +**Examples** + +```javascript +var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]); + +tree.remove(poly); +``` + +Returns **RBush** GeoJSON RBush + +### clear + +[clear](https://github.com/mourner/rbush#removing-data) + +**Examples** + +```javascript +tree.clear() +``` + +Returns **RBush** GeoJSON Rbush + +### search + +[search](https://github.com/mourner/rbush#search) + +**Parameters** + +- `geojson` **(BBox | FeatureCollection | Feature)** search with GeoJSON + +**Examples** + +```javascript +var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]); + +tree.search(poly); +``` + +Returns **FeatureCollection** all features that intersects with the given GeoJSON. + +### collides + +[collides](https://github.com/mourner/rbush#collisions) + +**Parameters** + +- `geojson` **(BBox | FeatureCollection | Feature)** collides with GeoJSON + +**Examples** + +```javascript +var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]); + +tree.collides(poly); +``` + +Returns **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** true if there are any items intersecting the given GeoJSON, otherwise false. + +### all + +[all](https://github.com/mourner/rbush#search) + +**Examples** + +```javascript +tree.all() +``` + +Returns **FeatureCollection** all the features in RBush + +### toJSON + +[toJSON](https://github.com/mourner/rbush#export-and-import) + +**Examples** + +```javascript +var exported = tree.toJSON() +``` + +Returns **any** export data as JSON object + +### fromJSON + +[fromJSON](https://github.com/mourner/rbush#export-and-import) + +**Parameters** + +- `json` **any** import previously exported data + +**Examples** + +```javascript +var exported = { + "children": [ + { + "type": "Feature", + "geometry": { + "type": "Point", + "coordinates": [110, 50] + }, + "properties": {}, + "bbox": [110, 50, 110, 50] + } + ], + "height": 1, + "leaf": true, + "minX": 110, + "minY": 50, + "maxX": 110, + "maxY": 50 +} +tree.fromJSON(exported) +``` + +Returns **RBush** GeoJSON RBush diff --git a/packages/turf-geojson-rbush/bench.js b/packages/turf-geojson-rbush/bench.js new file mode 100644 index 0000000000..51d932f1a6 --- /dev/null +++ b/packages/turf-geojson-rbush/bench.js @@ -0,0 +1,38 @@ +const Benchmark = require("benchmark"); +const { randomPoint, randomPolygon } = require("@turf/random"); +const geojsonRbush = require("./").default; + +// Fixtures +const points = randomPoint(3); +const point = points.features[0]; +const polygons = randomPolygon(3); +const polygon = polygons.features[0]; + +// Load trees before (used to benchmark search) +const pointsTree = geojsonRbush(); +pointsTree.load(points); +const polygonsTree = geojsonRbush(); +polygonsTree.load(polygons); + +/** + * Benchmark Results + * + * rbush.points x 313,979 ops/sec ±10.60% (67 runs sampled) + * rbush.polygons x 428,333 ops/sec ±1.69% (70 runs sampled) + * search.points x 5,986,675 ops/sec ±7.95% (77 runs sampled) + * search.polygons x 6,481,248 ops/sec ±0.93% (90 runs sampled) + */ +new Benchmark.Suite("geojson-rbush") + .add("rbush.points", () => { + const tree = geojsonRbush(); + tree.load(points); + }) + .add("rbush.polygons", () => { + const tree = geojsonRbush(); + tree.load(polygons); + }) + .add("search.points", () => pointsTree.search(point)) + .add("search.polygons", () => polygonsTree.search(polygon)) + .on("cycle", (e) => console.log(String(e.target))) + .on("complete", () => {}) + .run(); diff --git a/packages/turf-geojson-rbush/index.d.ts b/packages/turf-geojson-rbush/index.d.ts new file mode 100644 index 0000000000..42fc43a075 --- /dev/null +++ b/packages/turf-geojson-rbush/index.d.ts @@ -0,0 +1,30 @@ +import { + BBox, + Feature, + FeatureCollection, + Geometry, + GeoJsonProperties, +} from "geojson"; + +declare class RBush { + insert(feature: Feature): RBush; + load(features: FeatureCollection | Feature[]): RBush; + remove( + feature: Feature, + equals?: (a: Feature, b: Feature) => boolean + ): RBush; + clear(): RBush; + search(geojson: Feature | FeatureCollection | BBox): FeatureCollection; + all(): FeatureCollection; + collides(geosjon: Feature | FeatureCollection | BBox): boolean; + toJSON(): any; + fromJSON(data: any): RBush; +} + +/** + * https://github.com/mourner/rbush + */ +export default function rbush< + G extends Geometry = Geometry, + P extends GeoJsonProperties = GeoJsonProperties, +>(maxEntries?: number): RBush; diff --git a/packages/turf-geojson-rbush/index.js b/packages/turf-geojson-rbush/index.js new file mode 100644 index 0000000000..359f397b67 --- /dev/null +++ b/packages/turf-geojson-rbush/index.js @@ -0,0 +1,219 @@ +import rbush from "rbush"; +import { featureCollection } from "@turf/helpers"; +import { featureEach } from "@turf/meta"; +import turfBBox from "@turf/bbox"; + +/** + * @module rbush + */ + +/** + * GeoJSON implementation of [RBush](https://github.com/mourner/rbush#rbush) spatial index. + * + * @name rbush + * @param {number} [maxEntries=9] defines the maximum number of entries in a tree node. 9 (used by default) is a + * reasonable choice for most applications. Higher value means faster insertion and slower search, and vice versa. + * @returns {RBush} GeoJSON RBush + * @example + * var geojsonRbush = require('geojson-rbush').default; + * var tree = geojsonRbush(); + */ +function geojsonRbush(maxEntries) { + var tree = new rbush(maxEntries); + + /** + * [insert](https://github.com/mourner/rbush#data-format) + * + * @memberof rbush + * @param {Feature} feature insert single GeoJSON Feature + * @returns {RBush} GeoJSON RBush + * @example + * var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]); + * tree.insert(poly) + */ + tree.insert = function (feature) { + if (feature.type !== "Feature") throw new Error("invalid feature"); + feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature); + return rbush.prototype.insert.call(this, feature); + }; + + /** + * [load](https://github.com/mourner/rbush#bulk-inserting-data) + * + * @memberof rbush + * @param {FeatureCollection|Array} features load entire GeoJSON FeatureCollection + * @returns {RBush} GeoJSON RBush + * @example + * var polys = turf.polygons([ + * [[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]], + * [[[-93, 32], [-83, 32], [-83, 39], [-93, 39], [-93, 32]]] + * ]); + * tree.load(polys); + */ + tree.load = function (features) { + var load = []; + // Load an Array of Features + if (Array.isArray(features)) { + features.forEach(function (feature) { + if (feature.type !== "Feature") throw new Error("invalid features"); + feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature); + load.push(feature); + }); + } else { + // Load a FeatureCollection + featureEach(features, function (feature) { + if (feature.type !== "Feature") throw new Error("invalid features"); + feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature); + load.push(feature); + }); + } + return rbush.prototype.load.call(this, load); + }; + + /** + * [remove](https://github.com/mourner/rbush#removing-data) + * + * @memberof rbush + * @param {Feature} feature remove single GeoJSON Feature + * @param {Function} equals Pass a custom equals function to compare by value for removal. + * @returns {RBush} GeoJSON RBush + * @example + * var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]); + * + * tree.remove(poly); + */ + tree.remove = function (feature, equals) { + if (feature.type !== "Feature") throw new Error("invalid feature"); + feature.bbox = feature.bbox ? feature.bbox : turfBBox(feature); + return rbush.prototype.remove.call(this, feature, equals); + }; + + /** + * [clear](https://github.com/mourner/rbush#removing-data) + * + * @memberof rbush + * @returns {RBush} GeoJSON Rbush + * @example + * tree.clear() + */ + tree.clear = function () { + return rbush.prototype.clear.call(this); + }; + + /** + * [search](https://github.com/mourner/rbush#search) + * + * @memberof rbush + * @param {BBox|FeatureCollection|Feature} geojson search with GeoJSON + * @returns {FeatureCollection} all features that intersects with the given GeoJSON. + * @example + * var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]); + * + * tree.search(poly); + */ + tree.search = function (geojson) { + var features = rbush.prototype.search.call(this, this.toBBox(geojson)); + return featureCollection(features); + }; + + /** + * [collides](https://github.com/mourner/rbush#collisions) + * + * @memberof rbush + * @param {BBox|FeatureCollection|Feature} geojson collides with GeoJSON + * @returns {boolean} true if there are any items intersecting the given GeoJSON, otherwise false. + * @example + * var poly = turf.polygon([[[-78, 41], [-67, 41], [-67, 48], [-78, 48], [-78, 41]]]); + * + * tree.collides(poly); + */ + tree.collides = function (geojson) { + return rbush.prototype.collides.call(this, this.toBBox(geojson)); + }; + + /** + * [all](https://github.com/mourner/rbush#search) + * + * @memberof rbush + * @returns {FeatureCollection} all the features in RBush + * @example + * tree.all() + */ + tree.all = function () { + var features = rbush.prototype.all.call(this); + return featureCollection(features); + }; + + /** + * [toJSON](https://github.com/mourner/rbush#export-and-import) + * + * @memberof rbush + * @returns {any} export data as JSON object + * @example + * var exported = tree.toJSON() + */ + tree.toJSON = function () { + return rbush.prototype.toJSON.call(this); + }; + + /** + * [fromJSON](https://github.com/mourner/rbush#export-and-import) + * + * @memberof rbush + * @param {any} json import previously exported data + * @returns {RBush} GeoJSON RBush + * @example + * var exported = { + * "children": [ + * { + * "type": "Feature", + * "geometry": { + * "type": "Point", + * "coordinates": [110, 50] + * }, + * "properties": {}, + * "bbox": [110, 50, 110, 50] + * } + * ], + * "height": 1, + * "leaf": true, + * "minX": 110, + * "minY": 50, + * "maxX": 110, + * "maxY": 50 + * } + * tree.fromJSON(exported) + */ + tree.fromJSON = function (json) { + return rbush.prototype.fromJSON.call(this, json); + }; + + /** + * Converts GeoJSON to {minX, minY, maxX, maxY} schema + * + * @memberof rbush + * @private + * @param {BBox|FeatureCollection|Feature} geojson feature(s) to retrieve BBox from + * @returns {Object} converted to {minX, minY, maxX, maxY} + */ + tree.toBBox = function (geojson) { + var bbox; + if (geojson.bbox) bbox = geojson.bbox; + else if (Array.isArray(geojson) && geojson.length === 4) bbox = geojson; + else if (Array.isArray(geojson) && geojson.length === 6) + bbox = [geojson[0], geojson[1], geojson[3], geojson[4]]; + else if (geojson.type === "Feature") bbox = turfBBox(geojson); + else if (geojson.type === "FeatureCollection") bbox = turfBBox(geojson); + else throw new Error("invalid geojson"); + + return { + minX: bbox[0], + minY: bbox[1], + maxX: bbox[2], + maxY: bbox[3], + }; + }; + return tree; +} + +export default geojsonRbush; diff --git a/packages/turf-geojson-rbush/package.json b/packages/turf-geojson-rbush/package.json new file mode 100644 index 0000000000..504f901e77 --- /dev/null +++ b/packages/turf-geojson-rbush/package.json @@ -0,0 +1,74 @@ +{ + "name": "@turf/geojson-rbush", + "version": "7.0.0-alpha.2", + "description": "GeoJSON implementation of RBush", + "author": "Turf Authors", + "contributors": [ + "Vladimir Agafonkin <@mourner>", + "Denis Carriere <@DenisCarriere>", + "Jordan Rousseau <@jvrousseau>" + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/Turfjs/turf/issues" + }, + "homepage": "https://github.com/Turfjs/turf", + "repository": { + "type": "git", + "url": "git://github.com/Turfjs/turf.git" + }, + "funding": "https://opencollective.com/turf", + "publishConfig": { + "access": "public" + }, + "keywords": [ + "geojson", + "index", + "tree", + "spatial", + "rbush" + ], + "main": "dist/js/index.js", + "module": "dist/es/index.js", + "exports": { + "./package.json": "./package.json", + ".": { + "types": "./index.d.ts", + "import": "./dist/es/index.js", + "require": "./dist/js/index.js" + } + }, + "types": "index.d.ts", + "sideEffects": false, + "files": [ + "dist", + "index.d.ts" + ], + "scripts": { + "bench": "tsx bench.js", + "build": "rollup -c ../../rollup.config.js && echo '{\"type\":\"module\"}' > dist/es/package.json", + "docs": "tsx ../../scripts/generate-readmes", + "test": "npm-run-all --npm-path npm test:*", + "test:tape": "tsx test.js", + "test:types": "tsc --esModuleInterop --noEmit --strict types.ts" + }, + "devDependencies": { + "@turf/bbox-polygon": "^7.0.0-alpha.2", + "@turf/random": "^7.0.0-alpha.2", + "benchmark": "*", + "load-json-file": "*", + "npm-run-all": "*", + "rollup": "*", + "tape": "*", + "tsx": "*", + "typescript": "*", + "write-json-file": "*" + }, + "dependencies": { + "@turf/bbox": "^7.0.0-alpha.2", + "@turf/helpers": "^7.0.0-alpha.2", + "@turf/meta": "^7.0.0-alpha.2", + "@types/geojson": "7946.0.8", + "rbush": "^3.0.1" + } +} diff --git a/packages/turf-geojson-rbush/test.js b/packages/turf-geojson-rbush/test.js new file mode 100644 index 0000000000..83da5f0bc8 --- /dev/null +++ b/packages/turf-geojson-rbush/test.js @@ -0,0 +1,119 @@ +const fs = require("fs"); +const test = require("tape"); +const path = require("path"); +const load = require("load-json-file"); +const write = require("write-json-file"); +const bboxPolygon = require("@turf/bbox-polygon").default; +const { featureCollection, polygons } = require("@turf/helpers"); +const geojsonRbush = require("./").default; + +const directories = { + in: path.join(__dirname, "test", "in") + path.sep, + out: path.join(__dirname, "test", "out") + path.sep, +}; + +const fixtures = fs.readdirSync(directories.in).map((filename) => { + return { + filename, + name: path.parse(filename).name, + geojson: load.sync(directories.in + filename), + }; +}); + +test("geojson-rbush", (t) => { + for (const fixture of fixtures) { + const name = fixture.name; + const filename = fixture.filename; + const geojson = fixture.geojson; + const tree = geojsonRbush(); + tree.load(geojson); + + // Retrive all features inside the RBush index + const all = tree.all(); + + // Search using the first item in the FeatureCollection + const search = tree.search(geojson.features[0]); + + if (process.env.REGEN) { + write.sync(directories.out + "all." + filename, all); + write.sync(directories.out + "search." + filename, search); + } + + t.deepEqual( + all, + load.sync(directories.out + "all." + filename), + "all." + name + ); + t.deepEqual( + search, + load.sync(directories.out + "search." + filename), + "search." + name + ); + } + t.end(); +}); + +test("geojson-rbush -- bbox", (t) => { + const tree = geojsonRbush(); + tree.insert(bboxPolygon([-150, -60, 150, 60])); + + t.equal(tree.collides([-140, -50, 140, 50]), true); + t.equal(tree.search([-140, -50, 140, 50]).features.length, 1); + t.equal(tree.search(bboxPolygon([-150, -60, 150, 60])).features.length, 1); + t.equal( + tree.search(featureCollection([bboxPolygon([-150, -60, 150, 60])])).features + .length, + 1 + ); + t.equal(tree.collides([-180, -80, -170, -60]), false); + + // Errors + t.throws(() => tree.search("foo")); + t.end(); +}); + +test("geojson-rbush -- fromJSON", (t) => { + const tree = geojsonRbush(); + const poly = bboxPolygon([-150, -60, 150, 60]); + tree.insert(poly); + + const newTree = geojsonRbush(); + newTree.fromJSON(tree.toJSON()); + t.equal(newTree.all().features.length, 1); + newTree.remove(poly); + t.equal(newTree.all().features.length, 0); + t.end(); +}); + +test("geojson-rbush -- Array of Features -- Issue #5", (t) => { + // https://github.com/DenisCarriere/geojson-rbush/issues/5 + const tree = geojsonRbush(); + const polys = polygons([ + [ + [ + [-78, 41], + [-67, 41], + [-67, 48], + [-78, 48], + [-78, 41], + ], + ], + [ + [ + [-93, 32], + [-83, 32], + [-83, 39], + [-93, 39], + [-93, 32], + ], + ], + ]); + // Load Feature Collection + tree.load(polys); + t.equal(tree.all().features.length, 2); + + // Load Array of Features + tree.load(polys.features); + t.equal(tree.all().features.length, 4); + t.end(); +}); diff --git a/packages/turf-geojson-rbush/test/in/linestrings.geojson b/packages/turf-geojson-rbush/test/in/linestrings.geojson new file mode 100644 index 0000000000..2f2a0a9e5d --- /dev/null +++ b/packages/turf-geojson-rbush/test/in/linestrings.geojson @@ -0,0 +1,89 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -121.9921875, + 41.77131167976407 + ], + [ + -112.1484375, + 49.15296965617042 + ], + [ + -95.2734375, + 49.15296965617042 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -101.953125, + 34.016241889667015 + ], + [ + -88.9453125, + 40.17887331434696 + ], + [ + -78.046875, + 50.064191736659104 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -108.6328125, + 42.032974332441405 + ], + [ + -102.65625, + 39.36827914916014 + ], + [ + -95.97656249999999, + 39.36827914916014 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -71.71875, + 39.842286020743394 + ], + [ + -69.169921875, + 35.96022296929667 + ], + [ + -66.796875, + 31.952162238024975 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-geojson-rbush/test/in/points.geojson b/packages/turf-geojson-rbush/test/in/points.geojson new file mode 100644 index 0000000000..55a2882a8f --- /dev/null +++ b/packages/turf-geojson-rbush/test/in/points.geojson @@ -0,0 +1,38 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -86.8359375, + 42.8115217450979 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -67.5, + 48.69096039092549 + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -106.171875, + 46.800059446787316 + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-geojson-rbush/test/in/polygons.geojson b/packages/turf-geojson-rbush/test/in/polygons.geojson new file mode 100644 index 0000000000..451fd16d21 --- /dev/null +++ b/packages/turf-geojson-rbush/test/in/polygons.geojson @@ -0,0 +1,129 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -78, + 41 + ], + [ + -67, + 41 + ], + [ + -67, + 48 + ], + [ + -78, + 48 + ], + [ + -78, + 41 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -93, + 32 + ], + [ + -83, + 32 + ], + [ + -83, + 39 + ], + [ + -93, + 39 + ], + [ + -93, + 32 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -97.646484375, + 43.197167282501276 + ], + [ + -88.681640625, + 43.197167282501276 + ], + [ + -88.681640625, + 48.28319289548349 + ], + [ + -97.646484375, + 48.28319289548349 + ], + [ + -97.646484375, + 43.197167282501276 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -93.8671875, + 36.87962060502676 + ], + [ + -75.89355468749999, + 36.87962060502676 + ], + [ + -75.89355468749999, + 45.1510532655634 + ], + [ + -93.8671875, + 45.1510532655634 + ], + [ + -93.8671875, + 36.87962060502676 + ] + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-geojson-rbush/test/out/all.linestrings.geojson b/packages/turf-geojson-rbush/test/out/all.linestrings.geojson new file mode 100644 index 0000000000..4a75698a4b --- /dev/null +++ b/packages/turf-geojson-rbush/test/out/all.linestrings.geojson @@ -0,0 +1,113 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -121.9921875, + 41.77131167976407 + ], + [ + -112.1484375, + 49.15296965617042 + ], + [ + -95.2734375, + 49.15296965617042 + ] + ] + }, + "bbox": [ + -121.9921875, + 41.77131167976407, + -95.2734375, + 49.15296965617042 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -101.953125, + 34.016241889667015 + ], + [ + -88.9453125, + 40.17887331434696 + ], + [ + -78.046875, + 50.064191736659104 + ] + ] + }, + "bbox": [ + -101.953125, + 34.016241889667015, + -78.046875, + 50.064191736659104 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -108.6328125, + 42.032974332441405 + ], + [ + -102.65625, + 39.36827914916014 + ], + [ + -95.97656249999999, + 39.36827914916014 + ] + ] + }, + "bbox": [ + -108.6328125, + 39.36827914916014, + -95.97656249999999, + 42.032974332441405 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -71.71875, + 39.842286020743394 + ], + [ + -69.169921875, + 35.96022296929667 + ], + [ + -66.796875, + 31.952162238024975 + ] + ] + }, + "bbox": [ + -71.71875, + 31.952162238024975, + -66.796875, + 39.842286020743394 + ] + } + ] +} diff --git a/packages/turf-geojson-rbush/test/out/all.points.geojson b/packages/turf-geojson-rbush/test/out/all.points.geojson new file mode 100644 index 0000000000..24165ef6bb --- /dev/null +++ b/packages/turf-geojson-rbush/test/out/all.points.geojson @@ -0,0 +1,56 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -86.8359375, + 42.8115217450979 + ] + }, + "bbox": [ + -86.8359375, + 42.8115217450979, + -86.8359375, + 42.8115217450979 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -67.5, + 48.69096039092549 + ] + }, + "bbox": [ + -67.5, + 48.69096039092549, + -67.5, + 48.69096039092549 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -106.171875, + 46.800059446787316 + ] + }, + "bbox": [ + -106.171875, + 46.800059446787316, + -106.171875, + 46.800059446787316 + ] + } + ] +} diff --git a/packages/turf-geojson-rbush/test/out/all.polygons.geojson b/packages/turf-geojson-rbush/test/out/all.polygons.geojson new file mode 100644 index 0000000000..a25063017d --- /dev/null +++ b/packages/turf-geojson-rbush/test/out/all.polygons.geojson @@ -0,0 +1,153 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -78, + 41 + ], + [ + -67, + 41 + ], + [ + -67, + 48 + ], + [ + -78, + 48 + ], + [ + -78, + 41 + ] + ] + ] + }, + "bbox": [ + -78, + 41, + -67, + 48 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -93, + 32 + ], + [ + -83, + 32 + ], + [ + -83, + 39 + ], + [ + -93, + 39 + ], + [ + -93, + 32 + ] + ] + ] + }, + "bbox": [ + -93, + 32, + -83, + 39 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -97.646484375, + 43.197167282501276 + ], + [ + -88.681640625, + 43.197167282501276 + ], + [ + -88.681640625, + 48.28319289548349 + ], + [ + -97.646484375, + 48.28319289548349 + ], + [ + -97.646484375, + 43.197167282501276 + ] + ] + ] + }, + "bbox": [ + -97.646484375, + 43.197167282501276, + -88.681640625, + 48.28319289548349 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -93.8671875, + 36.87962060502676 + ], + [ + -75.89355468749999, + 36.87962060502676 + ], + [ + -75.89355468749999, + 45.1510532655634 + ], + [ + -93.8671875, + 45.1510532655634 + ], + [ + -93.8671875, + 36.87962060502676 + ] + ] + ] + }, + "bbox": [ + -93.8671875, + 36.87962060502676, + -75.89355468749999, + 45.1510532655634 + ] + } + ] +} diff --git a/packages/turf-geojson-rbush/test/out/search.linestrings.geojson b/packages/turf-geojson-rbush/test/out/search.linestrings.geojson new file mode 100644 index 0000000000..619566bd0f --- /dev/null +++ b/packages/turf-geojson-rbush/test/out/search.linestrings.geojson @@ -0,0 +1,86 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -121.9921875, + 41.77131167976407 + ], + [ + -112.1484375, + 49.15296965617042 + ], + [ + -95.2734375, + 49.15296965617042 + ] + ] + }, + "bbox": [ + -121.9921875, + 41.77131167976407, + -95.2734375, + 49.15296965617042 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -101.953125, + 34.016241889667015 + ], + [ + -88.9453125, + 40.17887331434696 + ], + [ + -78.046875, + 50.064191736659104 + ] + ] + }, + "bbox": [ + -101.953125, + 34.016241889667015, + -78.046875, + 50.064191736659104 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [ + [ + -108.6328125, + 42.032974332441405 + ], + [ + -102.65625, + 39.36827914916014 + ], + [ + -95.97656249999999, + 39.36827914916014 + ] + ] + }, + "bbox": [ + -108.6328125, + 39.36827914916014, + -95.97656249999999, + 42.032974332441405 + ] + } + ] +} diff --git a/packages/turf-geojson-rbush/test/out/search.points.geojson b/packages/turf-geojson-rbush/test/out/search.points.geojson new file mode 100644 index 0000000000..2c8bcde2cb --- /dev/null +++ b/packages/turf-geojson-rbush/test/out/search.points.geojson @@ -0,0 +1,22 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [ + -86.8359375, + 42.8115217450979 + ] + }, + "bbox": [ + -86.8359375, + 42.8115217450979, + -86.8359375, + 42.8115217450979 + ] + } + ] +} diff --git a/packages/turf-geojson-rbush/test/out/search.polygons.geojson b/packages/turf-geojson-rbush/test/out/search.polygons.geojson new file mode 100644 index 0000000000..acffede86a --- /dev/null +++ b/packages/turf-geojson-rbush/test/out/search.polygons.geojson @@ -0,0 +1,79 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -78, + 41 + ], + [ + -67, + 41 + ], + [ + -67, + 48 + ], + [ + -78, + 48 + ], + [ + -78, + 41 + ] + ] + ] + }, + "bbox": [ + -78, + 41, + -67, + 48 + ] + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -93.8671875, + 36.87962060502676 + ], + [ + -75.89355468749999, + 36.87962060502676 + ], + [ + -75.89355468749999, + 45.1510532655634 + ], + [ + -93.8671875, + 45.1510532655634 + ], + [ + -93.8671875, + 36.87962060502676 + ] + ] + ] + }, + "bbox": [ + -93.8671875, + 36.87962060502676, + -75.89355468749999, + 45.1510532655634 + ] + } + ] +} diff --git a/packages/turf-geojson-rbush/types.ts b/packages/turf-geojson-rbush/types.ts new file mode 100644 index 0000000000..adf299ec05 --- /dev/null +++ b/packages/turf-geojson-rbush/types.ts @@ -0,0 +1,45 @@ +import { point, polygon, featureCollection } from "@turf/helpers"; +import { BBox, Point, Polygon } from "geojson"; +import rbush from "./"; + +// Fixtures +const bbox: BBox = [-180, -90, 180, 90]; +const pt = point([0, 0]); +const points = featureCollection([pt, pt]); +const poly = polygon([ + [ + [0, 0], + [1, 1], + [1, 1], + [0, 0], + ], +]); +const polygons = featureCollection([poly, poly]); + +// Initialize GeoJSON RBush Tree +const tree = rbush(); + +// Load Tree with a FeatureCollection +tree.load(points); +tree.load(polygons); + +// Insert by Feature +tree.insert(pt); +tree.insert(poly); + +// Find All (returns FeatureCollection) +const all = tree.all(); + +// Search by Feature (returns FeatureCollection) +const search = tree.search(poly); + +// Collides by Feature (returns FeatureCollection) +const collides = tree.collides(poly); + +// Remove by Feature +tree.remove(pt); +tree.remove(poly); + +// BBox support +tree.search(bbox); +tree.collides(bbox); diff --git a/packages/turf/test.js b/packages/turf/test.js index 2395237fef..23931fc235 100644 --- a/packages/turf/test.js +++ b/packages/turf/test.js @@ -128,7 +128,7 @@ test("turf -- MIT license", (t) => { const { license } = pckg; if (license !== "MIT") t.fail(`${name} (license) must be "MIT"`); if (fs.readFileSync(path.join(dir, "LICENSE"), "utf8") !== text) - t.fail(`${name} (LICENSE) is different from @turf/turf`); + t.fail(`${name} (LICENSE) content is different from @turf/turf`); } t.end(); });