From 9b736433e05ee93a9c7297951bd5f6db88028a36 Mon Sep 17 00:00:00 2001 From: Rowan Winsemius Date: Sun, 18 Jun 2017 00:02:25 +1000 Subject: [PATCH 1/5] turf/booleanContains --- packages/turf-boolean-contains/LICENSE | 20 ++ packages/turf-boolean-contains/README.md | 63 ++++ packages/turf-boolean-contains/bench.js | 47 +++ packages/turf-boolean-contains/index.d.ts | 10 + packages/turf-boolean-contains/index.js | 316 +++++++++++++++++ packages/turf-boolean-contains/package.json | 46 +++ packages/turf-boolean-contains/test.js | 23 ++ .../false/LineIsNotContainedByLine.geojson | 21 ++ .../false/LineIsNotContainedByPolygon.geojson | 21 ++ ...ineIsNotContainedByPolygonBoundary.geojson | 21 ++ ...ltiPointIsNotContainedByMultiPoint.geojson | 21 ++ .../MultiPointIsNotContainedByPolygon.geojson | 21 ++ .../MultiPointsIsNotContainedByLine.geojson | 21 ++ .../PointIsNotContainedBYMultiPoint.geojson | 30 ++ .../false/PointIsNotContainedByLine.geojson | 21 ++ ...ntIsNotContainedByLineBecauseOnEnd.geojson | 21 ++ .../PointIsNotContainedByPolygon.geojson | 21 ++ .../test/false/PointOnPolygonBoundary.geojson | 21 ++ .../PolygonIsNotContainedByPolygon.geojson | 21 ++ .../test/true/LineIsContainedByLine.geojson | 21 ++ .../true/LineIsContainedByPolygon.geojson | 21 ++ ...iPointIsContainedByPolygonBoundary.geojson | 21 ++ .../MultiPointsContainedByMultiPoints.geojson | 21 ++ .../true/MultipointsIsContainedByLine.geojson | 21 ++ .../true/PointInsidePolygonBoundary.geojson | 21 ++ .../test/true/PointIsContainedByLine.geojson | 21 ++ .../true/PointIsContainedByMultiPoint.geojson | 30 ++ .../true/PolygonIsContainedByPolygon.geojson | 21 ++ .../test/true/PolygonsExactSameShape.geojson | 71 ++++ packages/turf-boolean-contains/yarn.lock | 318 ++++++++++++++++++ 30 files changed, 1373 insertions(+) create mode 100644 packages/turf-boolean-contains/LICENSE create mode 100644 packages/turf-boolean-contains/README.md create mode 100644 packages/turf-boolean-contains/bench.js create mode 100644 packages/turf-boolean-contains/index.d.ts create mode 100644 packages/turf-boolean-contains/index.js create mode 100644 packages/turf-boolean-contains/package.json create mode 100644 packages/turf-boolean-contains/test.js create mode 100644 packages/turf-boolean-contains/test/false/LineIsNotContainedByLine.geojson create mode 100644 packages/turf-boolean-contains/test/false/LineIsNotContainedByPolygon.geojson create mode 100644 packages/turf-boolean-contains/test/false/LineIsNotContainedByPolygonBoundary.geojson create mode 100644 packages/turf-boolean-contains/test/false/MultiPointIsNotContainedByMultiPoint.geojson create mode 100644 packages/turf-boolean-contains/test/false/MultiPointIsNotContainedByPolygon.geojson create mode 100644 packages/turf-boolean-contains/test/false/MultiPointsIsNotContainedByLine.geojson create mode 100644 packages/turf-boolean-contains/test/false/PointIsNotContainedBYMultiPoint.geojson create mode 100644 packages/turf-boolean-contains/test/false/PointIsNotContainedByLine.geojson create mode 100644 packages/turf-boolean-contains/test/false/PointIsNotContainedByLineBecauseOnEnd.geojson create mode 100644 packages/turf-boolean-contains/test/false/PointIsNotContainedByPolygon.geojson create mode 100644 packages/turf-boolean-contains/test/false/PointOnPolygonBoundary.geojson create mode 100644 packages/turf-boolean-contains/test/false/PolygonIsNotContainedByPolygon.geojson create mode 100644 packages/turf-boolean-contains/test/true/LineIsContainedByLine.geojson create mode 100644 packages/turf-boolean-contains/test/true/LineIsContainedByPolygon.geojson create mode 100644 packages/turf-boolean-contains/test/true/MultiPointIsContainedByPolygonBoundary.geojson create mode 100644 packages/turf-boolean-contains/test/true/MultiPointsContainedByMultiPoints.geojson create mode 100644 packages/turf-boolean-contains/test/true/MultipointsIsContainedByLine.geojson create mode 100644 packages/turf-boolean-contains/test/true/PointInsidePolygonBoundary.geojson create mode 100644 packages/turf-boolean-contains/test/true/PointIsContainedByLine.geojson create mode 100644 packages/turf-boolean-contains/test/true/PointIsContainedByMultiPoint.geojson create mode 100644 packages/turf-boolean-contains/test/true/PolygonIsContainedByPolygon.geojson create mode 100644 packages/turf-boolean-contains/test/true/PolygonsExactSameShape.geojson create mode 100644 packages/turf-boolean-contains/yarn.lock diff --git a/packages/turf-boolean-contains/LICENSE b/packages/turf-boolean-contains/LICENSE new file mode 100644 index 0000000000..96ce51b76f --- /dev/null +++ b/packages/turf-boolean-contains/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-boolean-contains/README.md b/packages/turf-boolean-contains/README.md new file mode 100644 index 0000000000..e9a3468a2d --- /dev/null +++ b/packages/turf-boolean-contains/README.md @@ -0,0 +1,63 @@ +# @turf/boolean-contains + +# booleanContains + +Boolean-contains returns True if the second geometry is completely contained by the first geometry. +The interiors of both geometries must intersect and, the interior and boundary of the secondary (geometry b) +must not intersect the exterior of the primary (geometry a). +Boolean-contains returns the exact opposite result of the `@turf/boolean-within`. + +**Parameters** + +- `feature1` **([Geometry](http://geojson.org/geojson-spec.html#geometry) \| [Feature](http://geojson.org/geojson-spec.html#feature-objects)<any>)** GeoJSON Feature or Geometry +- `feature2` **([Geometry](http://geojson.org/geojson-spec.html#geometry) \| [Feature](http://geojson.org/geojson-spec.html#feature-objects)<any>)** GeoJSON Feature or Geometry + +**Examples** + +```javascript +const point = { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [1, 2] + } +} +const line = { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } +} +turf.booleanContains(line, point); +//=true +``` + +Returns **[Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** true/false + + + +--- + +This module is part of the [Turfjs project](http://turfjs.org/), an open source +module collection dedicated to geographic algorithms. It is maintained in the +[Turfjs/turf](https://github.com/Turfjs/turf) repository, where you can create +PRs and issues. + +### Installation + +Install this module individually: + +```sh +$ npm install @turf/boolean-contains +``` + +Or install the Turf module that includes it as a function: + +```sh +$ npm install @turf/turf +``` diff --git a/packages/turf-boolean-contains/bench.js b/packages/turf-boolean-contains/bench.js new file mode 100644 index 0000000000..52868b4663 --- /dev/null +++ b/packages/turf-boolean-contains/bench.js @@ -0,0 +1,47 @@ +const path = require('path'); +const glob = require('glob'); +const Benchmark = require('benchmark'); +const load = require('load-json-file'); +const bbox = require('@turf/bbox'); +const contains = require('./'); + +/** + * Benchmark Results + * + * LineIsNotContainedByLine x 4,133,850 ops/sec ±1.62% (92 runs sampled) + * LineIsNotContainedByPolygon x 1,416,083 ops/sec ±2.47% (87 runs sampled) + * LineIsNotContainedByPolygonBoundary x 1,419,828 ops/sec ±1.85% (88 runs sampled) + * MultiPointIsNotContainedByMultiPoint x 6,705,712 ops/sec ±4.32% (76 runs sampled) + * MultiPointIsNotContainedByPolygon x 2,043,151 ops/sec ±3.21% (82 runs sampled) + * MultiPointsIsNotContainedByLine x 5,210,528 ops/sec ±3.21% (74 runs sampled) + * PointIsNotContainedByLine x 7,324,482 ops/sec ±4.22% (84 runs sampled) + * PointIsNotContainedByLineBecauseOnEnd x 6,024,271 ops/sec ±5.04% (78 runs sampled) + * PointIsNotContainedBYMultiPoint x 10,063,229 ops/sec ±3.50% (80 runs sampled) + * PointIsNotContainedByPolygon x 2,204,858 ops/sec ±3.03% (80 runs sampled) + * PointOnPolygonBoundary x 2,387,408 ops/sec ±2.47% (83 runs sampled) + * PolygonIsNotContainedByPolygon x 1,999,776 ops/sec ±3.20% (84 runs sampled) + * LineIsContainedByLine x 3,434,699 ops/sec ±3.43% (82 runs sampled) + * LineIsContainedByPolygon x 853,234 ops/sec ±2.43% (79 runs sampled) + * MultiPointIsContainedByPolygonBoundary x 1,197,014 ops/sec ±1.89% (85 runs sampled) + * MultiPointsContainedByMultiPoints x 6,601,619 ops/sec ±2.44% (80 runs sampled) + * MultipointsIsContainedByLine x 5,843,279 ops/sec ±2.37% (82 runs sampled) + * PointInsidePolygonBoundary x 2,110,993 ops/sec ±3.84% (79 runs sampled) + * PointIsContainedByLine x 7,436,720 ops/sec ±2.74% (80 runs sampled) + * PointIsContainedByMultiPoint x 10,256,333 ops/sec ±4.22% (75 runs sampled) + * PolygonIsContainedByPolygon x 757,885 ops/sec ±2.61% (82 runs sampled) + * PolygonsExactSameShape x 758,328 ops/sec ±2.27% (86 runs sampled) + */ +const suite = new Benchmark.Suite('turf-boolean-contains'); +glob.sync(path.join(__dirname, 'test', '**', '*.geojson')).forEach(filepath => { + const {name} = path.parse(filepath); + const geojson = load.sync(filepath); + const [feature1, feature2] = geojson.features; + feature1.bbox = bbox(feature1); + feature2.bbox = bbox(feature2); + suite.add(name, () => contains(feature1, feature2)); +}); + +suite + .on('cycle', e => console.log(String(e.target))) + .on('complete', () => {}) + .run(); diff --git a/packages/turf-boolean-contains/index.d.ts b/packages/turf-boolean-contains/index.d.ts new file mode 100644 index 0000000000..17629c4481 --- /dev/null +++ b/packages/turf-boolean-contains/index.d.ts @@ -0,0 +1,10 @@ +/// + +type Feature = GeoJSON.Feature | GeoJSON.GeometryObject; + +/** + * http://turfjs.org/docs/#boolean-contains + */ +declare function contains(feature1: Feature, feature2: Feature): boolean; +declare namespace contains { } +export = contains; diff --git a/packages/turf-boolean-contains/index.js b/packages/turf-boolean-contains/index.js new file mode 100644 index 0000000000..d311cd8823 --- /dev/null +++ b/packages/turf-boolean-contains/index.js @@ -0,0 +1,316 @@ +var inside = require('@turf/inside'); +var invariant = require('@turf/invariant'); +var getGeom = invariant.getGeom; +var getCoords = invariant.getCoords; +var getGeomType = invariant.getGeomType; + +/** + * Boolean-contains returns True if the second geometry is completely contained by the first geometry. + * The interiors of both geometries must intersect and, the interior and boundary of the secondary (geometry b) + * must not intersect the exterior of the primary (geometry a). + * Boolean-contains returns the exact opposite result of the `@turf/boolean-within`. + * + * @name booleanContains + * @param {Geometry|Feature} feature1 GeoJSON Feature or Geometry + * @param {Geometry|Feature} feature2 GeoJSON Feature or Geometry + * @returns {Boolean} true/false + * @example + * const point = { + * "type": "Feature", + * "properties": {}, + * "geometry": { + * "type": "Point", + * "coordinates": [1, 2] + * } + * } + * const line = { + * "type": "Feature", + * "properties": {}, + * "geometry": { + * "type": "LineString", + * "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + * } + * } + * turf.booleanContains(line, point); + * //=true + */ +module.exports = function (feature1, feature2) { + var type1 = getGeomType(feature1); + var type2 = getGeomType(feature2); + var geom1 = getGeom(feature1); + var geom2 = getGeom(feature2); + var coords1 = getCoords(feature1); + var coords2 = getCoords(feature2); + + switch (type1) { + case 'Point': + switch (type2) { + case 'Point': + return compareCoords(coords1, coords2); + } + throw new Error('feature2 ' + type2 + ' geometry not supported'); + case 'MultiPoint': + switch (type2) { + case 'Point': + return isPointInMultiPoint(geom1, geom2); + case 'MultiPoint': + return isMultiPointInMultiPoint(geom1, geom2); + } + throw new Error('feature2 ' + type2 + ' geometry not supported'); + case 'LineString': + switch (type2) { + case 'Point': + return isPointOnLine(geom1, geom2); + case 'LineString': + return isLineOnLine(geom1, geom2); + case 'MultiPoint': + return isMultiPointOnLine(geom1, geom2); + } + throw new Error('feature2 ' + type2 + ' geometry not supported'); + case 'Polygon': + switch (type2) { + case 'Point': + return inside(geom2, geom1, true); + case 'LineString': + return isLineInPoly(geom1, geom2); + case 'Polygon': + return isPolyInPoly(feature2, feature1); + case 'MultiPoint': + return isMultiPointInPoly(geom1, geom2); + } + throw new Error('feature2 ' + type2 + ' geometry not supported'); + default: + throw new Error('feature1 ' + type1 + ' geometry not supported'); + } +}; + +function isPointInMultiPoint(multiPoint, point) { + var i; + var output = false; + for (i = 0; i < multiPoint.coordinates.length; i++) { + if (compareCoords(multiPoint.coordinates[i], point.coordinates)) { + output = true; + break; + } + } + return output; +} + +function isMultiPointInMultiPoint(multiPoint1, multiPoint2) { + var foundAMatch = 0; + for (var i = 0; i < multiPoint2.coordinates.length; i++) { + var anyMatch = false; + for (var i2 = 0; i2 < multiPoint1.coordinates.length; i2++) { + if (compareCoords(multiPoint2.coordinates[i], multiPoint1.coordinates[i2])) { + foundAMatch++; + anyMatch = true; + break; + } + } + if (!anyMatch) { + return false; + } + } + return foundAMatch > 0; +} + +// http://stackoverflow.com/a/11908158/1979085 +function isPointOnLine(lineString, point) { + var output = false; + for (var i = 0; i < lineString.coordinates.length - 1; i++) { + var incEndVertices = true; + if (i === 0 || i === lineString.coordinates.length - 2) { + incEndVertices = false; + } + if (isPointOnLineSegment(lineString.coordinates[i], lineString.coordinates[i + 1], point.coordinates, incEndVertices)) { + output = true; + break; + } + } + return output; +} + +function isMultiPointOnLine(lineString, multiPoint) { + var output = true; + for (var i = 0; i < multiPoint.coordinates.length; i++) { + var pointIsOnLine = false; + for (var i2 = 0; i2 < lineString.coordinates.length - 1; i2++) { + var incEndVertices = true; + if (i2 === 0 || i2 === lineString.coordinates.length - 2) { + incEndVertices = false; + } + if (isPointOnLineSegment(lineString.coordinates[i2], lineString.coordinates[i2 + 1], multiPoint.coordinates[i], incEndVertices)) { + pointIsOnLine = true; + break; + } + } + if (!pointIsOnLine) { + output = false; + break; + } + } + return output; +} + +function isMultiPointInPoly(polygon, multiPoint) { + var output = true; + for (var i = 0; i < multiPoint.coordinates.length; i++) { + var isInside = inside(multiPoint.coordinates[1], polygon); + if (!isInside) { + output = false; + break; + } + } + return output; +} + +function isLineOnLine(lineString1, lineString2) { + var output = true; + for (var i = 0; i < lineString2.coordinates.length; i++) { + var checkLineCoords = isPointOnLine(lineString1, {type: 'Point', coordinates: lineString2.coordinates[i]}); + if (!checkLineCoords) { + output = false; + break; + } + } + if (output) { + if (compareCoords(lineString1.coordinates[0], lineString2.coordinates[0]) || + compareCoords(lineString1.coordinates[lineString1.coordinates.length - 1], lineString2.coordinates[lineString2.coordinates.length - 1])) { + output = false; + } + } + return output; +} + +function isLineInPoly(polygon, linestring) { + var output = true; + var foundInternalPoint = false; + for (var i = 0; i < linestring.coordinates.length; i++) { + var isInside = null; + if (!foundInternalPoint) { + isInside = inside(linestring.coordinates[i], polygon); + } else { + isInside = inside(linestring.coordinates[i], polygon, true); + } + if (isInside) { + foundInternalPoint = true; + } + if (!isInside) { + output = false; + break; + } + } + return output; +} + +/** + * Is Polygon (geom1) in Polygon (geom2) + * Only takes into account outer rings + * See http://stackoverflow.com/a/4833823/1979085 + * + * @private + * @param {Geometry|Feature} feature1 Polygon1 + * @param {Geometry|Feature} feature2 Polygon2 + * @returns {Boolean} true/false + */ +function isPolyInPoly(feature1, feature2) { + var coords = getCoords(feature1)[0]; + var ring = getCoords(feature2)[0]; + var bbox = feature2.bbox; + + // check if outer coordinates is inside outer ring + for (var i = 0; i < coords.length; i++) { + // 3x performance increase if BBox is present + if (bbox && !inBBox(coords[i], bbox)) return false; + if (!inRing(coords[i], ring)) return false; + } + return true; +} + + +/** + * Is a point on a line segment + * Only takes into account outer rings + * See http://stackoverflow.com/a/4833823/1979085 + * + * @private + * @param {Array} lineSegmentStart coord pair of start of line + * @param {Array} lineSegmentEnd coord pair of end of line + * @param {Array} point coord pair of point to check + * @param {Boolean} incEnd whether the point is allowed to fall on the line ends + * @returns {Boolean} true/false + */ +function isPointOnLineSegment(lineSegmentStart, lineSegmentEnd, point, incEnd) { + var dxc = point[0] - lineSegmentStart[0]; + var dyc = point[1] - lineSegmentStart[1]; + var dxl = lineSegmentEnd[0] - lineSegmentStart[0]; + var dyl = lineSegmentEnd[1] - lineSegmentStart[1]; + var cross = dxc * dyl - dyc * dxl; + if (cross !== 0) { + return false; + } + if (incEnd) { + if (Math.abs(dxl) >= Math.abs(dyl)) { + return dxl > 0 ? lineSegmentStart[0] <= point[0] && point[0] <= lineSegmentEnd[0] : lineSegmentEnd[0] <= point[0] && point[0] <= lineSegmentStart[0]; + } + return dyl > 0 ? lineSegmentStart[1] <= point[1] && point[1] <= lineSegmentEnd[1] : lineSegmentEnd[1] <= point[1] && point[1] <= lineSegmentStart[1]; + } else { + if (Math.abs(dxl) >= Math.abs(dyl)) { + return dxl > 0 ? lineSegmentStart[0] < point[0] && point[0] < lineSegmentEnd[0] : lineSegmentEnd[0] < point[0] && point[0] < lineSegmentStart[0]; + } + return dyl > 0 ? lineSegmentStart[1] < point[1] && point[1] < lineSegmentEnd[1] : lineSegmentEnd[1] < point[1] && point[1] < lineSegmentStart[1]; + } +} + +/** + * inRing - @turf/inside + * + * @private + * @param {[number, number]} pt [x,y] + * @param {Array<[number, number]>} ring [[x,y], [x,y],..] + * @param {boolean} ignoreBoundary ignoreBoundary + * @returns {boolean} inRing + */ +function inRing(pt, ring, ignoreBoundary) { + var isInside = false; + if (ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]) ring = ring.slice(0, ring.length - 1); + + for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) { + var xi = ring[i][0], yi = ring[i][1]; + var xj = ring[j][0], yj = ring[j][1]; + var onBoundary = (pt[1] * (xi - xj) + yi * (xj - pt[0]) + yj * (pt[0] - xi) === 0) && + ((xi - pt[0]) * (xj - pt[0]) <= 0) && ((yi - pt[1]) * (yj - pt[1]) <= 0); + if (onBoundary) return !ignoreBoundary; + var intersect = ((yi > pt[1]) !== (yj > pt[1])) && + (pt[0] < (xj - xi) * (pt[1] - yi) / (yj - yi) + xi); + if (intersect) isInside = !isInside; + } + return isInside; +} + +/** + * inBBox - @turf/inside + * + * @private + * @param {[number, number]} pt point [x,y] + * @param {[number, number, number, number]} bbox BBox [west, south, east, north] + * @returns {boolean} true/false if point is inside BBox + */ +function inBBox(pt, bbox) { + return bbox[0] <= pt[0] && + bbox[1] <= pt[1] && + bbox[2] >= pt[0] && + bbox[3] >= pt[1]; +} + +/** + * compareCoords + * + * @private + * @param {[number, number]} pair1 point [x,y] + * @param {[number, number]} pair2 point [x,y] + * @returns {boolean} true/false if coord pairs match + */ +function compareCoords(pair1, pair2) { + return pair1[0] === pair2[0] && pair1[1] === pair2[1]; +} diff --git a/packages/turf-boolean-contains/package.json b/packages/turf-boolean-contains/package.json new file mode 100644 index 0000000000..1cb8e42825 --- /dev/null +++ b/packages/turf-boolean-contains/package.json @@ -0,0 +1,46 @@ +{ + "name": "@turf/boolean-contains", + "version": "4.0.0", + "description": "turf boolean-contains module", + "main": "index.js", + "types": "index.d.ts", + "files": [ + "index.js", + "index.d.ts" + ], + "scripts": { + "test": "node test.js", + "bench": "node bench.js" + }, + "repository": { + "type": "git", + "url": "git://github.com/Turfjs/turf.git" + }, + "keywords": [ + "turf", + "contains", + "boolean", + "de-9im" + ], + "author": "Turf Authors", + "contributors": [ + "Rowan Winsemius <@rowanwins>", + "Denis Carriere <@DenisCarriere>" + ], + "license": "MIT", + "bugs": { + "url": "https://github.com/Turfjs/turf/issues" + }, + "homepage": "https://github.com/Turfjs/turf", + "devDependencies": { + "@turf/bbox": "^4.2.0", + "benchmark": "^2.1.4", + "glob": "^7.1.1", + "load-json-file": "^2.0.0", + "tape": "^4.6.3" + }, + "dependencies": { + "@turf/inside": "^4.2.0", + "@turf/invariant": "^4.2.0" + } +} diff --git a/packages/turf-boolean-contains/test.js b/packages/turf-boolean-contains/test.js new file mode 100644 index 0000000000..fb0a59fb5d --- /dev/null +++ b/packages/turf-boolean-contains/test.js @@ -0,0 +1,23 @@ +const glob = require('glob'); +const path = require('path'); +const test = require('tape'); +const load = require('load-json-file'); +const contains = require('./'); + +test('turf-boolean-contains#fixtures', t => { + // True Fixtures + glob.sync(path.join(__dirname, 'test', 'true', '*.geojson')).forEach(filepath => { + const {name} = path.parse(filepath); + const geojson = load.sync(filepath); + const [feature1, feature2] = geojson.features; + t.true(contains(feature1, feature2), '[true] ' + name); + }); + // False Fixtures + glob.sync(path.join(__dirname, 'test', 'false', '*.geojson')).forEach(filepath => { + const {name} = path.parse(filepath); + const geojson = load.sync(filepath); + const [feature1, feature2] = geojson.features; + t.false(contains(feature1, feature2), '[false] ' + name); + }); + t.end(); +}); diff --git a/packages/turf-boolean-contains/test/false/LineIsNotContainedByLine.geojson b/packages/turf-boolean-contains/test/false/LineIsNotContainedByLine.geojson new file mode 100644 index 0000000000..d8a54da354 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/LineIsNotContainedByLine.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 2], [1, 3], [1, 15.5]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/LineIsNotContainedByPolygon.geojson b/packages/turf-boolean-contains/test/false/LineIsNotContainedByPolygon.geojson new file mode 100644 index 0000000000..f65ab79889 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/LineIsNotContainedByPolygon.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 2], [1, 3], [1, 15.5]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/LineIsNotContainedByPolygonBoundary.geojson b/packages/turf-boolean-contains/test/false/LineIsNotContainedByPolygonBoundary.geojson new file mode 100644 index 0000000000..4fd182edbf --- /dev/null +++ b/packages/turf-boolean-contains/test/false/LineIsNotContainedByPolygonBoundary.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 2], [1, 3], [1, 3.5]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/MultiPointIsNotContainedByMultiPoint.geojson b/packages/turf-boolean-contains/test/false/MultiPointIsNotContainedByMultiPoint.geojson new file mode 100644 index 0000000000..4c8663f39b --- /dev/null +++ b/packages/turf-boolean-contains/test/false/MultiPointIsNotContainedByMultiPoint.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1, 1], [12, 12], [15, 15]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1, 1], [1, 1.5]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/MultiPointIsNotContainedByPolygon.geojson b/packages/turf-boolean-contains/test/false/MultiPointIsNotContainedByPolygon.geojson new file mode 100644 index 0000000000..a4f1e5e06c --- /dev/null +++ b/packages/turf-boolean-contains/test/false/MultiPointIsNotContainedByPolygon.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1, 1], [12, 12], [15, 15]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/MultiPointsIsNotContainedByLine.geojson b/packages/turf-boolean-contains/test/false/MultiPointsIsNotContainedByLine.geojson new file mode 100644 index 0000000000..e46f267ba4 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/MultiPointsIsNotContainedByLine.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1, 1], [12, 12], [15, 15]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/PointIsNotContainedBYMultiPoint.geojson b/packages/turf-boolean-contains/test/false/PointIsNotContainedBYMultiPoint.geojson new file mode 100644 index 0000000000..7dd96a2321 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/PointIsNotContainedBYMultiPoint.geojson @@ -0,0 +1,30 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [ + 1, + 1 + ], + [ + 12, + 12 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [1, 4] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/PointIsNotContainedByLine.geojson b/packages/turf-boolean-contains/test/false/PointIsNotContainedByLine.geojson new file mode 100644 index 0000000000..5b385b48e4 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/PointIsNotContainedByLine.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [2, 2] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/PointIsNotContainedByLineBecauseOnEnd.geojson b/packages/turf-boolean-contains/test/false/PointIsNotContainedByLineBecauseOnEnd.geojson new file mode 100644 index 0000000000..7a880bbd53 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/PointIsNotContainedByLineBecauseOnEnd.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [1, 4] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/PointIsNotContainedByPolygon.geojson b/packages/turf-boolean-contains/test/false/PointIsNotContainedByPolygon.geojson new file mode 100644 index 0000000000..c07b0bd685 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/PointIsNotContainedByPolygon.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [14,14] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/PointOnPolygonBoundary.geojson b/packages/turf-boolean-contains/test/false/PointOnPolygonBoundary.geojson new file mode 100644 index 0000000000..fe23f39fa6 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/PointOnPolygonBoundary.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [1,1] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/PolygonIsNotContainedByPolygon.geojson b/packages/turf-boolean-contains/test/false/PolygonIsNotContainedByPolygon.geojson new file mode 100644 index 0000000000..50c142cbde --- /dev/null +++ b/packages/turf-boolean-contains/test/false/PolygonIsNotContainedByPolygon.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 20], [1, 3], [1, 4], [1, 1]]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/LineIsContainedByLine.geojson b/packages/turf-boolean-contains/test/true/LineIsContainedByLine.geojson new file mode 100644 index 0000000000..8e4ca552a1 --- /dev/null +++ b/packages/turf-boolean-contains/test/true/LineIsContainedByLine.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 2], [1, 3], [1, 3.5]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/LineIsContainedByPolygon.geojson b/packages/turf-boolean-contains/test/true/LineIsContainedByPolygon.geojson new file mode 100644 index 0000000000..ec823e7915 --- /dev/null +++ b/packages/turf-boolean-contains/test/true/LineIsContainedByPolygon.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [2, 3], [2, 3.5]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/MultiPointIsContainedByPolygonBoundary.geojson b/packages/turf-boolean-contains/test/true/MultiPointIsContainedByPolygonBoundary.geojson new file mode 100644 index 0000000000..0d7cbccc42 --- /dev/null +++ b/packages/turf-boolean-contains/test/true/MultiPointIsContainedByPolygonBoundary.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1,1],[4,4]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/MultiPointsContainedByMultiPoints.geojson b/packages/turf-boolean-contains/test/true/MultiPointsContainedByMultiPoints.geojson new file mode 100644 index 0000000000..5d32b8e6cd --- /dev/null +++ b/packages/turf-boolean-contains/test/true/MultiPointsContainedByMultiPoints.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1, 1], [12, 12], [15, 15]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1, 1], [12, 12], [15, 15]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/MultipointsIsContainedByLine.geojson b/packages/turf-boolean-contains/test/true/MultipointsIsContainedByLine.geojson new file mode 100644 index 0000000000..7e0b98ce92 --- /dev/null +++ b/packages/turf-boolean-contains/test/true/MultipointsIsContainedByLine.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1, 1.2], [1, 1.5]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/PointInsidePolygonBoundary.geojson b/packages/turf-boolean-contains/test/true/PointInsidePolygonBoundary.geojson new file mode 100644 index 0000000000..0e7288ec9b --- /dev/null +++ b/packages/turf-boolean-contains/test/true/PointInsidePolygonBoundary.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [4,4] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/PointIsContainedByLine.geojson b/packages/turf-boolean-contains/test/true/PointIsContainedByLine.geojson new file mode 100644 index 0000000000..b5c6468f6f --- /dev/null +++ b/packages/turf-boolean-contains/test/true/PointIsContainedByLine.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [1, 2] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/PointIsContainedByMultiPoint.geojson b/packages/turf-boolean-contains/test/true/PointIsContainedByMultiPoint.geojson new file mode 100644 index 0000000000..7a101b3507 --- /dev/null +++ b/packages/turf-boolean-contains/test/true/PointIsContainedByMultiPoint.geojson @@ -0,0 +1,30 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [ + [ + 1, + 1 + ], + [ + 12, + 12 + ] + ] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [1, 1] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/PolygonIsContainedByPolygon.geojson b/packages/turf-boolean-contains/test/true/PolygonIsContainedByPolygon.geojson new file mode 100644 index 0000000000..eea0287949 --- /dev/null +++ b/packages/turf-boolean-contains/test/true/PolygonIsContainedByPolygon.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 2], [1, 3], [1, 4], [1, 1]]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/PolygonsExactSameShape.geojson b/packages/turf-boolean-contains/test/true/PolygonsExactSameShape.geojson new file mode 100644 index 0000000000..5f2774e9cb --- /dev/null +++ b/packages/turf-boolean-contains/test/true/PolygonsExactSameShape.geojson @@ -0,0 +1,71 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "fill": "#F00" + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -12.65625, + 36.87962060502676 + ], + [ + 35.419921875, + 36.38591277287651 + ], + [ + 37.79296875, + 56.897003921272606 + ], + [ + -12.12890625, + 57.040729838360875 + ], + [ + -12.65625, + 36.87962060502676 + ] + ] + ] + } + }, + { + "type": "Feature", + "properties": { + "fill": "#F00" + }, + "geometry": { + "type": "Polygon", + "coordinates": [ + [ + [ + -12.65625, + 36.87962060502676 + ], + [ + 35.419921875, + 36.38591277287651 + ], + [ + 37.79296875, + 56.897003921272606 + ], + [ + -12.12890625, + 57.040729838360875 + ], + [ + -12.65625, + 36.87962060502676 + ] + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/yarn.lock b/packages/turf-boolean-contains/yarn.lock new file mode 100644 index 0000000000..8680049857 --- /dev/null +++ b/packages/turf-boolean-contains/yarn.lock @@ -0,0 +1,318 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@turf/bbox@^3.10.5": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@turf/bbox/-/bbox-3.14.0.tgz#cee5f396dde78aca9cede05e1122db18bc504635" + dependencies: + "@turf/meta" "^3.14.0" + +"@turf/bbox@^4.2.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@turf/bbox/-/bbox-4.3.0.tgz#644c4b745172d21aae70d1584b2a7866f1040865" + dependencies: + "@turf/meta" "^4.3.0" + +"@turf/helpers@^3.10.5": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@turf/helpers/-/helpers-3.13.0.tgz#d06078a1464cf56cdb7ea624ea1e13a71b88b806" + +"@turf/helpers@^4.2.0", "@turf/helpers@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@turf/helpers/-/helpers-4.3.0.tgz#7b2f733aa0eb3ea1f07d467ac02ede00cc6cde0d" + +"@turf/inside@^4.2.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@turf/inside/-/inside-4.3.0.tgz#ba06be5966a5ab31c1cabb9819241e0802422c45" + dependencies: + "@turf/invariant" "^4.3.0" + +"@turf/invariant@^4.2.0", "@turf/invariant@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@turf/invariant/-/invariant-4.3.0.tgz#5bd1ce6ae51b1229dc0dc7d09d973fabae49af89" + +"@turf/line-overlap@^4.2.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@turf/line-overlap/-/line-overlap-4.3.0.tgz#f0572d3a3f536a35055d857099b5d1549cfd0074" + dependencies: + "@turf/helpers" "^4.3.0" + "@turf/invariant" "^4.3.0" + "@turf/line-segment" "^4.3.0" + "@turf/meta" "^4.3.0" + deep-equal "^1.0.1" + geojson-rbush "^1.0.1" + +"@turf/line-segment@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@turf/line-segment/-/line-segment-4.3.0.tgz#7835209227f3c0712ec549c6f51af72394c638ab" + dependencies: + "@turf/helpers" "^4.3.0" + "@turf/invariant" "^4.3.0" + "@turf/meta" "^4.3.0" + +"@turf/meta@^3.10.5", "@turf/meta@^3.14.0": + version "3.14.0" + resolved "https://registry.yarnpkg.com/@turf/meta/-/meta-3.14.0.tgz#8d3050c1a0f44bf406a633b6bd28c510f7bcee27" + +"@turf/meta@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@turf/meta/-/meta-4.3.0.tgz#eb11dd2c2511524258123767fe0f5c3bd963e8d7" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +benchmark@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/benchmark/-/benchmark-2.1.4.tgz#09f3de31c916425d498cc2ee565a0ebf3c2a5629" + dependencies: + lodash "^4.17.4" + platform "^1.3.3" + +brace-expansion@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.7.tgz#3effc3c50e000531fb720eaff80f0ae8ef23cf59" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +deep-equal@^1.0.1, deep-equal@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + +define-properties@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.2.tgz#83a73f2fea569898fb737193c8f873caf6d45c94" + dependencies: + foreach "^2.0.5" + object-keys "^1.0.8" + +defined@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" + +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.5.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c" + dependencies: + es-to-primitive "^1.1.1" + function-bind "^1.1.0" + is-callable "^1.1.3" + is-regex "^1.0.3" + +es-to-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" + dependencies: + is-callable "^1.1.1" + is-date-object "^1.0.1" + is-symbol "^1.0.1" + +for-each@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.2.tgz#2c40450b9348e97f281322593ba96704b9abd4d4" + dependencies: + is-function "~1.0.0" + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +function-bind@^1.0.2, function-bind@^1.1.0, function-bind@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" + +geojson-rbush@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/geojson-rbush/-/geojson-rbush-1.0.1.tgz#450559bc18457e725191ac9acbbe0a8b5e18ddae" + dependencies: + "@turf/bbox" "^3.10.5" + "@turf/helpers" "^3.10.5" + "@turf/meta" "^3.10.5" + rbush "^2.0.1" + +glob@^7.1.1, glob@~7.1.1: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +has@^1.0.1, has@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-callable@^1.1.1, is-callable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.3.tgz#86eb75392805ddc33af71c92a0eedf74ee7604b2" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + +is-function@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + +is-regex@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + +is-symbol@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +lodash@^4.17.4: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +object-inspect@~1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.2.2.tgz#c82115e4fcc888aea14d64c22e4f17f6a70d5e5a" + +object-keys@^1.0.8: + version "1.0.11" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +platform@^1.3.3: + version "1.3.4" + resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.4.tgz#6f0fb17edaaa48f21442b3a975c063130f1c3ebd" + +quickselect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-1.0.0.tgz#02630818f9aae4ecab26f0103f98d061c17c58f3" + +rbush@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/rbush/-/rbush-2.0.1.tgz#4cfaca28c3064bc0ee75431a1b79990e875eefa9" + dependencies: + quickselect "^1.0.0" + +resolve@~1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +resumer@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" + dependencies: + through "~2.3.4" + +string.prototype.trim@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.0" + function-bind "^1.0.2" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +tape@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/tape/-/tape-4.6.3.tgz#637e77581e9ab2ce17577e9bd4ce4f575806d8b6" + dependencies: + deep-equal "~1.0.1" + defined "~1.0.0" + for-each "~0.3.2" + function-bind "~1.1.0" + glob "~7.1.1" + has "~1.0.1" + inherits "~2.0.3" + minimist "~1.2.0" + object-inspect "~1.2.1" + resolve "~1.1.7" + resumer "~0.0.0" + string.prototype.trim "~1.1.2" + through "~2.3.8" + +through@~2.3.4, through@~2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From 3190e68181d1ed7e41d656ce95e3581bbf410a06 Mon Sep 17 00:00:00 2001 From: Rowan Winsemius Date: Sun, 18 Jun 2017 23:05:37 +1000 Subject: [PATCH 2/5] Fixes as per comments. Additional tests. --- packages/turf-bbox/package.json | 1 + packages/turf-boolean-contains/bench.js | 49 ++++++----- packages/turf-boolean-contains/index.d.ts | 6 +- packages/turf-boolean-contains/index.js | 83 ++++++++++--------- packages/turf-boolean-contains/package.json | 1 + ...lOnBoundaryIsNotContainedByPolygon.geojson | 21 +++++ ...intsOnLineEndsIsNotContainedByLine.geojson | 21 +++++ .../PointOnEndIsContainedByLinestring.geojson | 21 +++++ ...nedByPolygonWithNoInternalVertices.geojson | 21 +++++ .../test/true/LinesExactSame.geojson | 21 +++++ .../true/MultipointsIsContainedByLine.geojson | 2 +- .../true/PolygonIsContainedByPolygon.geojson | 2 +- 12 files changed, 181 insertions(+), 68 deletions(-) create mode 100644 packages/turf-boolean-contains/test/false/MultiPointAllOnBoundaryIsNotContainedByPolygon.geojson create mode 100644 packages/turf-boolean-contains/test/false/MultiPointsOnLineEndsIsNotContainedByLine.geojson create mode 100644 packages/turf-boolean-contains/test/false/PointOnEndIsContainedByLinestring.geojson create mode 100644 packages/turf-boolean-contains/test/true/LineIsContainedByPolygonWithNoInternalVertices.geojson create mode 100644 packages/turf-boolean-contains/test/true/LinesExactSame.geojson diff --git a/packages/turf-bbox/package.json b/packages/turf-bbox/package.json index 2d652d9bcb..ae35d367a5 100644 --- a/packages/turf-bbox/package.json +++ b/packages/turf-bbox/package.json @@ -31,6 +31,7 @@ }, "homepage": "https://github.com/Turfjs/turf", "devDependencies": { + "@turf/helpers": "^4.4.0", "benchmark": "^2.1.4", "tape": "^4.6.3" }, diff --git a/packages/turf-boolean-contains/bench.js b/packages/turf-boolean-contains/bench.js index 52868b4663..2e771c44e0 100644 --- a/packages/turf-boolean-contains/bench.js +++ b/packages/turf-boolean-contains/bench.js @@ -8,28 +8,33 @@ const contains = require('./'); /** * Benchmark Results * - * LineIsNotContainedByLine x 4,133,850 ops/sec ±1.62% (92 runs sampled) - * LineIsNotContainedByPolygon x 1,416,083 ops/sec ±2.47% (87 runs sampled) - * LineIsNotContainedByPolygonBoundary x 1,419,828 ops/sec ±1.85% (88 runs sampled) - * MultiPointIsNotContainedByMultiPoint x 6,705,712 ops/sec ±4.32% (76 runs sampled) - * MultiPointIsNotContainedByPolygon x 2,043,151 ops/sec ±3.21% (82 runs sampled) - * MultiPointsIsNotContainedByLine x 5,210,528 ops/sec ±3.21% (74 runs sampled) - * PointIsNotContainedByLine x 7,324,482 ops/sec ±4.22% (84 runs sampled) - * PointIsNotContainedByLineBecauseOnEnd x 6,024,271 ops/sec ±5.04% (78 runs sampled) - * PointIsNotContainedBYMultiPoint x 10,063,229 ops/sec ±3.50% (80 runs sampled) - * PointIsNotContainedByPolygon x 2,204,858 ops/sec ±3.03% (80 runs sampled) - * PointOnPolygonBoundary x 2,387,408 ops/sec ±2.47% (83 runs sampled) - * PolygonIsNotContainedByPolygon x 1,999,776 ops/sec ±3.20% (84 runs sampled) - * LineIsContainedByLine x 3,434,699 ops/sec ±3.43% (82 runs sampled) - * LineIsContainedByPolygon x 853,234 ops/sec ±2.43% (79 runs sampled) - * MultiPointIsContainedByPolygonBoundary x 1,197,014 ops/sec ±1.89% (85 runs sampled) - * MultiPointsContainedByMultiPoints x 6,601,619 ops/sec ±2.44% (80 runs sampled) - * MultipointsIsContainedByLine x 5,843,279 ops/sec ±2.37% (82 runs sampled) - * PointInsidePolygonBoundary x 2,110,993 ops/sec ±3.84% (79 runs sampled) - * PointIsContainedByLine x 7,436,720 ops/sec ±2.74% (80 runs sampled) - * PointIsContainedByMultiPoint x 10,256,333 ops/sec ±4.22% (75 runs sampled) - * PolygonIsContainedByPolygon x 757,885 ops/sec ±2.61% (82 runs sampled) - * PolygonsExactSameShape x 758,328 ops/sec ±2.27% (86 runs sampled) + * LineIsNotContainedByLine x 4,398,295 ops/sec ±1.43% (84 runs sampled) + * LineIsNotContainedByPolygon x 1,916,541 ops/sec ±3.03% (84 runs sampled) + * LineIsNotContainedByPolygonBoundary x 721,394 ops/sec ±3.84% (77 runs sampled) + * MultiPointAllOnBoundaryIsNotContainedByPolygon x 2,190,982 ops/sec ±2.56% (89 runs sampled) + * MultiPointIsNotContainedByMultiPoint x 7,368,141 ops/sec ±1.02% (90 runs sampled) + * MultiPointIsNotContainedByPolygon x 2,150,014 ops/sec ±0.92% (88 runs sampled) + * MultiPointsIsNotContainedByLine x 4,678,701 ops/sec ±0.88% (84 runs sampled) + * MultiPointsOnLineEndsIsNotContainedByLine x 3,713,593 ops/sec ±5.79% (86 runs sampled) + * PointIsNotContainedByLine x 6,149,162 ops/sec ±5.08% (82 runs sampled) + * PointIsNotContainedByLineBecauseOnEnd x 6,491,086 ops/sec ±0.79% (89 runs sampled) + * PointIsNotContainedBYMultiPoint x 10,046,634 ops/sec ±0.55% (92 runs sampled) + * PointIsNotContainedByPolygon x 2,310,881 ops/sec ±1.45% (88 runs sampled) + * PointOnEndIsContainedByLinestring x 6,252,890 ops/sec ±2.74% (79 runs sampled) + * PointOnPolygonBoundary x 2,607,654 ops/sec ±0.88% (90 runs sampled) + * PolygonIsNotContainedByPolygon x 1,706,009 ops/sec ±2.14% (87 runs sampled) + * LineIsContainedByLine x 4,310,811 ops/sec ±1.42% (89 runs sampled) + * LineIsContainedByPolygon x 1,101,408 ops/sec ±3.09% (89 runs sampled) + * LineIsContainedByPolygonWithNoInternalVertices x 1,153,415 ops/sec ±1.00% (88 runs sampled) + * LinesExactSame x 3,881,843 ops/sec ±3.83% (91 runs sampled) + * MultiPointIsContainedByPolygonBoundary x 1,262,263 ops/sec ±2.75% (89 runs sampled) + * MultiPointsContainedByMultiPoints x 7,074,094 ops/sec ±3.32% (92 runs sampled) + * MultipointsIsContainedByLine x 4,909,852 ops/sec ±2.85% (92 runs sampled) + * PointInsidePolygonBoundary x 2,323,817 ops/sec ±3.11% (88 runs sampled) + * PointIsContainedByLine x 7,894,080 ops/sec ±3.41% (89 runs sampled) + * PointIsContainedByMultiPoint x 11,832,775 ops/sec ±2.13% (89 runs sampled) + * PolygonIsContainedByPolygon x 1,907,608 ops/sec ±5.67% (87 runs sampled) + * PolygonsExactSameShape x 1,578,745 ops/sec ±7.73% (76 runs sampled) */ const suite = new Benchmark.Suite('turf-boolean-contains'); glob.sync(path.join(__dirname, 'test', '**', '*.geojson')).forEach(filepath => { diff --git a/packages/turf-boolean-contains/index.d.ts b/packages/turf-boolean-contains/index.d.ts index 17629c4481..eb796fe44b 100644 --- a/packages/turf-boolean-contains/index.d.ts +++ b/packages/turf-boolean-contains/index.d.ts @@ -5,6 +5,6 @@ type Feature = GeoJSON.Feature | GeoJSON.GeometryObject; /** * http://turfjs.org/docs/#boolean-contains */ -declare function contains(feature1: Feature, feature2: Feature): boolean; -declare namespace contains { } -export = contains; +declare function booleanContains(feature1: Feature, feature2: Feature): boolean; +declare namespace booleanContains { } +export = booleanContains; diff --git a/packages/turf-boolean-contains/index.js b/packages/turf-boolean-contains/index.js index d311cd8823..6014a24858 100644 --- a/packages/turf-boolean-contains/index.js +++ b/packages/turf-boolean-contains/index.js @@ -1,4 +1,5 @@ var inside = require('@turf/inside'); +var calcBbox = require('@turf/bbox'); var invariant = require('@turf/invariant'); var getGeom = invariant.getGeom; var getCoords = invariant.getCoords; @@ -60,7 +61,7 @@ module.exports = function (feature1, feature2) { case 'LineString': switch (type2) { case 'Point': - return isPointOnLine(geom1, geom2); + return isPointOnLine(geom1, geom2, true); case 'LineString': return isLineOnLine(geom1, geom2); case 'MultiPoint': @@ -74,7 +75,7 @@ module.exports = function (feature1, feature2) { case 'LineString': return isLineInPoly(geom1, geom2); case 'Polygon': - return isPolyInPoly(feature2, feature1); + return isPolyInPoly(geom1, geom2); case 'MultiPoint': return isMultiPointInPoly(geom1, geom2); } @@ -115,11 +116,11 @@ function isMultiPointInMultiPoint(multiPoint1, multiPoint2) { } // http://stackoverflow.com/a/11908158/1979085 -function isPointOnLine(lineString, point) { +function isPointOnLine(lineString, point, excEndPoints) { var output = false; for (var i = 0; i < lineString.coordinates.length - 1; i++) { var incEndVertices = true; - if (i === 0 || i === lineString.coordinates.length - 2) { + if ((i === 0 || i === lineString.coordinates.length - 2) && excEndPoints) { incEndVertices = false; } if (isPointOnLineSegment(lineString.coordinates[i], lineString.coordinates[i + 1], point.coordinates, incEndVertices)) { @@ -132,14 +133,14 @@ function isPointOnLine(lineString, point) { function isMultiPointOnLine(lineString, multiPoint) { var output = true; + var foundAnInteriorPoint = false; for (var i = 0; i < multiPoint.coordinates.length; i++) { var pointIsOnLine = false; for (var i2 = 0; i2 < lineString.coordinates.length - 1; i2++) { - var incEndVertices = true; - if (i2 === 0 || i2 === lineString.coordinates.length - 2) { - incEndVertices = false; - } - if (isPointOnLineSegment(lineString.coordinates[i2], lineString.coordinates[i2 + 1], multiPoint.coordinates[i], incEndVertices)) { + if (isPointOnLineSegment(lineString.coordinates[i2], lineString.coordinates[i2 + 1], multiPoint.coordinates[i], true)) { + if (!foundAnInteriorPoint && isPointOnLineSegment(lineString.coordinates[i2], lineString.coordinates[i2 + 1], multiPoint.coordinates[i], false)) { + foundAnInteriorPoint = true; + } pointIsOnLine = true; break; } @@ -149,13 +150,13 @@ function isMultiPointOnLine(lineString, multiPoint) { break; } } - return output; + return output && foundAnInteriorPoint; } function isMultiPointInPoly(polygon, multiPoint) { var output = true; for (var i = 0; i < multiPoint.coordinates.length; i++) { - var isInside = inside(multiPoint.coordinates[1], polygon); + var isInside = inside(multiPoint.coordinates[1], polygon, true); if (!isInside) { output = false; break; @@ -167,36 +168,29 @@ function isMultiPointInPoly(polygon, multiPoint) { function isLineOnLine(lineString1, lineString2) { var output = true; for (var i = 0; i < lineString2.coordinates.length; i++) { - var checkLineCoords = isPointOnLine(lineString1, {type: 'Point', coordinates: lineString2.coordinates[i]}); + var checkLineCoords = isPointOnLine(lineString1, {type: 'Point', coordinates: lineString2.coordinates[i]}, false); if (!checkLineCoords) { output = false; break; } } - if (output) { - if (compareCoords(lineString1.coordinates[0], lineString2.coordinates[0]) || - compareCoords(lineString1.coordinates[lineString1.coordinates.length - 1], lineString2.coordinates[lineString2.coordinates.length - 1])) { - output = false; - } - } return output; } function isLineInPoly(polygon, linestring) { - var output = true; - var foundInternalPoint = false; - for (var i = 0; i < linestring.coordinates.length; i++) { - var isInside = null; - if (!foundInternalPoint) { - isInside = inside(linestring.coordinates[i], polygon); - } else { - isInside = inside(linestring.coordinates[i], polygon, true); - } - if (isInside) { - foundInternalPoint = true; - } - if (!isInside) { - output = false; + var output = false; + var i = 0; + var lineLength = linestring.coordinates.length; + + var polyBbox = calcBbox(polygon); + var lineBbox = calcBbox(linestring); + if (!doBBoxOverlap(polyBbox, lineBbox)) { + return false; + } + for (i; i < lineLength - 1; i++) { + var midPoint = getMidpoint(linestring.coordinates[i], linestring.coordinates[i + 1]); + if (inside({type: 'Point', coordinates: midPoint}, polygon, true)) { + output = true; break; } } @@ -214,15 +208,10 @@ function isLineInPoly(polygon, linestring) { * @returns {Boolean} true/false */ function isPolyInPoly(feature1, feature2) { - var coords = getCoords(feature1)[0]; - var ring = getCoords(feature2)[0]; - var bbox = feature2.bbox; - - // check if outer coordinates is inside outer ring - for (var i = 0; i < coords.length; i++) { - // 3x performance increase if BBox is present - if (bbox && !inBBox(coords[i], bbox)) return false; - if (!inRing(coords[i], ring)) return false; + var poly1Bbox = calcBbox(feature1); + var poly2Bbox = calcBbox(feature2); + if (!doBBoxOverlap(poly1Bbox, poly2Bbox)) { + return false; } return true; } @@ -303,6 +292,14 @@ function inBBox(pt, bbox) { bbox[3] >= pt[1]; } +function doBBoxOverlap(bbox1, bbox2) { + if (bbox1[0] > bbox2[0]) return false; + if (bbox1[2] < bbox2[2]) return false; + if (bbox1[1] > bbox2[1]) return false; + if (bbox1[3] < bbox2[3]) return false; + return true; +} + /** * compareCoords * @@ -314,3 +311,7 @@ function inBBox(pt, bbox) { function compareCoords(pair1, pair2) { return pair1[0] === pair2[0] && pair1[1] === pair2[1]; } + +function getMidpoint(pair1, pair2) { + return [(pair1[0] + pair2[0]) / 2, (pair1[1] + pair2[1]) / 2]; +} diff --git a/packages/turf-boolean-contains/package.json b/packages/turf-boolean-contains/package.json index 1cb8e42825..a317ae9364 100644 --- a/packages/turf-boolean-contains/package.json +++ b/packages/turf-boolean-contains/package.json @@ -40,6 +40,7 @@ "tape": "^4.6.3" }, "dependencies": { + "@turf/bbox": "^4.4.0", "@turf/inside": "^4.2.0", "@turf/invariant": "^4.2.0" } diff --git a/packages/turf-boolean-contains/test/false/MultiPointAllOnBoundaryIsNotContainedByPolygon.geojson b/packages/turf-boolean-contains/test/false/MultiPointAllOnBoundaryIsNotContainedByPolygon.geojson new file mode 100644 index 0000000000..60b5f974c6 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/MultiPointAllOnBoundaryIsNotContainedByPolygon.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1,1],[1,10]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/MultiPointsOnLineEndsIsNotContainedByLine.geojson b/packages/turf-boolean-contains/test/false/MultiPointsOnLineEndsIsNotContainedByLine.geojson new file mode 100644 index 0000000000..7ce31b67f4 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/MultiPointsOnLineEndsIsNotContainedByLine.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "MultiPoint", + "coordinates": [[1, 1], [1, 4]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/false/PointOnEndIsContainedByLinestring.geojson b/packages/turf-boolean-contains/test/false/PointOnEndIsContainedByLinestring.geojson new file mode 100644 index 0000000000..ee52d798b9 --- /dev/null +++ b/packages/turf-boolean-contains/test/false/PointOnEndIsContainedByLinestring.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [1, 1] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/LineIsContainedByPolygonWithNoInternalVertices.geojson b/packages/turf-boolean-contains/test/true/LineIsContainedByPolygonWithNoInternalVertices.geojson new file mode 100644 index 0000000000..be16f95cd2 --- /dev/null +++ b/packages/turf-boolean-contains/test/true/LineIsContainedByPolygonWithNoInternalVertices.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Polygon", + "coordinates": [[[1, 1], [1, 10], [10, 10], [10, 1], [1, 1]]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [10,10]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/LinesExactSame.geojson b/packages/turf-boolean-contains/test/true/LinesExactSame.geojson new file mode 100644 index 0000000000..deb926d483 --- /dev/null +++ b/packages/turf-boolean-contains/test/true/LinesExactSame.geojson @@ -0,0 +1,21 @@ +{ + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + }, + { + "type": "Feature", + "properties": {}, + "geometry": { + "type": "LineString", + "coordinates": [[1, 1], [1, 2], [1, 3], [1, 4]] + } + } + ] +} \ No newline at end of file diff --git a/packages/turf-boolean-contains/test/true/MultipointsIsContainedByLine.geojson b/packages/turf-boolean-contains/test/true/MultipointsIsContainedByLine.geojson index 7e0b98ce92..19a2fe9707 100644 --- a/packages/turf-boolean-contains/test/true/MultipointsIsContainedByLine.geojson +++ b/packages/turf-boolean-contains/test/true/MultipointsIsContainedByLine.geojson @@ -14,7 +14,7 @@ "properties": {}, "geometry": { "type": "MultiPoint", - "coordinates": [[1, 1.2], [1, 1.5]] + "coordinates": [[1, 1], [1, 1.5]] } } ] diff --git a/packages/turf-boolean-contains/test/true/PolygonIsContainedByPolygon.geojson b/packages/turf-boolean-contains/test/true/PolygonIsContainedByPolygon.geojson index eea0287949..8fd689e7e5 100644 --- a/packages/turf-boolean-contains/test/true/PolygonIsContainedByPolygon.geojson +++ b/packages/turf-boolean-contains/test/true/PolygonIsContainedByPolygon.geojson @@ -14,7 +14,7 @@ "properties": {}, "geometry": { "type": "Polygon", - "coordinates": [[[1, 1], [1, 2], [1, 3], [1, 4], [1, 1]]] + "coordinates": [[[1, 1], [2, 2], [3, 2], [1, 1]]] } } ] From 4a40b786a179b6da80952109da0b17f6c0c9b72d Mon Sep 17 00:00:00 2001 From: Rowan Winsemius Date: Sun, 18 Jun 2017 23:10:40 +1000 Subject: [PATCH 3/5] Removed ununsed methods --- packages/turf-boolean-contains/index.js | 41 ------------------------- 1 file changed, 41 deletions(-) diff --git a/packages/turf-boolean-contains/index.js b/packages/turf-boolean-contains/index.js index 6014a24858..d7cadc933d 100644 --- a/packages/turf-boolean-contains/index.js +++ b/packages/turf-boolean-contains/index.js @@ -251,47 +251,6 @@ function isPointOnLineSegment(lineSegmentStart, lineSegmentEnd, point, incEnd) { } } -/** - * inRing - @turf/inside - * - * @private - * @param {[number, number]} pt [x,y] - * @param {Array<[number, number]>} ring [[x,y], [x,y],..] - * @param {boolean} ignoreBoundary ignoreBoundary - * @returns {boolean} inRing - */ -function inRing(pt, ring, ignoreBoundary) { - var isInside = false; - if (ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]) ring = ring.slice(0, ring.length - 1); - - for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) { - var xi = ring[i][0], yi = ring[i][1]; - var xj = ring[j][0], yj = ring[j][1]; - var onBoundary = (pt[1] * (xi - xj) + yi * (xj - pt[0]) + yj * (pt[0] - xi) === 0) && - ((xi - pt[0]) * (xj - pt[0]) <= 0) && ((yi - pt[1]) * (yj - pt[1]) <= 0); - if (onBoundary) return !ignoreBoundary; - var intersect = ((yi > pt[1]) !== (yj > pt[1])) && - (pt[0] < (xj - xi) * (pt[1] - yi) / (yj - yi) + xi); - if (intersect) isInside = !isInside; - } - return isInside; -} - -/** - * inBBox - @turf/inside - * - * @private - * @param {[number, number]} pt point [x,y] - * @param {[number, number, number, number]} bbox BBox [west, south, east, north] - * @returns {boolean} true/false if point is inside BBox - */ -function inBBox(pt, bbox) { - return bbox[0] <= pt[0] && - bbox[1] <= pt[1] && - bbox[2] >= pt[0] && - bbox[3] >= pt[1]; -} - function doBBoxOverlap(bbox1, bbox2) { if (bbox1[0] > bbox2[0]) return false; if (bbox1[2] < bbox2[2]) return false; From 0489bcec2f57c9bb7d7a50f3baf98ba0be2798c9 Mon Sep 17 00:00:00 2001 From: Denis Date: Sun, 18 Jun 2017 11:50:42 -0400 Subject: [PATCH 4/5] Update package.json --- packages/turf-boolean-contains/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/turf-boolean-contains/package.json b/packages/turf-boolean-contains/package.json index a317ae9364..311a477074 100644 --- a/packages/turf-boolean-contains/package.json +++ b/packages/turf-boolean-contains/package.json @@ -33,7 +33,6 @@ }, "homepage": "https://github.com/Turfjs/turf", "devDependencies": { - "@turf/bbox": "^4.2.0", "benchmark": "^2.1.4", "glob": "^7.1.1", "load-json-file": "^2.0.0", From 24524db19300d47dbcfca9c54b0c27c7515f27b8 Mon Sep 17 00:00:00 2001 From: Denis Date: Mon, 19 Jun 2017 10:37:20 -0400 Subject: [PATCH 5/5] Add shapely tests --- packages/turf-boolean-contains/index.js | 12 ++-- packages/turf-boolean-contains/test.js | 20 +++++- packages/turf-boolean-contains/yarn.lock | 72 +++------------------- packages/turf-boolean-crosses/package.json | 1 + packages/turf-boolean-crosses/yarn.lock | 25 +++----- scripts/boolean-shapely.py | 2 +- 6 files changed, 43 insertions(+), 89 deletions(-) diff --git a/packages/turf-boolean-contains/index.js b/packages/turf-boolean-contains/index.js index d7cadc933d..3994ee98e6 100644 --- a/packages/turf-boolean-contains/index.js +++ b/packages/turf-boolean-contains/index.js @@ -48,16 +48,18 @@ module.exports = function (feature1, feature2) { switch (type2) { case 'Point': return compareCoords(coords1, coords2); + default: + throw new Error('feature2 ' + type2 + ' geometry not supported'); } - throw new Error('feature2 ' + type2 + ' geometry not supported'); case 'MultiPoint': switch (type2) { case 'Point': return isPointInMultiPoint(geom1, geom2); case 'MultiPoint': return isMultiPointInMultiPoint(geom1, geom2); + default: + throw new Error('feature2 ' + type2 + ' geometry not supported'); } - throw new Error('feature2 ' + type2 + ' geometry not supported'); case 'LineString': switch (type2) { case 'Point': @@ -66,8 +68,9 @@ module.exports = function (feature1, feature2) { return isLineOnLine(geom1, geom2); case 'MultiPoint': return isMultiPointOnLine(geom1, geom2); + default: + throw new Error('feature2 ' + type2 + ' geometry not supported'); } - throw new Error('feature2 ' + type2 + ' geometry not supported'); case 'Polygon': switch (type2) { case 'Point': @@ -78,8 +81,9 @@ module.exports = function (feature1, feature2) { return isPolyInPoly(geom1, geom2); case 'MultiPoint': return isMultiPointInPoly(geom1, geom2); + default: + throw new Error('feature2 ' + type2 + ' geometry not supported'); } - throw new Error('feature2 ' + type2 + ' geometry not supported'); default: throw new Error('feature1 ' + type1 + ' geometry not supported'); } diff --git a/packages/turf-boolean-contains/test.js b/packages/turf-boolean-contains/test.js index fb0a59fb5d..122689db1c 100644 --- a/packages/turf-boolean-contains/test.js +++ b/packages/turf-boolean-contains/test.js @@ -2,6 +2,8 @@ const glob = require('glob'); const path = require('path'); const test = require('tape'); const load = require('load-json-file'); +const {point, lineString} = require('@turf/helpers'); +const shapely = require('../../scripts/boolean-shapely'); const contains = require('./'); test('turf-boolean-contains#fixtures', t => { @@ -10,14 +12,28 @@ test('turf-boolean-contains#fixtures', t => { const {name} = path.parse(filepath); const geojson = load.sync(filepath); const [feature1, feature2] = geojson.features; - t.true(contains(feature1, feature2), '[true] ' + name); + const result = contains(feature1, feature2); + + if (process.env.SHAPELY) shapely('contains', feature1, feature2).then(result => t.true(result, '[true] shapely - ' + name)); + t.true(result, '[true] ' + name); }); // False Fixtures glob.sync(path.join(__dirname, 'test', 'false', '*.geojson')).forEach(filepath => { const {name} = path.parse(filepath); const geojson = load.sync(filepath); const [feature1, feature2] = geojson.features; - t.false(contains(feature1, feature2), '[false] ' + name); + const result = contains(feature1, feature2); + + if (process.env.SHAPELY) shapely('contains', feature1, feature2).then(result => t.false(result, '[false] shapely - ' + name)); + t.false(result, '[false] ' + name); }); t.end(); }); + +test('turf-boolean-contains -- throws', t => { + const pt1 = point([0, 0]); + const pt2 = point([0, 0]); + + t.assert(contains(pt1.geometry, pt2.geometry)); + t.end(); +}); diff --git a/packages/turf-boolean-contains/yarn.lock b/packages/turf-boolean-contains/yarn.lock index 8680049857..1f1de0f4fc 100644 --- a/packages/turf-boolean-contains/yarn.lock +++ b/packages/turf-boolean-contains/yarn.lock @@ -2,25 +2,11 @@ # yarn lockfile v1 -"@turf/bbox@^3.10.5": - version "3.14.0" - resolved "https://registry.yarnpkg.com/@turf/bbox/-/bbox-3.14.0.tgz#cee5f396dde78aca9cede05e1122db18bc504635" +"@turf/bbox@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@turf/bbox/-/bbox-4.4.0.tgz#3149458eb41404427cf786a90fb3680a0e8aab55" dependencies: - "@turf/meta" "^3.14.0" - -"@turf/bbox@^4.2.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@turf/bbox/-/bbox-4.3.0.tgz#644c4b745172d21aae70d1584b2a7866f1040865" - dependencies: - "@turf/meta" "^4.3.0" - -"@turf/helpers@^3.10.5": - version "3.13.0" - resolved "https://registry.yarnpkg.com/@turf/helpers/-/helpers-3.13.0.tgz#d06078a1464cf56cdb7ea624ea1e13a71b88b806" - -"@turf/helpers@^4.2.0", "@turf/helpers@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@turf/helpers/-/helpers-4.3.0.tgz#7b2f733aa0eb3ea1f07d467ac02ede00cc6cde0d" + "@turf/meta" "^4.4.0" "@turf/inside@^4.2.0": version "4.3.0" @@ -32,32 +18,9 @@ version "4.3.0" resolved "https://registry.yarnpkg.com/@turf/invariant/-/invariant-4.3.0.tgz#5bd1ce6ae51b1229dc0dc7d09d973fabae49af89" -"@turf/line-overlap@^4.2.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@turf/line-overlap/-/line-overlap-4.3.0.tgz#f0572d3a3f536a35055d857099b5d1549cfd0074" - dependencies: - "@turf/helpers" "^4.3.0" - "@turf/invariant" "^4.3.0" - "@turf/line-segment" "^4.3.0" - "@turf/meta" "^4.3.0" - deep-equal "^1.0.1" - geojson-rbush "^1.0.1" - -"@turf/line-segment@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@turf/line-segment/-/line-segment-4.3.0.tgz#7835209227f3c0712ec549c6f51af72394c638ab" - dependencies: - "@turf/helpers" "^4.3.0" - "@turf/invariant" "^4.3.0" - "@turf/meta" "^4.3.0" - -"@turf/meta@^3.10.5", "@turf/meta@^3.14.0": - version "3.14.0" - resolved "https://registry.yarnpkg.com/@turf/meta/-/meta-3.14.0.tgz#8d3050c1a0f44bf406a633b6bd28c510f7bcee27" - -"@turf/meta@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@turf/meta/-/meta-4.3.0.tgz#eb11dd2c2511524258123767fe0f5c3bd963e8d7" +"@turf/meta@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@turf/meta/-/meta-4.4.0.tgz#4fa25d4cc0525bd4cdbaf4ff68a6f8ae81f1975f" balanced-match@^0.4.1: version "0.4.2" @@ -81,7 +44,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -deep-equal@^1.0.1, deep-equal@~1.0.1: +deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" @@ -137,15 +100,6 @@ function-bind@^1.0.2, function-bind@^1.1.0, function-bind@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" -geojson-rbush@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/geojson-rbush/-/geojson-rbush-1.0.1.tgz#450559bc18457e725191ac9acbbe0a8b5e18ddae" - dependencies: - "@turf/bbox" "^3.10.5" - "@turf/helpers" "^3.10.5" - "@turf/meta" "^3.10.5" - rbush "^2.0.1" - glob@^7.1.1, glob@~7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -259,16 +213,6 @@ platform@^1.3.3: version "1.3.4" resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.4.tgz#6f0fb17edaaa48f21442b3a975c063130f1c3ebd" -quickselect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-1.0.0.tgz#02630818f9aae4ecab26f0103f98d061c17c58f3" - -rbush@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/rbush/-/rbush-2.0.1.tgz#4cfaca28c3064bc0ee75431a1b79990e875eefa9" - dependencies: - quickselect "^1.0.0" - resolve@~1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" diff --git a/packages/turf-boolean-crosses/package.json b/packages/turf-boolean-crosses/package.json index bf072b3372..c145830c1d 100644 --- a/packages/turf-boolean-crosses/package.json +++ b/packages/turf-boolean-crosses/package.json @@ -36,6 +36,7 @@ "benchmark": "^2.1.4", "glob": "^7.1.2", "load-json-file": "^2.0.0", + "python-shell": "^0.4.0", "tape": "^4.6.3" }, "dependencies": { diff --git a/packages/turf-boolean-crosses/yarn.lock b/packages/turf-boolean-crosses/yarn.lock index 375ee3a8f0..a088d5a1bb 100644 --- a/packages/turf-boolean-crosses/yarn.lock +++ b/packages/turf-boolean-crosses/yarn.lock @@ -22,11 +22,7 @@ dependencies: "@turf/invariant" "^4.3.0" -"@turf/invariant@^4.3.0": - version "4.3.0" - resolved "https://registry.yarnpkg.com/@turf/invariant/-/invariant-4.3.0.tgz#5bd1ce6ae51b1229dc0dc7d09d973fabae49af89" - -"@turf/invariant@^4.4.0": +"@turf/invariant@^4.3.0", "@turf/invariant@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@turf/invariant/-/invariant-4.4.0.tgz#aac0afb840ae40908f9c80393f416222dcf79c32" @@ -150,7 +146,7 @@ geojson-rbush@^1.0.1: "@turf/meta" "^3.10.5" rbush "^2.0.1" -glob@^7.1.2: +glob@^7.1.2, glob@~7.1.1: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -161,17 +157,6 @@ glob@^7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" -glob@~7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -232,7 +217,7 @@ lodash@^4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -274,6 +259,10 @@ platform@^1.3.3: version "1.3.4" resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.4.tgz#6f0fb17edaaa48f21442b3a975c063130f1c3ebd" +python-shell@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/python-shell/-/python-shell-0.4.0.tgz#259c5470d885292b22e906a57b085f651752f956" + quickselect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-1.0.0.tgz#02630818f9aae4ecab26f0103f98d061c17c58f3" diff --git a/scripts/boolean-shapely.py b/scripts/boolean-shapely.py index d0567d1d2b..ef9920ad7e 100755 --- a/scripts/boolean-shapely.py +++ b/scripts/boolean-shapely.py @@ -12,7 +12,7 @@ def shapely(operation, geometry1, geometry2): if operation == 'crosses': print geometry1.crosses(geometry2) elif operation == 'contains': - print geometry1.conains(geometry2) + print geometry1.contains(geometry2) if __name__ == '__main__': OPERATION = sys.argv[1]