{"version":3,"sources":["../../index.ts","../../lib/util.ts","../../lib/Node.ts","../../lib/Edge.ts","../../lib/EdgeRing.ts","../../lib/Graph.ts"],"sourcesContent":["import {\n Feature,\n FeatureCollection,\n LineString,\n MultiLineString,\n Polygon,\n} from \"geojson\";\nimport { featureCollection } from \"@turf/helpers\";\nimport { Graph } from \"./lib/Graph.js\";\nimport { EdgeRing } from \"./lib/EdgeRing.js\";\n\n/**\n * Polygonizes {@link LineString|(Multi)LineString(s)} into {@link Polygons}.\n *\n * Implementation of GEOSPolygonize function (`geos::operation::polygonize::Polygonizer`).\n *\n * Polygonizes a set of lines that represents edges in a planar graph. Edges must be correctly\n * noded, i.e., they must only meet at their endpoints.\n *\n * The implementation correctly handles:\n *\n * - Dangles: edges which have one or both ends which are not incident on another edge endpoint.\n * - Cut Edges (bridges): edges that are connected at both ends but which do not form part of a polygon.\n *\n * @function\n * @param {FeatureCollection|Geometry|Feature} geoJson Lines in order to polygonize\n * @returns {FeatureCollection} Polygons created\n * @throws {Error} if geoJson is invalid.\n */\nfunction polygonize(\n geoJson: Feature | FeatureCollection | T\n): FeatureCollection {\n const graph = Graph.fromGeoJson(geoJson);\n\n // 1. Remove dangle node\n graph.deleteDangles();\n\n // 2. Remove cut-edges (bridge edges)\n graph.deleteCutEdges();\n\n // 3. Get all holes and shells\n const holes: EdgeRing[] = [],\n shells: EdgeRing[] = [];\n\n graph\n .getEdgeRings()\n .filter((edgeRing) => edgeRing.isValid())\n .forEach((edgeRing) => {\n if (edgeRing.isHole()) holes.push(edgeRing);\n else shells.push(edgeRing);\n });\n\n // 4. Assign Holes to Shells\n holes.forEach((hole) => {\n if (EdgeRing.findEdgeRingContaining(hole, shells)) shells.push(hole);\n });\n\n // 5. EdgeRings to Polygons\n return featureCollection(shells.map((shell) => shell.toPolygon()));\n}\n\nexport { polygonize };\nexport default polygonize;\n","import { Feature, Polygon } from \"geojson\";\nimport { booleanPointInPolygon } from \"@turf/boolean-point-in-polygon\";\nimport { point } from \"@turf/helpers\";\n\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign#Polyfill\nfunction mathSign(x: number) {\n return ((x > 0) as unknown as number) - ((x < 0) as unknown as number) || +x;\n}\n\n/**\n * Returns the direction of the point q relative to the vector p1 -> p2.\n *\n * Implementation of geos::algorithm::CGAlgorithm::orientationIndex()\n * (same as geos::algorithm::CGAlgorithm::computeOrientation())\n *\n * @param {number[]} p1 - the origin point of the vector\n * @param {number[]} p2 - the final point of the vector\n * @param {number[]} q - the point to compute the direction to\n *\n * @returns {number} - 1 if q is ccw (left) from p1->p2,\n * -1 if q is cw (right) from p1->p2,\n * 0 if q is colinear with p1->p2\n */\nexport function orientationIndex(p1: number[], p2: number[], q: number[]) {\n const dx1 = p2[0] - p1[0],\n dy1 = p2[1] - p1[1],\n dx2 = q[0] - p2[0],\n dy2 = q[1] - p2[1];\n\n return mathSign(dx1 * dy2 - dx2 * dy1);\n}\n\n/**\n * Checks if two envelopes are equal.\n *\n * The function assumes that the arguments are envelopes, i.e.: Rectangular polygon\n *\n * @param {Feature} env1 - Envelope\n * @param {Feature} env2 - Envelope\n * @returns {boolean} - True if the envelopes are equal\n */\nexport function envelopeIsEqual(\n env1: Feature,\n env2: Feature\n) {\n const envX1 = env1.geometry.coordinates[0].map((c) => c[0]),\n envY1 = env1.geometry.coordinates[0].map((c) => c[1]),\n envX2 = env2.geometry.coordinates[0].map((c) => c[0]),\n envY2 = env2.geometry.coordinates[0].map((c) => c[1]);\n\n return (\n Math.max.apply(null, envX1) === Math.max.apply(null, envX2) &&\n Math.max.apply(null, envY1) === Math.max.apply(null, envY2) &&\n Math.min.apply(null, envX1) === Math.min.apply(null, envX2) &&\n Math.min.apply(null, envY1) === Math.min.apply(null, envY2)\n );\n}\n\n/**\n * Check if a envelope is contained in other one.\n *\n * The function assumes that the arguments are envelopes, i.e.: Convex polygon\n * XXX: Envelopes are rectangular, checking if a point is inside a rectangule is something easy,\n * this could be further improved.\n *\n * @param {Feature} self - Envelope\n * @param {Feature} env - Envelope\n * @returns {boolean} - True if env is contained in self\n */\nexport function envelopeContains(\n self: Feature,\n env: Feature\n) {\n return env.geometry.coordinates[0].every((c) =>\n booleanPointInPolygon(point(c), self)\n );\n}\n\n/**\n * Checks if two coordinates are equal.\n *\n * @param {number[]} coord1 - First coordinate\n * @param {number[]} coord2 - Second coordinate\n * @returns {boolean} - True if coordinates are equal\n */\nexport function coordinatesEqual(coord1: number[], coord2: number[]) {\n return coord1[0] === coord2[0] && coord1[1] === coord2[1];\n}\n","import { orientationIndex } from \"./util.js\";\nimport { Edge } from \"./Edge.js\";\n\n/**\n * Node\n */\nclass Node {\n static buildId(coordinates: number[]) {\n return coordinates.join(\",\");\n }\n\n public id: string;\n public coordinates: number[];\n public innerEdges: Edge[];\n private outerEdges: Edge[];\n private outerEdgesSorted: boolean;\n\n constructor(coordinates: number[]) {\n this.id = Node.buildId(coordinates);\n this.coordinates = coordinates; //< {Number[]}\n this.innerEdges = []; //< {Edge[]}\n\n // We wil store to (out) edges in an CCW order as geos::planargraph::DirectedEdgeStar does\n this.outerEdges = []; //< {Edge[]}\n this.outerEdgesSorted = false; //< {Boolean} flag that stores if the outer Edges had been sorted\n }\n\n removeInnerEdge(edge: Edge) {\n this.innerEdges = this.innerEdges.filter((e) => e.from.id !== edge.from.id);\n }\n\n removeOuterEdge(edge: Edge) {\n this.outerEdges = this.outerEdges.filter((e) => e.to.id !== edge.to.id);\n }\n\n /**\n * Outer edges are stored CCW order.\n *\n * @memberof Node\n * @param {Edge} edge - Edge to add as an outerEdge.\n */\n addOuterEdge(edge: Edge) {\n this.outerEdges.push(edge);\n this.outerEdgesSorted = false;\n }\n\n /**\n * Sorts outer edges in CCW way.\n *\n * @memberof Node\n * @private\n */\n sortOuterEdges() {\n if (!this.outerEdgesSorted) {\n //this.outerEdges.sort((a, b) => a.compareTo(b));\n // Using this comparator in order to be deterministic\n this.outerEdges.sort((a, b) => {\n const aNode = a.to,\n bNode = b.to;\n\n if (\n aNode.coordinates[0] - this.coordinates[0] >= 0 &&\n bNode.coordinates[0] - this.coordinates[0] < 0\n )\n return 1;\n if (\n aNode.coordinates[0] - this.coordinates[0] < 0 &&\n bNode.coordinates[0] - this.coordinates[0] >= 0\n )\n return -1;\n\n if (\n aNode.coordinates[0] - this.coordinates[0] === 0 &&\n bNode.coordinates[0] - this.coordinates[0] === 0\n ) {\n if (\n aNode.coordinates[1] - this.coordinates[1] >= 0 ||\n bNode.coordinates[1] - this.coordinates[1] >= 0\n )\n return aNode.coordinates[1] - bNode.coordinates[1];\n return bNode.coordinates[1] - aNode.coordinates[1];\n }\n\n const det = orientationIndex(\n this.coordinates,\n aNode.coordinates,\n bNode.coordinates\n );\n if (det < 0) return 1;\n if (det > 0) return -1;\n\n const d1 =\n Math.pow(aNode.coordinates[0] - this.coordinates[0], 2) +\n Math.pow(aNode.coordinates[1] - this.coordinates[1], 2),\n d2 =\n Math.pow(bNode.coordinates[0] - this.coordinates[0], 2) +\n Math.pow(bNode.coordinates[1] - this.coordinates[1], 2);\n\n return d1 - d2;\n });\n this.outerEdgesSorted = true;\n }\n }\n\n /**\n * Retrieves outer edges.\n *\n * They are sorted if they aren't in the CCW order.\n *\n * @memberof Node\n * @returns {Edge[]} - List of outer edges sorted in a CCW order.\n */\n getOuterEdges() {\n this.sortOuterEdges();\n return this.outerEdges;\n }\n\n getOuterEdge(i: number) {\n this.sortOuterEdges();\n return this.outerEdges[i];\n }\n\n addInnerEdge(edge: Edge) {\n this.innerEdges.push(edge);\n }\n}\n\nexport { Node };\nexport default Node;\n","import { lineString } from \"@turf/helpers\";\nimport { orientationIndex } from \"./util.js\";\nimport { Node } from \"./Node.js\";\nimport { EdgeRing } from \"./EdgeRing.js\";\n\n/**\n * This class is inspired by GEOS's geos::operation::polygonize::PolygonizeDirectedEdge\n */\nclass Edge {\n public label?: number;\n public symetric?: Edge;\n public from: Node;\n public to: Node;\n public next?: Edge;\n public ring?: EdgeRing;\n\n /**\n * Creates or get the symetric Edge.\n *\n * @returns {Edge} - Symetric Edge.\n */\n getSymetric() {\n if (!this.symetric) {\n this.symetric = new Edge(this.to, this.from);\n this.symetric.symetric = this;\n }\n\n return this.symetric;\n }\n\n /**\n * @param {Node} from - start node of the Edge\n * @param {Node} to - end node of the edge\n */\n constructor(from: Node, to: Node) {\n this.from = from; //< start\n this.to = to; //< End\n\n this.next = undefined; //< The edge to be computed after\n this.label = undefined; //< Used in order to detect Cut Edges (Bridges)\n this.symetric = undefined; //< The symetric edge of this\n this.ring = undefined; //< EdgeRing in which the Edge is\n\n this.from.addOuterEdge(this);\n this.to.addInnerEdge(this);\n }\n\n /**\n * Removes edge from from and to nodes.\n */\n deleteEdge() {\n this.from.removeOuterEdge(this);\n this.to.removeInnerEdge(this);\n }\n\n /**\n * Compares Edge equallity.\n *\n * An edge is equal to another, if the from and to nodes are the same.\n *\n * @param {Edge} edge - Another Edge\n * @returns {boolean} - True if Edges are equal, False otherwise\n */\n isEqual(edge: Edge) {\n return this.from.id === edge.from.id && this.to.id === edge.to.id;\n }\n\n toString() {\n return `Edge { ${this.from.id} -> ${this.to.id} }`;\n }\n\n /**\n * Returns a LineString representation of the Edge\n *\n * @returns {Feature} - LineString representation of the Edge\n */\n toLineString() {\n return lineString([this.from.coordinates, this.to.coordinates]);\n }\n\n /**\n * Comparator of two edges.\n *\n * Implementation of geos::planargraph::DirectedEdge::compareTo.\n *\n * @param {Edge} edge - Another edge to compare with this one\n * @returns {number} -1 if this Edge has a greater angle with the positive x-axis than b,\n * 0 if the Edges are colinear,\n * 1 otherwise\n */\n compareTo(edge: Edge) {\n return orientationIndex(\n edge.from.coordinates,\n edge.to.coordinates,\n this.to.coordinates\n );\n }\n}\n\nexport { Edge };\nexport default Edge;\n","import { Polygon, Feature, Point, Position } from \"geojson\";\nimport {\n orientationIndex,\n envelopeIsEqual,\n envelopeContains,\n coordinatesEqual,\n} from \"./util.js\";\nimport { multiPoint, polygon, point } from \"@turf/helpers\";\nimport { envelope } from \"@turf/envelope\";\nimport { booleanPointInPolygon } from \"@turf/boolean-point-in-polygon\";\nimport { Edge } from \"./Edge.js\";\n\n/**\n * Ring of edges which form a polygon.\n *\n * The ring may be either an outer shell or a hole.\n *\n * This class is inspired in GEOS's geos::operation::polygonize::EdgeRing\n */\nclass EdgeRing {\n private edges: Edge[];\n private polygon?: Feature<\n Polygon,\n {\n [name: string]: any;\n }\n >;\n private envelope?: Feature<\n Polygon,\n {\n [name: string]: any;\n }\n >;\n\n constructor() {\n this.edges = [];\n this.polygon = undefined; //< Caches Polygon representation\n this.envelope = undefined; //< Caches Envelope representation\n }\n\n /**\n * Add an edge to the ring, inserting it in the last position.\n *\n * @memberof EdgeRing\n * @param {Edge} edge - Edge to be inserted\n */\n push(edge: Edge) {\n this.edges.push(edge);\n this.polygon = this.envelope = undefined;\n }\n\n /**\n * Get Edge.\n *\n * @memberof EdgeRing\n * @param {number} i - Index\n * @returns {Edge} - Edge in the i position\n */\n get(i: number) {\n return this.edges[i];\n }\n\n /**\n * Getter of length property.\n *\n * @memberof EdgeRing\n * @returns {number} - Length of the edge ring.\n */\n get length() {\n return this.edges.length;\n }\n\n /**\n * Similar to Array.prototype.forEach for the list of Edges in the EdgeRing.\n *\n * @memberof EdgeRing\n * @param {Function} f - The same function to be passed to Array.prototype.forEach\n */\n forEach(f: (edge: Edge, index: number, array: Edge[]) => void) {\n this.edges.forEach(f);\n }\n\n /**\n * Similar to Array.prototype.map for the list of Edges in the EdgeRing.\n *\n * @memberof EdgeRing\n * @param {Function} f - The same function to be passed to Array.prototype.map\n * @returns {Array} - The mapped values in the function\n */\n map(f: (edge: Edge, index: number, array: Edge[]) => T): T[] {\n return this.edges.map(f);\n }\n\n /**\n * Similar to Array.prototype.some for the list of Edges in the EdgeRing.\n *\n * @memberof EdgeRing\n * @param {Function} f - The same function to be passed to Array.prototype.some\n * @returns {boolean} - True if an Edge check the condition\n */\n some(f: (edge: Edge, index: number, array: Edge[]) => boolean) {\n return this.edges.some(f);\n }\n\n /**\n * Check if the ring is valid in geomtry terms.\n *\n * A ring must have either 0 or 4 or more points. The first and the last must be\n * equal (in 2D)\n * geos::geom::LinearRing::validateConstruction\n *\n * @memberof EdgeRing\n * @returns {boolean} - Validity of the EdgeRing\n */\n isValid() {\n // TODO: stub\n return true;\n }\n\n /**\n * Tests whether this ring is a hole.\n *\n * A ring is a hole if it is oriented counter-clockwise.\n * Similar implementation of geos::algorithm::CGAlgorithms::isCCW\n *\n * @memberof EdgeRing\n * @returns {boolean} - true: if it is a hole\n */\n isHole() {\n // XXX: Assuming Ring is valid\n // Find highest point\n const hiIndex = this.edges.reduce((high, edge, i) => {\n if (edge.from.coordinates[1] > this.edges[high].from.coordinates[1])\n high = i;\n return high;\n }, 0),\n iPrev = (hiIndex === 0 ? this.length : hiIndex) - 1,\n iNext = (hiIndex + 1) % this.length,\n disc = orientationIndex(\n this.edges[iPrev].from.coordinates,\n this.edges[hiIndex].from.coordinates,\n this.edges[iNext].from.coordinates\n );\n\n if (disc === 0)\n return (\n this.edges[iPrev].from.coordinates[0] >\n this.edges[iNext].from.coordinates[0]\n );\n return disc > 0;\n }\n\n /**\n * Creates a MultiPoint representing the EdgeRing (discarts edges directions).\n *\n * @memberof EdgeRing\n * @returns {Feature} - Multipoint representation of the EdgeRing\n */\n toMultiPoint() {\n return multiPoint(this.edges.map((edge) => edge.from.coordinates));\n }\n\n /**\n * Creates a Polygon representing the EdgeRing.\n *\n * @memberof EdgeRing\n * @returns {Feature} - Polygon representation of the Edge Ring\n */\n toPolygon() {\n if (this.polygon) return this.polygon;\n const coordinates = this.edges.map((edge) => edge.from.coordinates);\n coordinates.push(this.edges[0].from.coordinates);\n return (this.polygon = polygon([coordinates]));\n }\n\n /**\n * Calculates the envelope of the EdgeRing.\n *\n * @memberof EdgeRing\n * @returns {Feature} - envelope\n */\n getEnvelope() {\n if (this.envelope) return this.envelope;\n return (this.envelope = envelope(this.toPolygon()) as Feature<\n Polygon,\n { [name: string]: any }\n >);\n }\n\n /**\n * `geos::operation::polygonize::EdgeRing::findEdgeRingContaining`\n *\n * @param {EdgeRing} testEdgeRing - EdgeRing to look in the list\n * @param {EdgeRing[]} shellList - List of EdgeRing in which to search\n *\n * @returns {EdgeRing} - EdgeRing which contains the testEdgeRing\n */\n static findEdgeRingContaining(\n testEdgeRing: EdgeRing,\n shellList: EdgeRing[]\n ): EdgeRing | undefined {\n const testEnvelope = testEdgeRing.getEnvelope();\n\n let minEnvelope: Feature, minShell: EdgeRing | undefined;\n shellList.forEach((shell) => {\n const tryEnvelope = shell.getEnvelope();\n\n if (minShell) minEnvelope = minShell.getEnvelope();\n\n // the hole envelope cannot equal the shell envelope\n if (envelopeIsEqual(tryEnvelope, testEnvelope)) return;\n\n if (envelopeContains(tryEnvelope, testEnvelope)) {\n const testEdgeRingCoordinates = testEdgeRing.map(\n (edge) => edge.from.coordinates\n );\n\n let testPoint: Position | undefined;\n for (const pt of testEdgeRingCoordinates) {\n if (\n !shell.some((edge) => coordinatesEqual(pt, edge.from.coordinates))\n ) {\n testPoint = pt;\n }\n }\n\n if (testPoint && shell.inside(point(testPoint))) {\n if (!minShell || envelopeContains(minEnvelope, tryEnvelope))\n minShell = shell;\n }\n }\n });\n\n return minShell;\n }\n\n /**\n * Checks if the point is inside the edgeRing\n *\n * @param {Feature} pt - Point to check if it is inside the edgeRing\n * @returns {boolean} - True if it is inside, False otherwise\n */\n inside(pt: Feature) {\n return booleanPointInPolygon(pt, this.toPolygon());\n }\n}\n\nexport { EdgeRing };\nexport default EdgeRing;\n","import { Node } from \"./Node.js\";\nimport { Edge } from \"./Edge.js\";\nimport { EdgeRing } from \"./EdgeRing.js\";\nimport { flattenEach, coordReduce } from \"@turf/meta\";\nimport { featureOf } from \"@turf/invariant\";\nimport {\n FeatureCollection,\n LineString,\n MultiLineString,\n Feature,\n} from \"geojson\";\nimport { AllGeoJSON } from \"@turf/helpers\";\n\n/**\n * Validates the geoJson.\n *\n * @param {GeoJSON} geoJson - input geoJson.\n * @throws {Error} if geoJson is invalid.\n */\nfunction validateGeoJson(geoJson: AllGeoJSON) {\n if (!geoJson) throw new Error(\"No geojson passed\");\n\n if (\n geoJson.type !== \"FeatureCollection\" &&\n geoJson.type !== \"GeometryCollection\" &&\n geoJson.type !== \"MultiLineString\" &&\n geoJson.type !== \"LineString\" &&\n geoJson.type !== \"Feature\"\n )\n throw new Error(\n `Invalid input type '${geoJson.type}'. Geojson must be FeatureCollection, GeometryCollection, LineString, MultiLineString or Feature`\n );\n}\n\n/**\n * Represents a planar graph of edges and nodes that can be used to compute a polygonization.\n *\n * Although, this class is inspired by GEOS's `geos::operation::polygonize::PolygonizeGraph`,\n * it isn't a rewrite. As regards algorithm, this class implements the same logic, but it\n * isn't a javascript transcription of the C++ source.\n *\n * This graph is directed (both directions are created)\n */\nclass Graph {\n private nodes: { [id: string]: Node };\n private edges: Edge[];\n\n /**\n * Creates a graph from a GeoJSON.\n *\n * @param {FeatureCollection} geoJson - it must comply with the restrictions detailed in the index\n * @returns {Graph} - The newly created graph\n * @throws {Error} if geoJson is invalid.\n */\n static fromGeoJson(\n geoJson:\n | FeatureCollection\n | LineString\n | MultiLineString\n | Feature\n ) {\n validateGeoJson(geoJson);\n\n const graph = new Graph();\n flattenEach(geoJson, (feature) => {\n featureOf(feature, \"LineString\", \"Graph::fromGeoJson\");\n // When a LineString if formed by many segments, split them\n coordReduce(feature, (prev, cur) => {\n if (prev) {\n const start = graph.getNode(prev),\n end = graph.getNode(cur);\n\n graph.addEdge(start, end);\n }\n return cur;\n });\n });\n\n return graph;\n }\n\n /**\n * Creates or get a Node.\n *\n * @param {number[]} coordinates - Coordinates of the node\n * @returns {Node} - The created or stored node\n */\n getNode(coordinates: number[]) {\n const id = Node.buildId(coordinates);\n let node = this.nodes[id];\n if (!node) node = this.nodes[id] = new Node(coordinates);\n\n return node;\n }\n\n /**\n * Adds an Edge and its symetricall.\n *\n * Edges are added symetrically, i.e.: we also add its symetric\n *\n * @param {Node} from - Node which starts the Edge\n * @param {Node} to - Node which ends the Edge\n */\n addEdge(from: Node, to: Node) {\n const edge = new Edge(from, to),\n symetricEdge = edge.getSymetric();\n\n this.edges.push(edge);\n this.edges.push(symetricEdge);\n }\n\n constructor() {\n this.edges = []; //< {Edge[]} dirEdges\n\n // The key is the `id` of the Node (ie: coordinates.join(','))\n this.nodes = {};\n }\n\n /**\n * Removes Dangle Nodes (nodes with grade 1).\n */\n deleteDangles() {\n Object.keys(this.nodes)\n .map((id) => this.nodes[id])\n .forEach((node) => this._removeIfDangle(node));\n }\n\n /**\n * Check if node is dangle, if so, remove it.\n *\n * It calls itself recursively, removing a dangling node might cause another dangling node\n *\n * @param {Node} node - Node to check if it's a dangle\n */\n _removeIfDangle(node: Node) {\n // As edges are directed and symetrical, we count only innerEdges\n if (node.innerEdges.length <= 1) {\n const outerNodes = node.getOuterEdges().map((e) => e.to);\n this.removeNode(node);\n outerNodes.forEach((n) => this._removeIfDangle(n));\n }\n }\n\n /**\n * Delete cut-edges (bridge edges).\n *\n * The graph will be traversed, all the edges will be labeled according the ring\n * in which they are. (The label is a number incremented by 1). Edges with the same\n * label are cut-edges.\n */\n deleteCutEdges() {\n this._computeNextCWEdges();\n this._findLabeledEdgeRings();\n\n // Cut-edges (bridges) are edges where both edges have the same label\n this.edges.forEach((edge) => {\n if (edge.label === edge.symetric!.label) {\n this.removeEdge(edge.symetric!);\n this.removeEdge(edge);\n }\n });\n }\n\n /**\n * Set the `next` property of each Edge.\n *\n * The graph will be transversed in a CW form, so, we set the next of the symetrical edge as the previous one.\n * OuterEdges are sorted CCW.\n *\n * @param {Node} [node] - If no node is passed, the function calls itself for every node in the Graph\n */\n _computeNextCWEdges(node?: Node) {\n if (typeof node === \"undefined\") {\n Object.keys(this.nodes).forEach((id) =>\n this._computeNextCWEdges(this.nodes[id])\n );\n } else {\n node.getOuterEdges().forEach((edge, i) => {\n node.getOuterEdge(\n (i === 0 ? node.getOuterEdges().length : i) - 1\n ).symetric!.next = edge;\n });\n }\n }\n\n /**\n * Computes the next edge pointers going CCW around the given node, for the given edgering label.\n *\n * This algorithm has the effect of converting maximal edgerings into minimal edgerings\n *\n * XXX: method literally transcribed from `geos::operation::polygonize::PolygonizeGraph::computeNextCCWEdges`,\n * could be written in a more javascript way.\n *\n * @param {Node} node - Node\n * @param {number} label - Ring's label\n */\n _computeNextCCWEdges(node: Node, label: number) {\n const edges = node.getOuterEdges();\n let firstOutDE, prevInDE;\n\n for (let i = edges.length - 1; i >= 0; --i) {\n let de = edges[i],\n sym = de.symetric,\n outDE,\n inDE;\n\n if (de.label === label) outDE = de;\n\n if (sym!.label === label) inDE = sym;\n\n if (!outDE || !inDE)\n // This edge is not in edgering\n continue;\n\n if (inDE) prevInDE = inDE;\n\n if (outDE) {\n if (prevInDE) {\n prevInDE.next = outDE;\n prevInDE = undefined;\n }\n\n if (!firstOutDE) firstOutDE = outDE;\n }\n }\n\n if (prevInDE) prevInDE.next = firstOutDE;\n }\n\n /**\n * Finds rings and labels edges according to which rings are.\n *\n * The label is a number which is increased for each ring.\n *\n * @returns {Edge[]} edges that start rings\n */\n _findLabeledEdgeRings() {\n const edgeRingStarts: Edge[] = [];\n let label = 0;\n this.edges.forEach((edge) => {\n if (edge.label! >= 0) return;\n\n edgeRingStarts.push(edge);\n\n let e = edge;\n do {\n e.label = label;\n e = e.next!;\n } while (!edge.isEqual(e));\n\n label++;\n });\n\n return edgeRingStarts;\n }\n\n /**\n * Computes the EdgeRings formed by the edges in this graph.\n *\n * @returns {EdgeRing[]} - A list of all the EdgeRings in the graph.\n */\n getEdgeRings() {\n this._computeNextCWEdges();\n\n // Clear labels\n this.edges.forEach((edge) => {\n edge.label = undefined;\n });\n\n this._findLabeledEdgeRings().forEach((edge) => {\n // convertMaximalToMinimalEdgeRings\n this._findIntersectionNodes(edge).forEach((node) => {\n this._computeNextCCWEdges(node, edge.label!);\n });\n });\n\n const edgeRingList: EdgeRing[] = [];\n\n // find all edgerings\n this.edges.forEach((edge) => {\n if (edge.ring) return;\n edgeRingList.push(this._findEdgeRing(edge));\n });\n\n return edgeRingList;\n }\n\n /**\n * Find all nodes in a Maxima EdgeRing which are self-intersection nodes.\n *\n * @param {Node} startEdge - Start Edge of the Ring\n * @returns {Node[]} - intersection nodes\n */\n _findIntersectionNodes(startEdge: Edge) {\n const intersectionNodes = [];\n let edge = startEdge;\n do {\n // getDegree\n let degree = 0;\n edge.from.getOuterEdges().forEach((e) => {\n if (e.label === startEdge.label) ++degree;\n });\n\n if (degree > 1) intersectionNodes.push(edge.from);\n\n edge = edge.next!;\n } while (!startEdge.isEqual(edge));\n\n return intersectionNodes;\n }\n\n /**\n * Get the edge-ring which starts from the provided Edge.\n *\n * @param {Edge} startEdge - starting edge of the edge ring\n * @returns {EdgeRing} - EdgeRing which start Edge is the provided one.\n */\n _findEdgeRing(startEdge: Edge) {\n let edge = startEdge;\n const edgeRing = new EdgeRing();\n\n do {\n edgeRing.push(edge);\n edge.ring = edgeRing;\n edge = edge.next!;\n } while (!startEdge.isEqual(edge));\n\n return edgeRing;\n }\n\n /**\n * Removes a node from the Graph.\n *\n * It also removes edges asociated to that node\n * @param {Node} node - Node to be removed\n */\n removeNode(node: Node) {\n node.getOuterEdges().forEach((edge) => this.removeEdge(edge));\n node.innerEdges.forEach((edge) => this.removeEdge(edge));\n delete this.nodes[node.id];\n }\n\n /**\n * Remove edge from the graph and deletes the edge.\n *\n * @param {Edge} edge - Edge to be removed\n */\n removeEdge(edge: Edge) {\n this.edges = this.edges.filter((e) => !e.isEqual(edge));\n edge.deleteEdge();\n }\n}\n\nexport { Graph };\nexport default Graph;\n"],"mappings":"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","names":["point","booleanPointInPolygon"]}