1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283 |
- import distance from "@turf/distance";
- import { feature, featureCollection } from "@turf/helpers";
- import { featureEach } from "@turf/meta";
- import tin from "@turf/tin";
- import dissolve from "./lib/turf-dissolve.js";
- /**
- * Takes a set of {@link Point|points} and returns a concave hull Polygon or MultiPolygon.
- * Internally, this uses [turf-tin](https://github.com/Turfjs/turf-tin) to generate geometries.
- *
- * @name concave
- * @param {FeatureCollection<Point>} points input points
- * @param {Object} [options={}] Optional parameters
- * @param {number} [options.maxEdge=Infinity] the length (in 'units') of an edge necessary for part of the
- * hull to become concave.
- * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers
- * @returns {Feature<(Polygon|MultiPolygon)>|null} a concave hull (null value is returned if unable to compute hull)
- * @example
- * var points = turf.featureCollection([
- * turf.point([-63.601226, 44.642643]),
- * turf.point([-63.591442, 44.651436]),
- * turf.point([-63.580799, 44.648749]),
- * turf.point([-63.573589, 44.641788]),
- * turf.point([-63.587665, 44.64533]),
- * turf.point([-63.595218, 44.64765])
- * ]);
- * var options = {units: 'miles', maxEdge: 1};
- *
- * var hull = turf.concave(points, options);
- *
- * //addToMap
- * var addToMap = [points, hull]
- */
- function concave(points, options) {
- if (options === void 0) { options = {}; }
- var maxEdge = options.maxEdge || Infinity;
- var cleaned = removeDuplicates(points);
- var tinPolys = tin(cleaned);
- // calculate length of all edges and area of all triangles
- // and remove triangles that fail the max length test
- tinPolys.features = tinPolys.features.filter(function (triangle) {
- var pt1 = triangle.geometry.coordinates[0][0];
- var pt2 = triangle.geometry.coordinates[0][1];
- var pt3 = triangle.geometry.coordinates[0][2];
- var dist1 = distance(pt1, pt2, options);
- var dist2 = distance(pt2, pt3, options);
- var dist3 = distance(pt1, pt3, options);
- return dist1 <= maxEdge && dist2 <= maxEdge && dist3 <= maxEdge;
- });
- if (tinPolys.features.length < 1) {
- return null;
- }
- // merge the adjacent triangles
- var dissolved = dissolve(tinPolys);
- // geojson-dissolve always returns a MultiPolygon
- if (dissolved.coordinates.length === 1) {
- dissolved.coordinates = dissolved.coordinates[0];
- dissolved.type = "Polygon";
- }
- return feature(dissolved);
- }
- /**
- * Removes duplicated points in a collection returning a new collection
- *
- * @private
- * @param {FeatureCollection<Point>} points to be cleaned
- * @returns {FeatureCollection<Point>} cleaned set of points
- */
- function removeDuplicates(points) {
- var cleaned = [];
- var existing = {};
- featureEach(points, function (pt) {
- if (!pt.geometry) {
- return;
- }
- var key = pt.geometry.coordinates.join("-");
- if (!Object.prototype.hasOwnProperty.call(existing, key)) {
- cleaned.push(pt);
- existing[key] = true;
- }
- });
- return featureCollection(cleaned);
- }
- export default concave;
|