@turf/mask
Advanced tools
Comparing version 6.4.0 to 6.5.0
@@ -1,6 +0,3 @@ | ||
import rbush from 'rbush'; | ||
import union from '@turf/union'; | ||
import { polygon, featureCollection } from '@turf/helpers'; | ||
import turfBBox from '@turf/bbox'; | ||
import { flattenEach } from '@turf/meta'; | ||
import { polygon, multiPolygon } from '@turf/helpers'; | ||
import polygonClipping from 'polygon-clipping'; | ||
@@ -23,63 +20,38 @@ /** | ||
*/ | ||
function mask(polygon$$1, mask) { | ||
function mask(polygon, mask) { | ||
// Define mask | ||
var maskPolygon = createMask(mask); | ||
// Define polygon | ||
var separated = separatePolygons(polygon$$1); | ||
var polygonOuters = separated[0]; | ||
var polygonInners = separated[1]; | ||
var polygonOuters = null; | ||
if (polygon.type === "FeatureCollection") polygonOuters = unionFc(polygon); | ||
else | ||
polygonOuters = createGeomFromPolygonClippingOutput( | ||
polygonClipping.union(polygon.geometry.coordinates) | ||
); | ||
// Union Outers & Inners | ||
polygonOuters = unionPolygons(polygonOuters); | ||
polygonInners = unionPolygons(polygonInners); | ||
polygonOuters.geometry.coordinates.forEach(function (contour) { | ||
maskPolygon.geometry.coordinates.push(contour[0]); | ||
}); | ||
// Create masked area | ||
var masked = buildMask(maskPolygon, polygonOuters, polygonInners); | ||
return masked; | ||
return maskPolygon; | ||
} | ||
/** | ||
* Build Mask | ||
* | ||
* @private | ||
* @param {Feature<Polygon>} maskPolygon Mask Outer | ||
* @param {FeatureCollection<Polygon>} polygonOuters Polygon Outers | ||
* @param {FeatureCollection<Polygon>} polygonInners Polygon Inners | ||
* @returns {Feature<Polygon>} Feature Polygon | ||
*/ | ||
function buildMask(maskPolygon, polygonOuters, polygonInners) { | ||
var coordinates = []; | ||
coordinates.push(maskPolygon.geometry.coordinates[0]); | ||
flattenEach(polygonOuters, function (feature) { | ||
coordinates.push(feature.geometry.coordinates[0]); | ||
}); | ||
flattenEach(polygonInners, function (feature) { | ||
coordinates.push(feature.geometry.coordinates[0]); | ||
}); | ||
return polygon(coordinates); | ||
function unionFc(fc) { | ||
var unioned = | ||
fc.features.length === 2 | ||
? polygonClipping.union( | ||
fc.features[0].geometry.coordinates, | ||
fc.features[1].geometry.coordinates | ||
) | ||
: polygonClipping.union.apply( | ||
polygonClipping, | ||
fc.features.map(function (f) { | ||
return f.geometry.coordinates; | ||
}) | ||
); | ||
return createGeomFromPolygonClippingOutput(unioned); | ||
} | ||
/** | ||
* Separate Polygons to inners & outers | ||
* | ||
* @private | ||
* @param {FeatureCollection|Feature<Polygon|MultiPolygon>} poly GeoJSON Feature | ||
* @returns {Array<FeatureCollection<Polygon>, FeatureCollection<Polygon>>} Outer & Inner lines | ||
*/ | ||
function separatePolygons(poly) { | ||
var outers = []; | ||
var inners = []; | ||
flattenEach(poly, function (feature) { | ||
var coordinates = feature.geometry.coordinates; | ||
var featureOuter = coordinates[0]; | ||
var featureInner = coordinates.slice(1); | ||
outers.push(polygon([featureOuter])); | ||
featureInner.forEach(function (inner) { | ||
inners.push(polygon([inner])); | ||
}); | ||
}); | ||
return [featureCollection(outers), featureCollection(inners)]; | ||
function createGeomFromPolygonClippingOutput(unioned) { | ||
return multiPolygon(unioned); | ||
} | ||
@@ -108,90 +80,2 @@ | ||
/** | ||
* Union Polygons | ||
* | ||
* @private | ||
* @param {FeatureCollection<Polygon>} polygons collection of polygons | ||
* @returns {FeatureCollection<Polygon>} polygons only apply union if they collide | ||
*/ | ||
function unionPolygons(polygons) { | ||
if (polygons.features.length <= 1) return polygons; | ||
var tree = createIndex(polygons); | ||
var results = []; | ||
var removed = {}; | ||
flattenEach(polygons, function (currentFeature, currentIndex) { | ||
// Exclude any removed features | ||
if (removed[currentIndex]) return true; | ||
// Don't search for itself | ||
tree.remove({ index: currentIndex }, filterByIndex); | ||
removed[currentIndex] = true; | ||
// Keep applying the union operation until no more overlapping features | ||
while (true) { | ||
var bbox = turfBBox(currentFeature); | ||
var search = tree.search({ | ||
minX: bbox[0], | ||
minY: bbox[1], | ||
maxX: bbox[2], | ||
maxY: bbox[3], | ||
}); | ||
if (search.length > 0) { | ||
var polys = search.map(function (item) { | ||
removed[item.index] = true; | ||
tree.remove({ index: item.index }, filterByIndex); | ||
return item.geojson; | ||
}); | ||
for (var i = 0, l = polys.length; i < l; i++) { | ||
currentFeature = union(currentFeature, polys[i]); | ||
} | ||
} | ||
// Done | ||
if (search.length === 0) break; | ||
} | ||
results.push(currentFeature); | ||
}); | ||
return featureCollection(results); | ||
} | ||
/** | ||
* Filter by Index - RBush helper function | ||
* | ||
* @private | ||
* @param {Object} a remove item | ||
* @param {Object} b search item | ||
* @returns {boolean} true if matches | ||
*/ | ||
function filterByIndex(a, b) { | ||
return a.index === b.index; | ||
} | ||
/** | ||
* Create RBush Tree Index | ||
* | ||
* @private | ||
* @param {FeatureCollection<any>} features GeoJSON FeatureCollection | ||
* @returns {RBush} RBush Tree | ||
*/ | ||
function createIndex(features) { | ||
var tree = rbush(); | ||
var load = []; | ||
flattenEach(features, function (feature, index) { | ||
var bbox = turfBBox(feature); | ||
load.push({ | ||
minX: bbox[0], | ||
minY: bbox[1], | ||
maxX: bbox[2], | ||
maxY: bbox[3], | ||
geojson: feature, | ||
index: index, | ||
}); | ||
}); | ||
tree.load(load); | ||
return tree; | ||
} | ||
export default mask; |
'use strict'; | ||
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } | ||
var rbush = _interopDefault(require('rbush')); | ||
var union = _interopDefault(require('@turf/union')); | ||
var helpers = require('@turf/helpers'); | ||
var turfBBox = _interopDefault(require('@turf/bbox')); | ||
var meta = require('@turf/meta'); | ||
var polygonClipping = require('polygon-clipping'); | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
var polygonClipping__default = /*#__PURE__*/_interopDefaultLegacy(polygonClipping); | ||
/** | ||
@@ -31,59 +30,34 @@ * Takes any type of {@link Polygon|polygon} and an optional mask and returns a {@link Polygon|polygon} exterior ring with holes. | ||
// Define polygon | ||
var separated = separatePolygons(polygon); | ||
var polygonOuters = separated[0]; | ||
var polygonInners = separated[1]; | ||
var polygonOuters = null; | ||
if (polygon.type === "FeatureCollection") polygonOuters = unionFc(polygon); | ||
else | ||
polygonOuters = createGeomFromPolygonClippingOutput( | ||
polygonClipping__default['default'].union(polygon.geometry.coordinates) | ||
); | ||
// Union Outers & Inners | ||
polygonOuters = unionPolygons(polygonOuters); | ||
polygonInners = unionPolygons(polygonInners); | ||
polygonOuters.geometry.coordinates.forEach(function (contour) { | ||
maskPolygon.geometry.coordinates.push(contour[0]); | ||
}); | ||
// Create masked area | ||
var masked = buildMask(maskPolygon, polygonOuters, polygonInners); | ||
return masked; | ||
return maskPolygon; | ||
} | ||
/** | ||
* Build Mask | ||
* | ||
* @private | ||
* @param {Feature<Polygon>} maskPolygon Mask Outer | ||
* @param {FeatureCollection<Polygon>} polygonOuters Polygon Outers | ||
* @param {FeatureCollection<Polygon>} polygonInners Polygon Inners | ||
* @returns {Feature<Polygon>} Feature Polygon | ||
*/ | ||
function buildMask(maskPolygon, polygonOuters, polygonInners) { | ||
var coordinates = []; | ||
coordinates.push(maskPolygon.geometry.coordinates[0]); | ||
meta.flattenEach(polygonOuters, function (feature) { | ||
coordinates.push(feature.geometry.coordinates[0]); | ||
}); | ||
meta.flattenEach(polygonInners, function (feature) { | ||
coordinates.push(feature.geometry.coordinates[0]); | ||
}); | ||
return helpers.polygon(coordinates); | ||
function unionFc(fc) { | ||
var unioned = | ||
fc.features.length === 2 | ||
? polygonClipping__default['default'].union( | ||
fc.features[0].geometry.coordinates, | ||
fc.features[1].geometry.coordinates | ||
) | ||
: polygonClipping__default['default'].union.apply( | ||
polygonClipping__default['default'], | ||
fc.features.map(function (f) { | ||
return f.geometry.coordinates; | ||
}) | ||
); | ||
return createGeomFromPolygonClippingOutput(unioned); | ||
} | ||
/** | ||
* Separate Polygons to inners & outers | ||
* | ||
* @private | ||
* @param {FeatureCollection|Feature<Polygon|MultiPolygon>} poly GeoJSON Feature | ||
* @returns {Array<FeatureCollection<Polygon>, FeatureCollection<Polygon>>} Outer & Inner lines | ||
*/ | ||
function separatePolygons(poly) { | ||
var outers = []; | ||
var inners = []; | ||
meta.flattenEach(poly, function (feature) { | ||
var coordinates = feature.geometry.coordinates; | ||
var featureOuter = coordinates[0]; | ||
var featureInner = coordinates.slice(1); | ||
outers.push(helpers.polygon([featureOuter])); | ||
featureInner.forEach(function (inner) { | ||
inners.push(helpers.polygon([inner])); | ||
}); | ||
}); | ||
return [helpers.featureCollection(outers), helpers.featureCollection(inners)]; | ||
function createGeomFromPolygonClippingOutput(unioned) { | ||
return helpers.multiPolygon(unioned); | ||
} | ||
@@ -112,90 +86,3 @@ | ||
/** | ||
* Union Polygons | ||
* | ||
* @private | ||
* @param {FeatureCollection<Polygon>} polygons collection of polygons | ||
* @returns {FeatureCollection<Polygon>} polygons only apply union if they collide | ||
*/ | ||
function unionPolygons(polygons) { | ||
if (polygons.features.length <= 1) return polygons; | ||
var tree = createIndex(polygons); | ||
var results = []; | ||
var removed = {}; | ||
meta.flattenEach(polygons, function (currentFeature, currentIndex) { | ||
// Exclude any removed features | ||
if (removed[currentIndex]) return true; | ||
// Don't search for itself | ||
tree.remove({ index: currentIndex }, filterByIndex); | ||
removed[currentIndex] = true; | ||
// Keep applying the union operation until no more overlapping features | ||
while (true) { | ||
var bbox = turfBBox(currentFeature); | ||
var search = tree.search({ | ||
minX: bbox[0], | ||
minY: bbox[1], | ||
maxX: bbox[2], | ||
maxY: bbox[3], | ||
}); | ||
if (search.length > 0) { | ||
var polys = search.map(function (item) { | ||
removed[item.index] = true; | ||
tree.remove({ index: item.index }, filterByIndex); | ||
return item.geojson; | ||
}); | ||
for (var i = 0, l = polys.length; i < l; i++) { | ||
currentFeature = union(currentFeature, polys[i]); | ||
} | ||
} | ||
// Done | ||
if (search.length === 0) break; | ||
} | ||
results.push(currentFeature); | ||
}); | ||
return helpers.featureCollection(results); | ||
} | ||
/** | ||
* Filter by Index - RBush helper function | ||
* | ||
* @private | ||
* @param {Object} a remove item | ||
* @param {Object} b search item | ||
* @returns {boolean} true if matches | ||
*/ | ||
function filterByIndex(a, b) { | ||
return a.index === b.index; | ||
} | ||
/** | ||
* Create RBush Tree Index | ||
* | ||
* @private | ||
* @param {FeatureCollection<any>} features GeoJSON FeatureCollection | ||
* @returns {RBush} RBush Tree | ||
*/ | ||
function createIndex(features) { | ||
var tree = rbush(); | ||
var load = []; | ||
meta.flattenEach(features, function (feature, index) { | ||
var bbox = turfBBox(feature); | ||
load.push({ | ||
minX: bbox[0], | ||
minY: bbox[1], | ||
maxX: bbox[2], | ||
maxY: bbox[3], | ||
geojson: feature, | ||
index: index, | ||
}); | ||
}); | ||
tree.load(load); | ||
return tree; | ||
} | ||
module.exports = mask; | ||
module.exports.default = mask; |
{ | ||
"name": "@turf/mask", | ||
"version": "6.4.0", | ||
"version": "6.5.0", | ||
"description": "turf mask module", | ||
@@ -15,2 +15,3 @@ "author": "Turf Authors", | ||
}, | ||
"funding": "https://opencollective.com/turf", | ||
"publishConfig": { | ||
@@ -57,9 +58,6 @@ "access": "public" | ||
"dependencies": { | ||
"@turf/bbox": "^6.4.0", | ||
"@turf/helpers": "^6.4.0", | ||
"@turf/meta": "^6.4.0", | ||
"@turf/union": "^6.4.0", | ||
"rbush": "^2.0.1" | ||
"@turf/helpers": "^6.5.0", | ||
"polygon-clipping": "^0.15.3" | ||
}, | ||
"gitHead": "1e62773cfc88c627cca8effcb5c14cfb65a905ac" | ||
"gitHead": "5375941072b90d489389db22b43bfe809d5e451e" | ||
} |
@@ -11,4 +11,4 @@ # @turf/mask | ||
- `polygon` **([FeatureCollection][2] \| [Feature][3]<([Polygon][4] \| [MultiPolygon][5])>)** GeoJSON Polygon used as interior rings or holes. | ||
- `mask` **[Feature][3]<[Polygon][4]>?** GeoJSON Polygon used as the exterior ring (if undefined, the world extent is used) | ||
- `polygon` **([FeatureCollection][2] \| [Feature][3]<([Polygon][4] \| [MultiPolygon][5])>)** GeoJSON Polygon used as interior rings or holes. | ||
- `mask` **[Feature][3]<[Polygon][4]>?** GeoJSON Polygon used as the exterior ring (if undefined, the world extent is used) | ||
@@ -18,4 +18,21 @@ **Examples** | ||
```javascript | ||
var polygon = turf.polygon([[[112, -21], [116, -36], [146, -39], [153, -24], [133, -10], [112, -21]]]); | ||
var mask = turf.polygon([[[90, -55], [170, -55], [170, 10], [90, 10], [90, -55]]]); | ||
var polygon = turf.polygon([ | ||
[ | ||
[112, -21], | ||
[116, -36], | ||
[146, -39], | ||
[153, -24], | ||
[133, -10], | ||
[112, -21], | ||
], | ||
]); | ||
var mask = turf.polygon([ | ||
[ | ||
[90, -55], | ||
[170, -55], | ||
[170, 10], | ||
[90, 10], | ||
[90, -55], | ||
], | ||
]); | ||
@@ -25,3 +42,3 @@ var masked = turf.mask(polygon, mask); | ||
//addToMap | ||
var addToMap = [masked] | ||
var addToMap = [masked]; | ||
``` | ||
@@ -32,9 +49,5 @@ | ||
[1]: https://tools.ietf.org/html/rfc7946#section-3.1.6 | ||
[2]: https://tools.ietf.org/html/rfc7946#section-3.3 | ||
[3]: https://tools.ietf.org/html/rfc7946#section-3.2 | ||
[4]: https://tools.ietf.org/html/rfc7946#section-3.1.6 | ||
[5]: https://tools.ietf.org/html/rfc7946#section-3.1.7 | ||
@@ -41,0 +54,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
2
75
9676
159
+ Addedpolygon-clipping@^0.15.3
- Removed@turf/bbox@^6.4.0
- Removed@turf/meta@^6.4.0
- Removed@turf/union@^6.4.0
- Removedrbush@^2.0.1
- Removed@turf/bbox@6.5.0(transitive)
- Removed@turf/invariant@6.5.0(transitive)
- Removed@turf/meta@6.5.0(transitive)
- Removed@turf/union@6.5.0(transitive)
- Removedquickselect@1.1.1(transitive)
- Removedrbush@2.0.2(transitive)
Updated@turf/helpers@^6.5.0