@turf/concave
Advanced tools
Comparing version 6.0.0 to 6.0.1
33
index.js
"use strict"; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
} | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var tin_1 = require("@turf/tin"); | ||
var distance_1 = require("@turf/distance"); | ||
var distance_1 = __importDefault(require("@turf/distance")); | ||
var helpers_1 = require("@turf/helpers"); | ||
var meta_1 = require("@turf/meta"); | ||
var helpers_1 = require("@turf/helpers"); | ||
var turf_dissolve_1 = require("./lib/turf-dissolve"); | ||
var tin_1 = __importDefault(require("@turf/tin")); | ||
var turf_dissolve_1 = __importDefault(require("./lib/turf-dissolve")); | ||
/** | ||
@@ -15,3 +18,4 @@ * Takes a set of {@link Point|points} and returns a concave hull Polygon or MultiPolygon. | ||
* @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 {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 | ||
@@ -37,12 +41,3 @@ * @returns {Feature<(Polygon|MultiPolygon)>|null} a concave hull (null value is returned if unable to compute hull) | ||
if (options === void 0) { options = {}; } | ||
// Optional parameters | ||
options = options || {}; | ||
if (!helpers_1.isObject(options)) | ||
throw new Error('options is invalid'); | ||
// validation | ||
if (!points) | ||
throw new Error('points is required'); | ||
var maxEdge = options.maxEdge || Infinity; | ||
if (!helpers_1.isNumber(maxEdge)) | ||
throw new Error('maxEdge is invalid'); | ||
var cleaned = removeDuplicates(points); | ||
@@ -61,4 +56,5 @@ var tinPolys = tin_1.default(cleaned); | ||
}); | ||
if (tinPolys.features.length < 1) | ||
if (tinPolys.features.length < 1) { | ||
return null; | ||
} | ||
// merge the adjacent triangles | ||
@@ -69,3 +65,3 @@ var dissolved = turf_dissolve_1.default(tinPolys); | ||
dissolved.coordinates = dissolved.coordinates[0]; | ||
dissolved.type = 'Polygon'; | ||
dissolved.type = "Polygon"; | ||
} | ||
@@ -85,5 +81,6 @@ return helpers_1.feature(dissolved); | ||
meta_1.featureEach(points, function (pt) { | ||
if (!pt.geometry) | ||
if (!pt.geometry) { | ||
return; | ||
var key = pt.geometry.coordinates.join('-'); | ||
} | ||
var key = pt.geometry.coordinates.join("-"); | ||
if (!existing.hasOwnProperty(key)) { | ||
@@ -90,0 +87,0 @@ cleaned.push(pt); |
68
index.ts
@@ -1,7 +0,7 @@ | ||
import tin from '@turf/tin'; | ||
import distance from '@turf/distance'; | ||
import { featureEach } from '@turf/meta'; | ||
import { feature, featureCollection, isObject, isNumber, polygon } from '@turf/helpers'; | ||
import { Point, Feature, FeatureCollection, MultiPolygon, Polygon, Units} from '@turf/helpers' | ||
import dissolve from './lib/turf-dissolve'; | ||
import distance from "@turf/distance"; | ||
import { feature, featureCollection, isNumber, isObject, polygon } from "@turf/helpers"; | ||
import { Feature, FeatureCollection, MultiPolygon, Point, Polygon, Units} from "@turf/helpers"; | ||
import { featureEach } from "@turf/meta"; | ||
import tin from "@turf/tin"; | ||
import dissolve from "./lib/turf-dissolve"; | ||
@@ -15,3 +15,4 @@ /** | ||
* @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 {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 | ||
@@ -35,34 +36,27 @@ * @returns {Feature<(Polygon|MultiPolygon)>|null} a concave hull (null value is returned if unable to compute hull) | ||
*/ | ||
function concave(points: FeatureCollection<Point>, options: { | ||
maxEdge?: number, | ||
units?: Units | ||
} = {}): Feature<Polygon | MultiPolygon> { | ||
// Optional parameters | ||
options = options || {}; | ||
if (!isObject(options)) throw new Error('options is invalid'); | ||
function concave( | ||
points: FeatureCollection<Point>, | ||
options: {maxEdge?: number, units?: Units} = {}, | ||
): Feature<Polygon | MultiPolygon> | null { | ||
const maxEdge = options.maxEdge || Infinity; | ||
// validation | ||
if (!points) throw new Error('points is required'); | ||
var maxEdge = options.maxEdge || Infinity; | ||
if (!isNumber(maxEdge)) throw new Error('maxEdge is invalid'); | ||
const cleaned = removeDuplicates(points); | ||
var cleaned = removeDuplicates(points); | ||
var tinPolys = tin(cleaned); | ||
const 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); | ||
tinPolys.features = tinPolys.features.filter((triangle) => { | ||
const pt1 = triangle.geometry.coordinates[0][0]; | ||
const pt2 = triangle.geometry.coordinates[0][1]; | ||
const pt3 = triangle.geometry.coordinates[0][2]; | ||
const dist1 = distance(pt1, pt2, options); | ||
const dist2 = distance(pt2, pt3, options); | ||
const dist3 = distance(pt1, pt3, options); | ||
return (dist1 <= maxEdge && dist2 <= maxEdge && dist3 <= maxEdge); | ||
}); | ||
if (tinPolys.features.length < 1) return null; | ||
if (tinPolys.features.length < 1) { return null; } | ||
// merge the adjacent triangles | ||
var dissolved: any = dissolve(tinPolys); | ||
const dissolved: any = dissolve(tinPolys); | ||
@@ -72,3 +66,3 @@ // geojson-dissolve always returns a MultiPolygon | ||
dissolved.coordinates = dissolved.coordinates[0]; | ||
dissolved.type = 'Polygon'; | ||
dissolved.type = "Polygon"; | ||
} | ||
@@ -85,9 +79,9 @@ return feature(dissolved); | ||
*/ | ||
function removeDuplicates(points: FeatureCollection<Point>) { | ||
var cleaned = []; | ||
var existing = {}; | ||
function removeDuplicates(points: FeatureCollection<Point>): FeatureCollection<Point> { | ||
const cleaned: Array<Feature<Point>> = []; | ||
const existing: {[key: string]: boolean} = {}; | ||
featureEach(points, function (pt) { | ||
if (!pt.geometry) return; | ||
var key = pt.geometry.coordinates.join('-'); | ||
featureEach(points, (pt) => { | ||
if (!pt.geometry) { return; } | ||
const key = pt.geometry.coordinates.join("-"); | ||
if (!existing.hasOwnProperty(key)) { | ||
@@ -94,0 +88,0 @@ cleaned.push(pt); |
@@ -1,8 +0,8 @@ | ||
import clone from '@turf/clone'; | ||
import { getType } from '@turf/invariant'; | ||
import { isObject } from '@turf/helpers'; | ||
import { flattenEach } from '@turf/meta'; | ||
import lineDissolve from './turf-line-dissolve'; | ||
import polygonDissolve from './turf-polygon-dissolve'; | ||
import { Feature, FeatureCollection, LineString, MultiLineString, Polygon, MultiPolygon } from '@turf/helpers'; | ||
import clone from "@turf/clone"; | ||
import { isObject } from "@turf/helpers"; | ||
import { Feature, FeatureCollection, LineString, MultiLineString, MultiPolygon, Polygon } from "@turf/helpers"; | ||
import { getType } from "@turf/invariant"; | ||
import { flattenEach } from "@turf/meta"; | ||
import lineDissolve from "./turf-line-dissolve"; | ||
import polygonDissolve from "./turf-polygon-dissolve"; | ||
@@ -21,30 +21,30 @@ /** | ||
mutate?: boolean, | ||
} = {}): Feature<LineString|MultiLineString|MultiPolygon> { | ||
} = {}): Feature<LineString|MultiLineString|Polygon|MultiPolygon> | null { | ||
// Optional parameters | ||
options = options || {}; | ||
if (!isObject(options)) throw new Error('options is invalid'); | ||
var mutate = options.mutate; | ||
if (!isObject(options)) { throw new Error("options is invalid"); } | ||
const mutate = options.mutate; | ||
// Validation | ||
if (getType(geojson) !== 'FeatureCollection') throw new Error('geojson must be a FeatureCollection'); | ||
if (!geojson.features.length) throw new Error('geojson is empty'); | ||
if (getType(geojson) !== "FeatureCollection") { throw new Error("geojson must be a FeatureCollection"); } | ||
if (!geojson.features.length) { throw new Error("geojson is empty"); } | ||
// Clone geojson to avoid side effects | ||
// Topojson modifies in place, so we need to deep clone first | ||
if (mutate === false || mutate === undefined) geojson = clone(geojson); | ||
if (mutate === false || mutate === undefined) { geojson = clone(geojson); } | ||
// Assert homogenity | ||
var type = getHomogenousType(geojson); | ||
if (!type) throw new Error('geojson must be homogenous'); | ||
const type = getHomogenousType(geojson); | ||
if (!type) { throw new Error("geojson must be homogenous"); } | ||
// Data => Typescript hack | ||
const data: any = geojson | ||
const data: any = geojson; | ||
switch (type) { | ||
case 'LineString': | ||
case "LineString": | ||
return lineDissolve(data, options); | ||
case 'Polygon': | ||
case "Polygon": | ||
return polygonDissolve(data, options); | ||
default: | ||
throw new Error(type + ' is not supported'); | ||
throw new Error(type + " is not supported"); | ||
} | ||
@@ -60,9 +60,9 @@ } | ||
*/ | ||
function getHomogenousType(geojson) { | ||
var types = {}; | ||
flattenEach(geojson, function (feature) { | ||
function getHomogenousType(geojson: any) { | ||
const types: {[key: string]: boolean} = {}; | ||
flattenEach(geojson, (feature) => { | ||
types[feature.geometry.type] = true; | ||
}); | ||
var keys = Object.keys(types); | ||
if (keys.length === 1) return keys[0]; | ||
const keys = Object.keys(types); | ||
if (keys.length === 1) { return keys[0]; } | ||
return null; | ||
@@ -69,0 +69,0 @@ } |
@@ -1,6 +0,6 @@ | ||
import clone from '@turf/clone'; | ||
import { getType } from '@turf/invariant'; | ||
import { lineReduce } from '@turf/meta'; | ||
import { isObject, multiLineString, lineString } from '@turf/helpers'; | ||
import { Feature, FeatureCollection, LineString, MultiLineString } from '@turf/helpers'; | ||
import clone from "@turf/clone"; | ||
import { isObject, lineString, multiLineString } from "@turf/helpers"; | ||
import { Feature, FeatureCollection, LineString, MultiLineString } from "@turf/helpers"; | ||
import { getType } from "@turf/invariant"; | ||
import { lineReduce } from "@turf/meta"; | ||
@@ -16,28 +16,28 @@ /** | ||
*/ | ||
function lineDissolve(geojson: FeatureCollection<LineString|MultiLineString>, options: { | ||
mutate?: boolean, | ||
} = {}): Feature<LineString|MultiLineString> { | ||
function lineDissolve( | ||
geojson: FeatureCollection<LineString|MultiLineString>, | ||
options: {mutate?: boolean} = {}, | ||
): Feature<LineString|MultiLineString> | null { | ||
// Optional parameters | ||
options = options || {}; | ||
if (!isObject(options)) throw new Error('options is invalid'); | ||
var mutate = options.mutate; | ||
if (!isObject(options)) { throw new Error("options is invalid"); } | ||
const mutate = options.mutate; | ||
// Validation | ||
if (getType(geojson) !== 'FeatureCollection') throw new Error('geojson must be a FeatureCollection'); | ||
if (!geojson.features.length) throw new Error('geojson is empty'); | ||
if (getType(geojson) !== "FeatureCollection") { throw new Error("geojson must be a FeatureCollection"); } | ||
if (!geojson.features.length) { throw new Error("geojson is empty"); } | ||
// Clone geojson to avoid side effects | ||
if (mutate === false || mutate === undefined) geojson = clone(geojson); | ||
if (mutate === false || mutate === undefined) { geojson = clone(geojson); } | ||
var result = []; | ||
var lastLine = lineReduce(geojson, function (previousLine, currentLine) { | ||
const result: any[] = []; | ||
const lastLine = lineReduce(geojson, (previousLine: any, currentLine: any) => { | ||
// Attempt to merge this LineString with the other LineStrings, updating | ||
// the reference as it is merged with others and grows. | ||
var merged = mergeLineStrings(previousLine, currentLine); | ||
const merged = mergeLineStrings(previousLine, currentLine); | ||
// Accumulate the merged LineString | ||
if (merged) return merged; | ||
if (merged) { return merged; | ||
// Put the unmerged LineString back into the list | ||
else { | ||
} else { | ||
result.push(previousLine); | ||
@@ -48,15 +48,19 @@ return currentLine; | ||
// Append the last line | ||
if (lastLine) result.push(lastLine); | ||
if (lastLine) { result.push(lastLine); } | ||
// Return null if no lines were dissolved | ||
if (!result.length) return null; | ||
if (!result.length) { | ||
return null; | ||
// Return LineString if only 1 line was dissolved | ||
else if (result.length === 1) return result[0]; | ||
} else if (result.length === 1) { | ||
return result[0]; | ||
// Return MultiLineString if multiple lines were dissolved with gaps | ||
else return multiLineString(result.map(function (line) { return line.coordinates; })); | ||
} else { return multiLineString(result.map((line) => { | ||
return line.coordinates; | ||
})); } | ||
} | ||
// [Number, Number] -> String | ||
function coordId(coord) { | ||
return coord[0].toString() + ',' + coord[1].toString(); | ||
function coordId(coord: number[]) { | ||
return coord[0].toString() + "," + coord[1].toString(); | ||
} | ||
@@ -72,18 +76,18 @@ | ||
*/ | ||
function mergeLineStrings(a, b) { | ||
var coords1 = a.geometry.coordinates; | ||
var coords2 = b.geometry.coordinates; | ||
function mergeLineStrings(a: Feature<LineString>, b: Feature<LineString>) { | ||
const coords1 = a.geometry.coordinates; | ||
const coords2 = b.geometry.coordinates; | ||
var s1 = coordId(coords1[0]); | ||
var e1 = coordId(coords1[coords1.length - 1]); | ||
var s2 = coordId(coords2[0]); | ||
var e2 = coordId(coords2[coords2.length - 1]); | ||
const s1 = coordId(coords1[0]); | ||
const e1 = coordId(coords1[coords1.length - 1]); | ||
const s2 = coordId(coords2[0]); | ||
const e2 = coordId(coords2[coords2.length - 1]); | ||
// TODO: handle case where more than one of these is true! | ||
var coords; | ||
if (s1 === e2) coords = coords2.concat(coords1.slice(1)); | ||
else if (s2 === e1) coords = coords1.concat(coords2.slice(1)); | ||
else if (s1 === s2) coords = coords1.slice(1).reverse().concat(coords2); | ||
else if (e1 === e2) coords = coords1.concat(coords2.reverse().slice(1)); | ||
else return null; | ||
let coords; | ||
if (s1 === e2) { coords = coords2.concat(coords1.slice(1)); | ||
} else if (s2 === e1) { coords = coords1.concat(coords2.slice(1)); | ||
} else if (s1 === s2) { coords = coords1.slice(1).reverse().concat(coords2); | ||
} else if (e1 === e2) { coords = coords1.concat(coords2.reverse().slice(1)); | ||
} else { return null; } | ||
@@ -90,0 +94,0 @@ return lineString(coords); |
@@ -1,8 +0,7 @@ | ||
import clone from '@turf/clone'; | ||
import { merge } from 'topojson-client'; | ||
import { getType } from '@turf/invariant'; | ||
import { topology } from 'topojson-server'; | ||
import { flattenEach } from '@turf/meta'; | ||
import { isObject, geometryCollection } from '@turf/helpers'; | ||
import { Feature, FeatureCollection, LineString, MultiLineString, Polygon, MultiPolygon } from '@turf/helpers'; | ||
import clone from "@turf/clone"; | ||
import { geometryCollection, isObject } from "@turf/helpers"; | ||
import { Feature, FeatureCollection, LineString, MultiLineString, MultiPolygon, Polygon } from "@turf/helpers"; | ||
import { getType } from "@turf/invariant"; | ||
import { flattenEach } from "@turf/meta"; | ||
import { merge, topology } from "topojson"; | ||
@@ -17,21 +16,21 @@ /** | ||
*/ | ||
function polygonDissolve(geojson: FeatureCollection<Polygon|MultiPolygon>, options: { | ||
mutate?: boolean, | ||
} = {}) { | ||
export default function polygonDissolve( | ||
geojson: FeatureCollection<Polygon|MultiPolygon>, | ||
options: {mutate?: boolean} = {}, | ||
): Feature<Polygon|MultiPolygon> | null { | ||
// Validation | ||
if (getType(geojson) !== 'FeatureCollection') throw new Error('geojson must be a FeatureCollection'); | ||
if (!geojson.features.length) throw new Error('geojson is empty'); | ||
if (getType(geojson) !== "FeatureCollection") { throw new Error("geojson must be a FeatureCollection"); } | ||
if (!geojson.features.length) { throw new Error("geojson is empty"); } | ||
// Clone geojson to avoid side effects | ||
// Topojson modifies in place, so we need to deep clone first | ||
if (options.mutate === false || options.mutate === undefined) geojson = clone(geojson); | ||
if (options.mutate === false || options.mutate === undefined) { geojson = clone(geojson); } | ||
var geoms = []; | ||
flattenEach(geojson, function (feature) { | ||
const geoms: any[] = []; | ||
flattenEach(geojson, (feature) => { | ||
geoms.push(feature.geometry); | ||
}); | ||
var topo = topology({geoms: geometryCollection(geoms).geometry}); | ||
return merge(topo, topo.objects.geoms.geometries); | ||
const topo: any = topology({geoms: geometryCollection(geoms).geometry}); | ||
const merged: any = merge(topo, topo.objects.geoms.geometries); | ||
return merged; | ||
} | ||
export default polygonDissolve; |
{ | ||
"name": "@turf/concave", | ||
"version": "6.0.0", | ||
"version": "6.0.1", | ||
"description": "turf concave module", | ||
"main": "index", | ||
"types": "index.d.ts", | ||
"files": [ | ||
"index.js", | ||
"index.ts", | ||
"index.d.ts", | ||
"lib" | ||
@@ -46,6 +48,9 @@ ], | ||
"devDependencies": { | ||
"@types/tape": "*", | ||
"@types/topojson": "*", | ||
"benchmark": "*", | ||
"load-json-file": "*", | ||
"tape": "*", | ||
"tslint": "*", | ||
"typescript": "*", | ||
"tape": "*", | ||
"write-json-file": "*" | ||
@@ -60,5 +65,4 @@ }, | ||
"@turf/tin": "6.x", | ||
"topojson-client": "3.x", | ||
"topojson-server": "3.x" | ||
"topojson": "3.x" | ||
} | ||
} |
@@ -7,11 +7,11 @@ # @turf/concave | ||
Takes a set of [points](https://tools.ietf.org/html/rfc7946#section-3.1.2) and returns a concave hull Polygon or MultiPolygon. | ||
Internally, this uses [turf-tin](https://github.com/Turfjs/turf-tin) to generate geometries. | ||
Takes a set of [points][1] and returns a concave hull Polygon or MultiPolygon. | ||
Internally, this uses [turf-tin][2] to generate geometries. | ||
**Parameters** | ||
- `points` **[FeatureCollection](https://tools.ietf.org/html/rfc7946#section-3.3)<[Point](https://tools.ietf.org/html/rfc7946#section-3.1.2)>** input points | ||
- `options` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Optional parameters (optional, default `{}`) | ||
- `options.maxEdge` **[number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)** the length (in 'units') of an edge necessary for part of the hull to become concave. (optional, default `Infinity`) | ||
- `options.units` **[string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)** can be degrees, radians, miles, or kilometers (optional, default `'kilometers'`) | ||
- `points` **[FeatureCollection][3]<[Point][4]>** input points | ||
- `options` **[Object][5]** Optional parameters (optional, default `{}`) | ||
- `options.maxEdge` **[number][6]** the length (in 'units') of an edge necessary for part of the hull to become concave. (optional, default `Infinity`) | ||
- `options.units` **[string][7]** can be degrees, radians, miles, or kilometers (optional, default `'kilometers'`) | ||
@@ -37,4 +37,24 @@ **Examples** | ||
Returns **([Feature](https://tools.ietf.org/html/rfc7946#section-3.2)<([Polygon](https://tools.ietf.org/html/rfc7946#section-3.1.6) \| [MultiPolygon](https://tools.ietf.org/html/rfc7946#section-3.1.7))> | null)** a concave hull (null value is returned if unable to compute hull) | ||
Returns **([Feature][8]<([Polygon][9] \| [MultiPolygon][10])> | null)** a concave hull (null value is returned if unable to compute hull) | ||
[1]: https://tools.ietf.org/html/rfc7946#section-3.1.2 | ||
[2]: https://github.com/Turfjs/turf-tin | ||
[3]: https://tools.ietf.org/html/rfc7946#section-3.3 | ||
[4]: https://tools.ietf.org/html/rfc7946#section-3.1.2 | ||
[5]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object | ||
[6]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number | ||
[7]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String | ||
[8]: https://tools.ietf.org/html/rfc7946#section-3.2 | ||
[9]: https://tools.ietf.org/html/rfc7946#section-3.1.6 | ||
[10]: https://tools.ietf.org/html/rfc7946#section-3.1.7 | ||
<!-- This file is automatically generated. Please don't edit it directly: | ||
@@ -41,0 +61,0 @@ if you find an error, edit the source file (likely index.js), and re-run |
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
23087
7
13
419
82
0
8
+ Addedtopojson@3.x
+ Addedtopojson@3.0.2(transitive)
+ Addedtopojson-client@3.0.0(transitive)
+ Addedtopojson-server@3.0.0(transitive)
+ Addedtopojson-simplify@3.0.2(transitive)
- Removedtopojson-client@3.x
- Removedtopojson-server@3.x
- Removedtopojson-client@3.1.0(transitive)
- Removedtopojson-server@3.0.1(transitive)