index.cjs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. "use strict";Object.defineProperty(exports, "__esModule", {value: true});// index.ts
  2. var _helpers = require('@turf/helpers');
  3. // lib/util.ts
  4. var _booleanpointinpolygon = require('@turf/boolean-point-in-polygon');
  5. function mathSign(x) {
  6. return (x > 0) - (x < 0) || +x;
  7. }
  8. function orientationIndex(p1, p2, q) {
  9. const dx1 = p2[0] - p1[0], dy1 = p2[1] - p1[1], dx2 = q[0] - p2[0], dy2 = q[1] - p2[1];
  10. return mathSign(dx1 * dy2 - dx2 * dy1);
  11. }
  12. function envelopeIsEqual(env1, env2) {
  13. const envX1 = env1.geometry.coordinates[0].map((c) => c[0]), envY1 = env1.geometry.coordinates[0].map((c) => c[1]), envX2 = env2.geometry.coordinates[0].map((c) => c[0]), envY2 = env2.geometry.coordinates[0].map((c) => c[1]);
  14. return Math.max.apply(null, envX1) === Math.max.apply(null, envX2) && Math.max.apply(null, envY1) === Math.max.apply(null, envY2) && Math.min.apply(null, envX1) === Math.min.apply(null, envX2) && Math.min.apply(null, envY1) === Math.min.apply(null, envY2);
  15. }
  16. function envelopeContains(self, env) {
  17. return env.geometry.coordinates[0].every(
  18. (c) => _booleanpointinpolygon.booleanPointInPolygon.call(void 0, _helpers.point.call(void 0, c), self)
  19. );
  20. }
  21. function coordinatesEqual(coord1, coord2) {
  22. return coord1[0] === coord2[0] && coord1[1] === coord2[1];
  23. }
  24. // lib/Node.ts
  25. var Node = class _Node {
  26. static buildId(coordinates) {
  27. return coordinates.join(",");
  28. }
  29. constructor(coordinates) {
  30. this.id = _Node.buildId(coordinates);
  31. this.coordinates = coordinates;
  32. this.innerEdges = [];
  33. this.outerEdges = [];
  34. this.outerEdgesSorted = false;
  35. }
  36. removeInnerEdge(edge) {
  37. this.innerEdges = this.innerEdges.filter((e) => e.from.id !== edge.from.id);
  38. }
  39. removeOuterEdge(edge) {
  40. this.outerEdges = this.outerEdges.filter((e) => e.to.id !== edge.to.id);
  41. }
  42. /**
  43. * Outer edges are stored CCW order.
  44. *
  45. * @memberof Node
  46. * @param {Edge} edge - Edge to add as an outerEdge.
  47. */
  48. addOuterEdge(edge) {
  49. this.outerEdges.push(edge);
  50. this.outerEdgesSorted = false;
  51. }
  52. /**
  53. * Sorts outer edges in CCW way.
  54. *
  55. * @memberof Node
  56. * @private
  57. */
  58. sortOuterEdges() {
  59. if (!this.outerEdgesSorted) {
  60. this.outerEdges.sort((a, b) => {
  61. const aNode = a.to, bNode = b.to;
  62. if (aNode.coordinates[0] - this.coordinates[0] >= 0 && bNode.coordinates[0] - this.coordinates[0] < 0)
  63. return 1;
  64. if (aNode.coordinates[0] - this.coordinates[0] < 0 && bNode.coordinates[0] - this.coordinates[0] >= 0)
  65. return -1;
  66. if (aNode.coordinates[0] - this.coordinates[0] === 0 && bNode.coordinates[0] - this.coordinates[0] === 0) {
  67. if (aNode.coordinates[1] - this.coordinates[1] >= 0 || bNode.coordinates[1] - this.coordinates[1] >= 0)
  68. return aNode.coordinates[1] - bNode.coordinates[1];
  69. return bNode.coordinates[1] - aNode.coordinates[1];
  70. }
  71. const det = orientationIndex(
  72. this.coordinates,
  73. aNode.coordinates,
  74. bNode.coordinates
  75. );
  76. if (det < 0) return 1;
  77. if (det > 0) return -1;
  78. const d1 = Math.pow(aNode.coordinates[0] - this.coordinates[0], 2) + Math.pow(aNode.coordinates[1] - this.coordinates[1], 2), d2 = Math.pow(bNode.coordinates[0] - this.coordinates[0], 2) + Math.pow(bNode.coordinates[1] - this.coordinates[1], 2);
  79. return d1 - d2;
  80. });
  81. this.outerEdgesSorted = true;
  82. }
  83. }
  84. /**
  85. * Retrieves outer edges.
  86. *
  87. * They are sorted if they aren't in the CCW order.
  88. *
  89. * @memberof Node
  90. * @returns {Edge[]} - List of outer edges sorted in a CCW order.
  91. */
  92. getOuterEdges() {
  93. this.sortOuterEdges();
  94. return this.outerEdges;
  95. }
  96. getOuterEdge(i) {
  97. this.sortOuterEdges();
  98. return this.outerEdges[i];
  99. }
  100. addInnerEdge(edge) {
  101. this.innerEdges.push(edge);
  102. }
  103. };
  104. // lib/Edge.ts
  105. var Edge = class _Edge {
  106. /**
  107. * Creates or get the symetric Edge.
  108. *
  109. * @returns {Edge} - Symetric Edge.
  110. */
  111. getSymetric() {
  112. if (!this.symetric) {
  113. this.symetric = new _Edge(this.to, this.from);
  114. this.symetric.symetric = this;
  115. }
  116. return this.symetric;
  117. }
  118. /**
  119. * @param {Node} from - start node of the Edge
  120. * @param {Node} to - end node of the edge
  121. */
  122. constructor(from, to) {
  123. this.from = from;
  124. this.to = to;
  125. this.next = void 0;
  126. this.label = void 0;
  127. this.symetric = void 0;
  128. this.ring = void 0;
  129. this.from.addOuterEdge(this);
  130. this.to.addInnerEdge(this);
  131. }
  132. /**
  133. * Removes edge from from and to nodes.
  134. */
  135. deleteEdge() {
  136. this.from.removeOuterEdge(this);
  137. this.to.removeInnerEdge(this);
  138. }
  139. /**
  140. * Compares Edge equallity.
  141. *
  142. * An edge is equal to another, if the from and to nodes are the same.
  143. *
  144. * @param {Edge} edge - Another Edge
  145. * @returns {boolean} - True if Edges are equal, False otherwise
  146. */
  147. isEqual(edge) {
  148. return this.from.id === edge.from.id && this.to.id === edge.to.id;
  149. }
  150. toString() {
  151. return `Edge { ${this.from.id} -> ${this.to.id} }`;
  152. }
  153. /**
  154. * Returns a LineString representation of the Edge
  155. *
  156. * @returns {Feature<LineString>} - LineString representation of the Edge
  157. */
  158. toLineString() {
  159. return _helpers.lineString.call(void 0, [this.from.coordinates, this.to.coordinates]);
  160. }
  161. /**
  162. * Comparator of two edges.
  163. *
  164. * Implementation of geos::planargraph::DirectedEdge::compareTo.
  165. *
  166. * @param {Edge} edge - Another edge to compare with this one
  167. * @returns {number} -1 if this Edge has a greater angle with the positive x-axis than b,
  168. * 0 if the Edges are colinear,
  169. * 1 otherwise
  170. */
  171. compareTo(edge) {
  172. return orientationIndex(
  173. edge.from.coordinates,
  174. edge.to.coordinates,
  175. this.to.coordinates
  176. );
  177. }
  178. };
  179. // lib/EdgeRing.ts
  180. var _envelope = require('@turf/envelope');
  181. var EdgeRing = class {
  182. constructor() {
  183. this.edges = [];
  184. this.polygon = void 0;
  185. this.envelope = void 0;
  186. }
  187. /**
  188. * Add an edge to the ring, inserting it in the last position.
  189. *
  190. * @memberof EdgeRing
  191. * @param {Edge} edge - Edge to be inserted
  192. */
  193. push(edge) {
  194. this.edges.push(edge);
  195. this.polygon = this.envelope = void 0;
  196. }
  197. /**
  198. * Get Edge.
  199. *
  200. * @memberof EdgeRing
  201. * @param {number} i - Index
  202. * @returns {Edge} - Edge in the i position
  203. */
  204. get(i) {
  205. return this.edges[i];
  206. }
  207. /**
  208. * Getter of length property.
  209. *
  210. * @memberof EdgeRing
  211. * @returns {number} - Length of the edge ring.
  212. */
  213. get length() {
  214. return this.edges.length;
  215. }
  216. /**
  217. * Similar to Array.prototype.forEach for the list of Edges in the EdgeRing.
  218. *
  219. * @memberof EdgeRing
  220. * @param {Function} f - The same function to be passed to Array.prototype.forEach
  221. */
  222. forEach(f) {
  223. this.edges.forEach(f);
  224. }
  225. /**
  226. * Similar to Array.prototype.map for the list of Edges in the EdgeRing.
  227. *
  228. * @memberof EdgeRing
  229. * @param {Function} f - The same function to be passed to Array.prototype.map
  230. * @returns {Array} - The mapped values in the function
  231. */
  232. map(f) {
  233. return this.edges.map(f);
  234. }
  235. /**
  236. * Similar to Array.prototype.some for the list of Edges in the EdgeRing.
  237. *
  238. * @memberof EdgeRing
  239. * @param {Function} f - The same function to be passed to Array.prototype.some
  240. * @returns {boolean} - True if an Edge check the condition
  241. */
  242. some(f) {
  243. return this.edges.some(f);
  244. }
  245. /**
  246. * Check if the ring is valid in geomtry terms.
  247. *
  248. * A ring must have either 0 or 4 or more points. The first and the last must be
  249. * equal (in 2D)
  250. * geos::geom::LinearRing::validateConstruction
  251. *
  252. * @memberof EdgeRing
  253. * @returns {boolean} - Validity of the EdgeRing
  254. */
  255. isValid() {
  256. return true;
  257. }
  258. /**
  259. * Tests whether this ring is a hole.
  260. *
  261. * A ring is a hole if it is oriented counter-clockwise.
  262. * Similar implementation of geos::algorithm::CGAlgorithms::isCCW
  263. *
  264. * @memberof EdgeRing
  265. * @returns {boolean} - true: if it is a hole
  266. */
  267. isHole() {
  268. const hiIndex = this.edges.reduce((high, edge, i) => {
  269. if (edge.from.coordinates[1] > this.edges[high].from.coordinates[1])
  270. high = i;
  271. return high;
  272. }, 0), iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1, iNext = (hiIndex + 1) % this.length, disc = orientationIndex(
  273. this.edges[iPrev].from.coordinates,
  274. this.edges[hiIndex].from.coordinates,
  275. this.edges[iNext].from.coordinates
  276. );
  277. if (disc === 0)
  278. return this.edges[iPrev].from.coordinates[0] > this.edges[iNext].from.coordinates[0];
  279. return disc > 0;
  280. }
  281. /**
  282. * Creates a MultiPoint representing the EdgeRing (discarts edges directions).
  283. *
  284. * @memberof EdgeRing
  285. * @returns {Feature<MultiPoint>} - Multipoint representation of the EdgeRing
  286. */
  287. toMultiPoint() {
  288. return _helpers.multiPoint.call(void 0, this.edges.map((edge) => edge.from.coordinates));
  289. }
  290. /**
  291. * Creates a Polygon representing the EdgeRing.
  292. *
  293. * @memberof EdgeRing
  294. * @returns {Feature<Polygon>} - Polygon representation of the Edge Ring
  295. */
  296. toPolygon() {
  297. if (this.polygon) return this.polygon;
  298. const coordinates = this.edges.map((edge) => edge.from.coordinates);
  299. coordinates.push(this.edges[0].from.coordinates);
  300. return this.polygon = _helpers.polygon.call(void 0, [coordinates]);
  301. }
  302. /**
  303. * Calculates the envelope of the EdgeRing.
  304. *
  305. * @memberof EdgeRing
  306. * @returns {Feature<Polygon>} - envelope
  307. */
  308. getEnvelope() {
  309. if (this.envelope) return this.envelope;
  310. return this.envelope = _envelope.envelope.call(void 0, this.toPolygon());
  311. }
  312. /**
  313. * `geos::operation::polygonize::EdgeRing::findEdgeRingContaining`
  314. *
  315. * @param {EdgeRing} testEdgeRing - EdgeRing to look in the list
  316. * @param {EdgeRing[]} shellList - List of EdgeRing in which to search
  317. *
  318. * @returns {EdgeRing} - EdgeRing which contains the testEdgeRing
  319. */
  320. static findEdgeRingContaining(testEdgeRing, shellList) {
  321. const testEnvelope = testEdgeRing.getEnvelope();
  322. let minEnvelope, minShell;
  323. shellList.forEach((shell) => {
  324. const tryEnvelope = shell.getEnvelope();
  325. if (minShell) minEnvelope = minShell.getEnvelope();
  326. if (envelopeIsEqual(tryEnvelope, testEnvelope)) return;
  327. if (envelopeContains(tryEnvelope, testEnvelope)) {
  328. const testEdgeRingCoordinates = testEdgeRing.map(
  329. (edge) => edge.from.coordinates
  330. );
  331. let testPoint;
  332. for (const pt of testEdgeRingCoordinates) {
  333. if (!shell.some((edge) => coordinatesEqual(pt, edge.from.coordinates))) {
  334. testPoint = pt;
  335. }
  336. }
  337. if (testPoint && shell.inside(_helpers.point.call(void 0, testPoint))) {
  338. if (!minShell || envelopeContains(minEnvelope, tryEnvelope))
  339. minShell = shell;
  340. }
  341. }
  342. });
  343. return minShell;
  344. }
  345. /**
  346. * Checks if the point is inside the edgeRing
  347. *
  348. * @param {Feature<Point>} pt - Point to check if it is inside the edgeRing
  349. * @returns {boolean} - True if it is inside, False otherwise
  350. */
  351. inside(pt) {
  352. return _booleanpointinpolygon.booleanPointInPolygon.call(void 0, pt, this.toPolygon());
  353. }
  354. };
  355. // lib/Graph.ts
  356. var _meta = require('@turf/meta');
  357. var _invariant = require('@turf/invariant');
  358. function validateGeoJson(geoJson) {
  359. if (!geoJson) throw new Error("No geojson passed");
  360. if (geoJson.type !== "FeatureCollection" && geoJson.type !== "GeometryCollection" && geoJson.type !== "MultiLineString" && geoJson.type !== "LineString" && geoJson.type !== "Feature")
  361. throw new Error(
  362. `Invalid input type '${geoJson.type}'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature`
  363. );
  364. }
  365. var Graph = class _Graph {
  366. /**
  367. * Creates a graph from a GeoJSON.
  368. *
  369. * @param {FeatureCollection<LineString>} geoJson - it must comply with the restrictions detailed in the index
  370. * @returns {Graph} - The newly created graph
  371. * @throws {Error} if geoJson is invalid.
  372. */
  373. static fromGeoJson(geoJson) {
  374. validateGeoJson(geoJson);
  375. const graph = new _Graph();
  376. _meta.flattenEach.call(void 0, geoJson, (feature) => {
  377. _invariant.featureOf.call(void 0, feature, "LineString", "Graph::fromGeoJson");
  378. _meta.coordReduce.call(void 0, feature, (prev, cur) => {
  379. if (prev) {
  380. const start = graph.getNode(prev), end = graph.getNode(cur);
  381. graph.addEdge(start, end);
  382. }
  383. return cur;
  384. });
  385. });
  386. return graph;
  387. }
  388. /**
  389. * Creates or get a Node.
  390. *
  391. * @param {number[]} coordinates - Coordinates of the node
  392. * @returns {Node} - The created or stored node
  393. */
  394. getNode(coordinates) {
  395. const id = Node.buildId(coordinates);
  396. let node = this.nodes[id];
  397. if (!node) node = this.nodes[id] = new Node(coordinates);
  398. return node;
  399. }
  400. /**
  401. * Adds an Edge and its symetricall.
  402. *
  403. * Edges are added symetrically, i.e.: we also add its symetric
  404. *
  405. * @param {Node} from - Node which starts the Edge
  406. * @param {Node} to - Node which ends the Edge
  407. */
  408. addEdge(from, to) {
  409. const edge = new Edge(from, to), symetricEdge = edge.getSymetric();
  410. this.edges.push(edge);
  411. this.edges.push(symetricEdge);
  412. }
  413. constructor() {
  414. this.edges = [];
  415. this.nodes = {};
  416. }
  417. /**
  418. * Removes Dangle Nodes (nodes with grade 1).
  419. */
  420. deleteDangles() {
  421. Object.keys(this.nodes).map((id) => this.nodes[id]).forEach((node) => this._removeIfDangle(node));
  422. }
  423. /**
  424. * Check if node is dangle, if so, remove it.
  425. *
  426. * It calls itself recursively, removing a dangling node might cause another dangling node
  427. *
  428. * @param {Node} node - Node to check if it's a dangle
  429. */
  430. _removeIfDangle(node) {
  431. if (node.innerEdges.length <= 1) {
  432. const outerNodes = node.getOuterEdges().map((e) => e.to);
  433. this.removeNode(node);
  434. outerNodes.forEach((n) => this._removeIfDangle(n));
  435. }
  436. }
  437. /**
  438. * Delete cut-edges (bridge edges).
  439. *
  440. * The graph will be traversed, all the edges will be labeled according the ring
  441. * in which they are. (The label is a number incremented by 1). Edges with the same
  442. * label are cut-edges.
  443. */
  444. deleteCutEdges() {
  445. this._computeNextCWEdges();
  446. this._findLabeledEdgeRings();
  447. this.edges.forEach((edge) => {
  448. if (edge.label === edge.symetric.label) {
  449. this.removeEdge(edge.symetric);
  450. this.removeEdge(edge);
  451. }
  452. });
  453. }
  454. /**
  455. * Set the `next` property of each Edge.
  456. *
  457. * The graph will be transversed in a CW form, so, we set the next of the symetrical edge as the previous one.
  458. * OuterEdges are sorted CCW.
  459. *
  460. * @param {Node} [node] - If no node is passed, the function calls itself for every node in the Graph
  461. */
  462. _computeNextCWEdges(node) {
  463. if (typeof node === "undefined") {
  464. Object.keys(this.nodes).forEach(
  465. (id) => this._computeNextCWEdges(this.nodes[id])
  466. );
  467. } else {
  468. node.getOuterEdges().forEach((edge, i) => {
  469. node.getOuterEdge(
  470. (i === 0 ? node.getOuterEdges().length : i) - 1
  471. ).symetric.next = edge;
  472. });
  473. }
  474. }
  475. /**
  476. * Computes the next edge pointers going CCW around the given node, for the given edgering label.
  477. *
  478. * This algorithm has the effect of converting maximal edgerings into minimal edgerings
  479. *
  480. * XXX: method literally transcribed from `geos::operation::polygonize::PolygonizeGraph::computeNextCCWEdges`,
  481. * could be written in a more javascript way.
  482. *
  483. * @param {Node} node - Node
  484. * @param {number} label - Ring's label
  485. */
  486. _computeNextCCWEdges(node, label) {
  487. const edges = node.getOuterEdges();
  488. let firstOutDE, prevInDE;
  489. for (let i = edges.length - 1; i >= 0; --i) {
  490. let de = edges[i], sym = de.symetric, outDE, inDE;
  491. if (de.label === label) outDE = de;
  492. if (sym.label === label) inDE = sym;
  493. if (!outDE || !inDE)
  494. continue;
  495. if (inDE) prevInDE = inDE;
  496. if (outDE) {
  497. if (prevInDE) {
  498. prevInDE.next = outDE;
  499. prevInDE = void 0;
  500. }
  501. if (!firstOutDE) firstOutDE = outDE;
  502. }
  503. }
  504. if (prevInDE) prevInDE.next = firstOutDE;
  505. }
  506. /**
  507. * Finds rings and labels edges according to which rings are.
  508. *
  509. * The label is a number which is increased for each ring.
  510. *
  511. * @returns {Edge[]} edges that start rings
  512. */
  513. _findLabeledEdgeRings() {
  514. const edgeRingStarts = [];
  515. let label = 0;
  516. this.edges.forEach((edge) => {
  517. if (edge.label >= 0) return;
  518. edgeRingStarts.push(edge);
  519. let e = edge;
  520. do {
  521. e.label = label;
  522. e = e.next;
  523. } while (!edge.isEqual(e));
  524. label++;
  525. });
  526. return edgeRingStarts;
  527. }
  528. /**
  529. * Computes the EdgeRings formed by the edges in this graph.
  530. *
  531. * @returns {EdgeRing[]} - A list of all the EdgeRings in the graph.
  532. */
  533. getEdgeRings() {
  534. this._computeNextCWEdges();
  535. this.edges.forEach((edge) => {
  536. edge.label = void 0;
  537. });
  538. this._findLabeledEdgeRings().forEach((edge) => {
  539. this._findIntersectionNodes(edge).forEach((node) => {
  540. this._computeNextCCWEdges(node, edge.label);
  541. });
  542. });
  543. const edgeRingList = [];
  544. this.edges.forEach((edge) => {
  545. if (edge.ring) return;
  546. edgeRingList.push(this._findEdgeRing(edge));
  547. });
  548. return edgeRingList;
  549. }
  550. /**
  551. * Find all nodes in a Maxima EdgeRing which are self-intersection nodes.
  552. *
  553. * @param {Node} startEdge - Start Edge of the Ring
  554. * @returns {Node[]} - intersection nodes
  555. */
  556. _findIntersectionNodes(startEdge) {
  557. const intersectionNodes = [];
  558. let edge = startEdge;
  559. do {
  560. let degree = 0;
  561. edge.from.getOuterEdges().forEach((e) => {
  562. if (e.label === startEdge.label) ++degree;
  563. });
  564. if (degree > 1) intersectionNodes.push(edge.from);
  565. edge = edge.next;
  566. } while (!startEdge.isEqual(edge));
  567. return intersectionNodes;
  568. }
  569. /**
  570. * Get the edge-ring which starts from the provided Edge.
  571. *
  572. * @param {Edge} startEdge - starting edge of the edge ring
  573. * @returns {EdgeRing} - EdgeRing which start Edge is the provided one.
  574. */
  575. _findEdgeRing(startEdge) {
  576. let edge = startEdge;
  577. const edgeRing = new EdgeRing();
  578. do {
  579. edgeRing.push(edge);
  580. edge.ring = edgeRing;
  581. edge = edge.next;
  582. } while (!startEdge.isEqual(edge));
  583. return edgeRing;
  584. }
  585. /**
  586. * Removes a node from the Graph.
  587. *
  588. * It also removes edges asociated to that node
  589. * @param {Node} node - Node to be removed
  590. */
  591. removeNode(node) {
  592. node.getOuterEdges().forEach((edge) => this.removeEdge(edge));
  593. node.innerEdges.forEach((edge) => this.removeEdge(edge));
  594. delete this.nodes[node.id];
  595. }
  596. /**
  597. * Remove edge from the graph and deletes the edge.
  598. *
  599. * @param {Edge} edge - Edge to be removed
  600. */
  601. removeEdge(edge) {
  602. this.edges = this.edges.filter((e) => !e.isEqual(edge));
  603. edge.deleteEdge();
  604. }
  605. };
  606. // index.ts
  607. function polygonize(geoJson) {
  608. const graph = Graph.fromGeoJson(geoJson);
  609. graph.deleteDangles();
  610. graph.deleteCutEdges();
  611. const holes = [], shells = [];
  612. graph.getEdgeRings().filter((edgeRing) => edgeRing.isValid()).forEach((edgeRing) => {
  613. if (edgeRing.isHole()) holes.push(edgeRing);
  614. else shells.push(edgeRing);
  615. });
  616. holes.forEach((hole) => {
  617. if (EdgeRing.findEdgeRingContaining(hole, shells)) shells.push(hole);
  618. });
  619. return _helpers.featureCollection.call(void 0, shells.map((shell) => shell.toPolygon()));
  620. }
  621. var turf_polygonize_default = polygonize;
  622. exports.default = turf_polygonize_default; exports.polygonize = polygonize;
  623. //# sourceMappingURL=index.cjs.map