{"version":3,"sources":["../../index.ts","../../lib/turf-dissolve.ts","../../lib/turf-line-dissolve.ts","../../lib/turf-polygon-dissolve.ts"],"sourcesContent":["import { distance } from \"@turf/distance\";\nimport { feature, featureCollection } from \"@turf/helpers\";\nimport {\n Feature,\n FeatureCollection,\n MultiPolygon,\n Point,\n Polygon,\n} from \"geojson\";\nimport { Units } from \"@turf/helpers\";\nimport { featureEach } from \"@turf/meta\";\nimport { tin } from \"@turf/tin\";\nimport { dissolve } from \"./lib/turf-dissolve.js\";\n\n/**\n * Takes a set of {@link Point|points} and returns a concave hull Polygon or MultiPolygon.\n * Internally, this uses [turf-tin](https://github.com/Turfjs/turf-tin) to generate geometries.\n *\n * @function\n * @param {FeatureCollection} points input points\n * @param {Object} [options={}] Optional parameters\n * @param {number} [options.maxEdge=Infinity] the length (in 'units') of an edge necessary for part of the\n * hull to become concave.\n * @param {string} [options.units='kilometers'] can be degrees, radians, miles, or kilometers\n * @returns {Feature<(Polygon|MultiPolygon)>|null} a concave hull (null value is returned if unable to compute hull)\n * @example\n * var points = turf.featureCollection([\n * turf.point([-63.601226, 44.642643]),\n * turf.point([-63.591442, 44.651436]),\n * turf.point([-63.580799, 44.648749]),\n * turf.point([-63.573589, 44.641788]),\n * turf.point([-63.587665, 44.64533]),\n * turf.point([-63.595218, 44.64765])\n * ]);\n * var options = {units: 'miles', maxEdge: 1};\n *\n * var hull = turf.concave(points, options);\n *\n * //addToMap\n * var addToMap = [points, hull]\n */\nfunction concave(\n points: FeatureCollection,\n options: { maxEdge?: number; units?: Units } = {}\n): Feature | null {\n const maxEdge = options.maxEdge || Infinity;\n\n const cleaned = removeDuplicates(points);\n\n const tinPolys = tin(cleaned);\n // calculate length of all edges and area of all triangles\n // and remove triangles that fail the max length test\n tinPolys.features = tinPolys.features.filter((triangle) => {\n const pt1 = triangle.geometry.coordinates[0][0];\n const pt2 = triangle.geometry.coordinates[0][1];\n const pt3 = triangle.geometry.coordinates[0][2];\n const dist1 = distance(pt1, pt2, options);\n const dist2 = distance(pt2, pt3, options);\n const dist3 = distance(pt1, pt3, options);\n return dist1 <= maxEdge && dist2 <= maxEdge && dist3 <= maxEdge;\n });\n\n if (tinPolys.features.length < 1) {\n return null;\n }\n\n // merge the adjacent triangles\n const dissolved: any = dissolve(tinPolys);\n\n // geojson-dissolve always returns a MultiPolygon\n if (dissolved.coordinates.length === 1) {\n dissolved.coordinates = dissolved.coordinates[0];\n dissolved.type = \"Polygon\";\n }\n return feature(dissolved);\n}\n\n/**\n * Removes duplicated points in a collection returning a new collection\n *\n * @private\n * @param {FeatureCollection} points to be cleaned\n * @returns {FeatureCollection} cleaned set of points\n */\nfunction removeDuplicates(\n points: FeatureCollection\n): FeatureCollection {\n const cleaned: Array> = [];\n const existing: { [key: string]: boolean } = {};\n\n featureEach(points, (pt) => {\n if (!pt.geometry) {\n return;\n }\n const key = pt.geometry.coordinates.join(\"-\");\n if (!Object.prototype.hasOwnProperty.call(existing, key)) {\n cleaned.push(pt);\n existing[key] = true;\n }\n });\n return featureCollection(cleaned);\n}\n\nexport { concave };\nexport default concave;\n","import {\n Feature,\n FeatureCollection,\n LineString,\n MultiLineString,\n MultiPolygon,\n Polygon,\n} from \"geojson\";\nimport { clone } from \"@turf/clone\";\nimport { isObject } from \"@turf/helpers\";\nimport { getType } from \"@turf/invariant\";\nimport { flattenEach } from \"@turf/meta\";\nimport { lineDissolve } from \"./turf-line-dissolve.js\";\nimport { polygonDissolve } from \"./turf-polygon-dissolve.js\";\n\n/**\n * Transform function: attempts to dissolve geojson objects where possible\n * [GeoJSON] -> GeoJSON geometry\n *\n * @private\n * @param {FeatureCollection} geojson Features to dissolved\n * @param {Object} [options={}] Optional parameters\n * @param {boolean} [options.mutate=false] Prevent input mutation\n * @returns {Feature} Dissolved Features\n */\nfunction dissolve(\n geojson: FeatureCollection<\n LineString | MultiLineString | Polygon | MultiPolygon\n >,\n options: {\n mutate?: boolean;\n } = {}\n): Feature | null {\n // Optional parameters\n options = options || {};\n if (!isObject(options)) {\n throw new Error(\"options is invalid\");\n }\n const mutate = options.mutate;\n\n // Validation\n if (getType(geojson) !== \"FeatureCollection\") {\n throw new Error(\"geojson must be a FeatureCollection\");\n }\n if (!geojson.features.length) {\n throw new Error(\"geojson is empty\");\n }\n\n // Clone geojson to avoid side effects\n // Topojson modifies in place, so we need to deep clone first\n if (mutate === false || mutate === undefined) {\n geojson = clone(geojson);\n }\n\n // Assert homogenity\n const type = getHomogenousType(geojson);\n if (!type) {\n throw new Error(\"geojson must be homogenous\");\n }\n\n // Data => Typescript hack\n const data: any = geojson;\n\n switch (type) {\n case \"LineString\":\n return lineDissolve(data, options);\n case \"Polygon\":\n return polygonDissolve(data, options);\n default:\n throw new Error(type + \" is not supported\");\n }\n}\n\n/**\n * Checks if GeoJSON is Homogenous\n *\n * @private\n * @param {GeoJSON} geojson GeoJSON\n * @returns {string|null} Homogenous type or null if multiple types\n */\nfunction getHomogenousType(geojson: any) {\n const types: { [key: string]: boolean } = {};\n flattenEach(geojson, (feature) => {\n types[feature.geometry.type] = true;\n });\n const keys = Object.keys(types);\n if (keys.length === 1) {\n return keys[0];\n }\n return null;\n}\n\nexport { dissolve };\nexport default dissolve;\n","import {\n Feature,\n FeatureCollection,\n LineString,\n MultiLineString,\n} from \"geojson\";\nimport { clone } from \"@turf/clone\";\nimport { isObject, lineString, multiLineString } from \"@turf/helpers\";\nimport { getType } from \"@turf/invariant\";\nimport { lineReduce } from \"@turf/meta\";\n\n/**\n * Merges all connected (non-forking, non-junctioning) line strings into single lineStrings.\n * [LineString] -> LineString|MultiLineString\n *\n * @param {FeatureCollection} geojson Lines to dissolve\n * @param {Object} [options={}] Optional parameters\n * @param {boolean} [options.mutate=false] Prevent input mutation\n * @returns {Feature} Dissolved lines\n */\nfunction lineDissolve(\n geojson: FeatureCollection,\n options: { mutate?: boolean } = {}\n): Feature | null {\n // Optional parameters\n options = options || {};\n if (!isObject(options)) {\n throw new Error(\"options is invalid\");\n }\n const mutate = options.mutate;\n\n // Validation\n if (getType(geojson) !== \"FeatureCollection\") {\n throw new Error(\"geojson must be a FeatureCollection\");\n }\n if (!geojson.features.length) {\n throw new Error(\"geojson is empty\");\n }\n\n // Clone geojson to avoid side effects\n if (mutate === false || mutate === undefined) {\n geojson = clone(geojson);\n }\n\n const result: any[] = [];\n const lastLine = lineReduce(\n geojson,\n (previousLine: any, currentLine: any) => {\n // Attempt to merge this LineString with the other LineStrings, updating\n // the reference as it is merged with others and grows.\n const merged = mergeLineStrings(previousLine, currentLine);\n\n // Accumulate the merged LineString\n if (merged) {\n return merged;\n // Put the unmerged LineString back into the list\n } else {\n result.push(previousLine);\n return currentLine;\n }\n }\n );\n // Append the last line\n if (lastLine) {\n result.push(lastLine);\n }\n\n // Return null if no lines were dissolved\n if (!result.length) {\n return null;\n // Return LineString if only 1 line was dissolved\n } else if (result.length === 1) {\n return result[0];\n // Return MultiLineString if multiple lines were dissolved with gaps\n } else {\n return multiLineString(\n result.map((line) => {\n return line.coordinates;\n })\n );\n }\n}\n\n// [Number, Number] -> String\nfunction coordId(coord: number[]) {\n return coord[0].toString() + \",\" + coord[1].toString();\n}\n\n/**\n * LineString, LineString -> LineString\n *\n * @private\n * @param {Feature} a line1\n * @param {Feature} b line2\n * @returns {Feature|null} Merged LineString\n */\nfunction mergeLineStrings(a: Feature, b: Feature) {\n const coords1 = a.geometry.coordinates;\n const coords2 = b.geometry.coordinates;\n\n const s1 = coordId(coords1[0]);\n const e1 = coordId(coords1[coords1.length - 1]);\n const s2 = coordId(coords2[0]);\n const e2 = coordId(coords2[coords2.length - 1]);\n\n // TODO: handle case where more than one of these is true!\n let coords;\n if (s1 === e2) {\n coords = coords2.concat(coords1.slice(1));\n } else if (s2 === e1) {\n coords = coords1.concat(coords2.slice(1));\n } else if (s1 === s2) {\n coords = coords1.slice(1).reverse().concat(coords2);\n } else if (e1 === e2) {\n coords = coords1.concat(coords2.reverse().slice(1));\n } else {\n return null;\n }\n\n return lineString(coords);\n}\n\nexport { lineDissolve };\nexport default lineDissolve;\n","import { Feature, FeatureCollection, MultiPolygon, Polygon } from \"geojson\";\nimport { clone } from \"@turf/clone\";\nimport { geometryCollection } from \"@turf/helpers\";\nimport { getType } from \"@turf/invariant\";\nimport { flattenEach } from \"@turf/meta\";\nimport { merge } from \"topojson-client\";\nimport { topology } from \"topojson-server\";\n\n/**\n * Dissolves all overlapping (Multi)Polygon\n *\n * @param {FeatureCollection} geojson Polygons to dissolve\n * @param {Object} [options={}] Optional parameters\n * @param {boolean} [options.mutate=false] Prevent input mutation\n * @returns {Feature} Dissolved Polygons\n */\nfunction polygonDissolve(\n geojson: FeatureCollection,\n options: { mutate?: boolean } = {}\n): Feature | null {\n // Validation\n if (getType(geojson) !== \"FeatureCollection\") {\n throw new Error(\"geojson must be a FeatureCollection\");\n }\n if (!geojson.features.length) {\n throw new Error(\"geojson is empty\");\n }\n\n // Clone geojson to avoid side effects\n // Topojson modifies in place, so we need to deep clone first\n if (options.mutate === false || options.mutate === undefined) {\n geojson = clone(geojson);\n }\n\n const geoms: any[] = [];\n flattenEach(geojson, (feature) => {\n geoms.push(feature.geometry);\n });\n const topo: any = topology({ geoms: geometryCollection(geoms).geometry });\n const merged: any = merge(topo, topo.objects.geoms.geometries);\n return merged;\n}\n\nexport { polygonDissolve };\nexport default polygonDissolve;\n"],"mappings":"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","names":["clone","isObject","getType","flattenEach","clone","getType","feature","isObject","getType","clone","flattenEach","feature"]}