\n * The WKTWriter
outputs coordinates rounded to the precision\n * model. Only the maximum number of decimal places necessary to represent the\n * ordinates to the required precision will be output.\n *
\n * The SFS WKT spec does not define a special tag for {@link LinearRing}s.\n * Under the spec, rings are output as \n * LINESTRING
s.\n */\nexport default class WKTWriter {\n /**\n * @param {GeometryFactory} geometryFactory\n */\n constructor(geometryFactory) {\n this.parser = new WKTParser(geometryFactory)\n }\n\n /**\n * Converts a Geometry
to its Well-known Text representation.\n *\n * @param {Geometry} geometry a Geometry
to process.\n * @return {string} a GeoJSONReader
is parameterized by a GeometryFactory
,\n * to allow it to create Geometry
objects of the appropriate\n * implementation. In particular, the GeometryFactory
determines\n * the PrecisionModel
and SRID
that is used.\n *\n * @param {GeometryFactory} geometryFactory\n */\n constructor(geometryFactory) {\n this.parser = new GeoJSONParser(geometryFactory || new GeometryFactory())\n }\n\n /**\n * Reads a GeoJSON representation of a {@link Geometry}\n *\n * Will also parse GeoJSON Features/FeatureCollections as custom objects.\n *\n * @param {Object|String} geoJson a GeoJSON Object or String.\n * @return {Geometry|Object} a Geometry or Feature/FeatureCollection representation.
\n * @memberof module:org/locationtech/jts/io/GeoJSONReader#\n */\n read(geoJson) {\n const geometry = this.parser.read(geoJson)\n return geometry\n }\n}\n","/**\n * @module org/locationtech/jts/io/GeoJSONWriter\n */\n\nimport GeoJSONParser from './GeoJSONParser.js'\n\n/**\n * Writes the GeoJSON representation of a {@link Geometry}. The\n * The GeoJSON format is defined here.\n */\nexport default class GeoJSONWriter {\n /**\n * The GeoJSONWriter
outputs coordinates rounded to the precision\n * model. Only the maximum number of decimal places necessary to represent the\n * ordinates to the required precision will be output.\n *\n * @param {GeometryFactory} geometryFactory\n * @constructor\n */\n constructor() {\n this.parser = new GeoJSONParser(this.geometryFactory)\n }\n\n /**\n * Converts a Geometry
to its GeoJSON representation.\n *\n * @param {Geometry}\n * geometry a Geometry
to process.\n * @return {Object} The GeoJSON representation of the Geometry.\n * @memberof module:org/locationtech/jts/io/GeoJSONWriter#\n */\n write(geometry) {\n return this.parser.write(geometry)\n }\n}\n","/**\n * @module org/locationtech/jts/io/WKTReader\n */\n\nimport GeometryFactory from '../geom/GeometryFactory.js'\nimport WKTParser from './WKTParser.js'\n\n/**\n * Converts a geometry in Well-Known Text format to a {@link Geometry}.\n * WKTReader
supports extracting Geometry
objects\n * from either {@link Reader}s or {@link String}s. This allows it to function\n * as a parser to read Geometry
objects from text blocks embedded\n * in other data formats (e.g. XML).\n */\n\nexport default class WKTReader {\n /**\n * A WKTReader
is parameterized by a GeometryFactory
,\n * to allow it to create Geometry
objects of the appropriate\n * implementation. In particular, the GeometryFactory
determines\n * the PrecisionModel
and SRID
that is used.\n * @param {GeometryFactory} geometryFactory\n */\n constructor(geometryFactory) {\n this.parser = new WKTParser(geometryFactory || new GeometryFactory())\n }\n\n /**\n * Reads a Well-Known Text representation of a {@link Geometry}\n *\n * @param {string}\n * wkt a Geometry
read from\n * string.
\n * @memberof module:org/locationtech/jts/io/WKTReader#\n */\n read(wkt) {\n return this.parser.read(wkt)\n }\n}\n","import Assert from '../util/Assert.js'\nexport default class SegmentPointComparator {\n static relativeSign(x0, x1) {\n if (x0 < x1) return -1\n if (x0 > x1) return 1\n return 0\n }\n static compare(octant, p0, p1) {\n if (p0.equals2D(p1)) return 0\n const xSign = SegmentPointComparator.relativeSign(p0.x, p1.x)\n const ySign = SegmentPointComparator.relativeSign(p0.y, p1.y)\n switch (octant) {\n case 0:\n return SegmentPointComparator.compareValue(xSign, ySign)\n case 1:\n return SegmentPointComparator.compareValue(ySign, xSign)\n case 2:\n return SegmentPointComparator.compareValue(ySign, -xSign)\n case 3:\n return SegmentPointComparator.compareValue(-xSign, ySign)\n case 4:\n return SegmentPointComparator.compareValue(-xSign, -ySign)\n case 5:\n return SegmentPointComparator.compareValue(-ySign, -xSign)\n case 6:\n return SegmentPointComparator.compareValue(-ySign, xSign)\n case 7:\n return SegmentPointComparator.compareValue(xSign, -ySign)\n }\n Assert.shouldNeverReachHere('invalid octant value')\n return 0\n }\n static compareValue(compareSign0, compareSign1) {\n if (compareSign0 < 0) return -1\n if (compareSign0 > 0) return 1\n if (compareSign1 < 0) return -1\n if (compareSign1 > 0) return 1\n return 0\n }\n}\n","import Coordinate from '../geom/Coordinate.js'\nimport SegmentPointComparator from './SegmentPointComparator.js'\nimport Comparable from '../../../../java/lang/Comparable.js'\nexport default class SegmentNode {\n constructor() {\n SegmentNode.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._segString = null\n this.coord = null\n this.segmentIndex = null\n this._segmentOctant = null\n this._isInterior = null\n const segString = arguments[0], coord = arguments[1], segmentIndex = arguments[2], segmentOctant = arguments[3]\n this._segString = segString\n this.coord = new Coordinate(coord)\n this.segmentIndex = segmentIndex\n this._segmentOctant = segmentOctant\n this._isInterior = !coord.equals2D(segString.getCoordinate(segmentIndex))\n }\n getCoordinate() {\n return this.coord\n }\n print(out) {\n out.print(this.coord)\n out.print(' seg # = ' + this.segmentIndex)\n }\n compareTo(obj) {\n const other = obj\n if (this.segmentIndex < other.segmentIndex) return -1\n if (this.segmentIndex > other.segmentIndex) return 1\n if (this.coord.equals2D(other.coord)) return 0\n if (!this._isInterior) return -1\n if (!other._isInterior) return 1\n return SegmentPointComparator.compare(this._segmentOctant, this.coord, other.coord)\n }\n isEndPoint(maxSegmentIndex) {\n if (this.segmentIndex === 0 && !this._isInterior) return true\n if (this.segmentIndex === maxSegmentIndex) return true\n return false\n }\n toString() {\n return this.segmentIndex + ':' + this.coord.toString()\n }\n isInterior() {\n return this._isInterior\n }\n get interfaces_() {\n return [Comparable]\n }\n}\n","import CoordinateList from '../geom/CoordinateList.js'\nimport SegmentNode from './SegmentNode.js'\nimport Iterator from '../../../../java/util/Iterator.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport NodedSegmentString from './NodedSegmentString.js'\nimport Integer from '../../../../java/lang/Integer.js'\nimport UnsupportedOperationException from '../../../../java/lang/UnsupportedOperationException.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport RuntimeException from '../../../../java/lang/RuntimeException.js'\nimport Assert from '../util/Assert.js'\nimport TreeMap from '../../../../java/util/TreeMap.js'\nexport default class SegmentNodeList {\n constructor() {\n SegmentNodeList.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._nodeMap = new TreeMap()\n this._edge = null\n const edge = arguments[0]\n this._edge = edge\n }\n getSplitCoordinates() {\n const coordList = new CoordinateList()\n this.addEndpoints()\n const it = this.iterator()\n let eiPrev = it.next()\n while (it.hasNext()) {\n const ei = it.next()\n this.addEdgeCoordinates(eiPrev, ei, coordList)\n eiPrev = ei\n }\n return coordList.toCoordinateArray()\n }\n addCollapsedNodes() {\n const collapsedVertexIndexes = new ArrayList()\n this.findCollapsesFromInsertedNodes(collapsedVertexIndexes)\n this.findCollapsesFromExistingVertices(collapsedVertexIndexes)\n for (let it = collapsedVertexIndexes.iterator(); it.hasNext(); ) {\n const vertexIndex = it.next().intValue()\n this.add(this._edge.getCoordinate(vertexIndex), vertexIndex)\n }\n }\n createSplitEdgePts(ei0, ei1) {\n let npts = ei1.segmentIndex - ei0.segmentIndex + 2\n if (npts === 2) return [new Coordinate(ei0.coord), new Coordinate(ei1.coord)]\n const lastSegStartPt = this._edge.getCoordinate(ei1.segmentIndex)\n const useIntPt1 = ei1.isInterior() || !ei1.coord.equals2D(lastSegStartPt)\n if (!useIntPt1) \n npts--\n \n const pts = new Array(npts).fill(null)\n let ipt = 0\n pts[ipt++] = new Coordinate(ei0.coord)\n for (let i = ei0.segmentIndex + 1; i <= ei1.segmentIndex; i++) \n pts[ipt++] = this._edge.getCoordinate(i)\n \n if (useIntPt1) pts[ipt] = new Coordinate(ei1.coord)\n return pts\n }\n print(out) {\n out.println('Intersections:')\n for (let it = this.iterator(); it.hasNext(); ) {\n const ei = it.next()\n ei.print(out)\n }\n }\n findCollapsesFromExistingVertices(collapsedVertexIndexes) {\n for (let i = 0; i < this._edge.size() - 2; i++) {\n const p0 = this._edge.getCoordinate(i)\n const p1 = this._edge.getCoordinate(i + 1)\n const p2 = this._edge.getCoordinate(i + 2)\n if (p0.equals2D(p2)) \n collapsedVertexIndexes.add(Integer.valueOf(i + 1))\n \n }\n }\n addEdgeCoordinates(ei0, ei1, coordList) {\n const pts = this.createSplitEdgePts(ei0, ei1)\n coordList.add(pts, false)\n }\n iterator() {\n return this._nodeMap.values().iterator()\n }\n addSplitEdges(edgeList) {\n this.addEndpoints()\n this.addCollapsedNodes()\n const it = this.iterator()\n let eiPrev = it.next()\n while (it.hasNext()) {\n const ei = it.next()\n const newEdge = this.createSplitEdge(eiPrev, ei)\n edgeList.add(newEdge)\n eiPrev = ei\n }\n }\n findCollapseIndex(ei0, ei1, collapsedVertexIndex) {\n if (!ei0.coord.equals2D(ei1.coord)) return false\n let numVerticesBetween = ei1.segmentIndex - ei0.segmentIndex\n if (!ei1.isInterior()) \n numVerticesBetween--\n \n if (numVerticesBetween === 1) {\n collapsedVertexIndex[0] = ei0.segmentIndex + 1\n return true\n }\n return false\n }\n findCollapsesFromInsertedNodes(collapsedVertexIndexes) {\n const collapsedVertexIndex = new Array(1).fill(null)\n const it = this.iterator()\n let eiPrev = it.next()\n while (it.hasNext()) {\n const ei = it.next()\n const isCollapsed = this.findCollapseIndex(eiPrev, ei, collapsedVertexIndex)\n if (isCollapsed) collapsedVertexIndexes.add(Integer.valueOf(collapsedVertexIndex[0]))\n eiPrev = ei\n }\n }\n getEdge() {\n return this._edge\n }\n addEndpoints() {\n const maxSegIndex = this._edge.size() - 1\n this.add(this._edge.getCoordinate(0), 0)\n this.add(this._edge.getCoordinate(maxSegIndex), maxSegIndex)\n }\n createSplitEdge(ei0, ei1) {\n const pts = this.createSplitEdgePts(ei0, ei1)\n return new NodedSegmentString(pts, this._edge.getData())\n }\n add(intPt, segmentIndex) {\n const eiNew = new SegmentNode(this._edge, intPt, segmentIndex, this._edge.getSegmentOctant(segmentIndex))\n const ei = this._nodeMap.get(eiNew)\n if (ei !== null) {\n Assert.isTrue(ei.coord.equals2D(intPt), 'Found equal nodes with different coordinates')\n return ei\n }\n this._nodeMap.put(eiNew, eiNew)\n return eiNew\n }\n checkSplitEdgesCorrectness(splitEdges) {\n const edgePts = this._edge.getCoordinates()\n const split0 = splitEdges.get(0)\n const pt0 = split0.getCoordinate(0)\n if (!pt0.equals2D(edgePts[0])) throw new RuntimeException('bad split edge start point at ' + pt0)\n const splitn = splitEdges.get(splitEdges.size() - 1)\n const splitnPts = splitn.getCoordinates()\n const ptn = splitnPts[splitnPts.length - 1]\n if (!ptn.equals2D(edgePts[edgePts.length - 1])) throw new RuntimeException('bad split edge end point at ' + ptn)\n }\n}\nclass NodeVertexIterator {\n constructor() {\n NodeVertexIterator.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._nodeList = null\n this._edge = null\n this._nodeIt = null\n this._currNode = null\n this._nextNode = null\n this._currSegIndex = 0\n const nodeList = arguments[0]\n this._nodeList = nodeList\n this._edge = nodeList.getEdge()\n this._nodeIt = nodeList.iterator()\n this.readNextNode()\n }\n next() {\n if (this._currNode === null) {\n this._currNode = this._nextNode\n this._currSegIndex = this._currNode.segmentIndex\n this.readNextNode()\n return this._currNode\n }\n if (this._nextNode === null) return null\n if (this._nextNode.segmentIndex === this._currNode.segmentIndex) {\n this._currNode = this._nextNode\n this._currSegIndex = this._currNode.segmentIndex\n this.readNextNode()\n return this._currNode\n }\n if (this._nextNode.segmentIndex > this._currNode.segmentIndex) {}\n return null\n }\n remove() {\n throw new UnsupportedOperationException(this.getClass().getName())\n }\n hasNext() {\n if (this._nextNode === null) return false\n return true\n }\n readNextNode() {\n if (this._nodeIt.hasNext()) this._nextNode = this._nodeIt.next(); else this._nextNode = null\n }\n get interfaces_() {\n return [Iterator]\n }\n}\n","import Coordinate from '../geom/Coordinate.js'\nimport IllegalArgumentException from '../../../../java/lang/IllegalArgumentException.js'\nexport default class Octant {\n static octant() {\n if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {\n const dx = arguments[0], dy = arguments[1]\n if (dx === 0.0 && dy === 0.0) throw new IllegalArgumentException('Cannot compute the octant for point ( ' + dx + ', ' + dy + ' )')\n const adx = Math.abs(dx)\n const ady = Math.abs(dy)\n if (dx >= 0) \n if (dy >= 0) \n if (adx >= ady) return 0; else return 1\n else \n if (adx >= ady) return 7; else return 6\n \n else \n if (dy >= 0) \n if (adx >= ady) return 3; else return 2\n else \n if (adx >= ady) return 4; else return 5\n \n \n } else if (arguments[0] instanceof Coordinate && arguments[1] instanceof Coordinate) {\n const p0 = arguments[0], p1 = arguments[1]\n const dx = p1.x - p0.x\n const dy = p1.y - p0.y\n if (dx === 0.0 && dy === 0.0) throw new IllegalArgumentException('Cannot compute the octant for two identical points ' + p0)\n return Octant.octant(dx, dy)\n }\n }\n}\n","export default class SegmentString {\n getCoordinates() {}\n size() {}\n getCoordinate(i) {}\n isClosed() {}\n setData(data) {}\n getData() {}\n}\n","import SegmentString from './SegmentString.js'\nexport default class NodableSegmentString {\n addIntersection(intPt, segmentIndex) {}\n get interfaces_() {\n return [SegmentString]\n }\n}\n","import SegmentNodeList from './SegmentNodeList.js'\nimport WKTWriter from '../io/WKTWriter.js'\nimport CoordinateArraySequence from '../geom/impl/CoordinateArraySequence.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport Octant from './Octant.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport NodableSegmentString from './NodableSegmentString.js'\nexport default class NodedSegmentString {\n constructor() {\n NodedSegmentString.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._nodeList = new SegmentNodeList(this)\n this._pts = null\n this._data = null\n const pts = arguments[0], data = arguments[1]\n this._pts = pts\n this._data = data\n }\n static getNodedSubstrings() {\n if (arguments.length === 1) {\n const segStrings = arguments[0]\n const resultEdgelist = new ArrayList()\n NodedSegmentString.getNodedSubstrings(segStrings, resultEdgelist)\n return resultEdgelist\n } else if (arguments.length === 2) {\n const segStrings = arguments[0], resultEdgelist = arguments[1]\n for (let i = segStrings.iterator(); i.hasNext(); ) {\n const ss = i.next()\n ss.getNodeList().addSplitEdges(resultEdgelist)\n }\n }\n }\n getCoordinates() {\n return this._pts\n }\n size() {\n return this._pts.length\n }\n getCoordinate(i) {\n return this._pts[i]\n }\n isClosed() {\n return this._pts[0].equals(this._pts[this._pts.length - 1])\n }\n getSegmentOctant(index) {\n if (index === this._pts.length - 1) return -1\n return this.safeOctant(this.getCoordinate(index), this.getCoordinate(index + 1))\n }\n setData(data) {\n this._data = data\n }\n safeOctant(p0, p1) {\n if (p0.equals2D(p1)) return 0\n return Octant.octant(p0, p1)\n }\n getData() {\n return this._data\n }\n addIntersection() {\n if (arguments.length === 2) {\n const intPt = arguments[0], segmentIndex = arguments[1]\n this.addIntersectionNode(intPt, segmentIndex)\n } else if (arguments.length === 4) {\n const li = arguments[0], segmentIndex = arguments[1], geomIndex = arguments[2], intIndex = arguments[3]\n const intPt = new Coordinate(li.getIntersection(intIndex))\n this.addIntersection(intPt, segmentIndex)\n }\n }\n toString() {\n return WKTWriter.toLineString(new CoordinateArraySequence(this._pts))\n }\n getNodeList() {\n return this._nodeList\n }\n addIntersectionNode(intPt, segmentIndex) {\n let normalizedSegmentIndex = segmentIndex\n const nextSegIndex = normalizedSegmentIndex + 1\n if (nextSegIndex < this._pts.length) {\n const nextPt = this._pts[nextSegIndex]\n if (intPt.equals2D(nextPt)) \n normalizedSegmentIndex = nextSegIndex\n \n }\n const ei = this._nodeList.add(intPt, normalizedSegmentIndex)\n return ei\n }\n addIntersections(li, segmentIndex, geomIndex) {\n for (let i = 0; i < li.getIntersectionNum(); i++) \n this.addIntersection(li, segmentIndex, geomIndex, i)\n \n }\n get interfaces_() {\n return [NodableSegmentString]\n }\n}\n","import LineSegment from '../../geom/LineSegment.js'\nexport default class MonotoneChainOverlapAction {\n constructor() {\n MonotoneChainOverlapAction.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._overlapSeg1 = new LineSegment()\n this._overlapSeg2 = new LineSegment()\n }\n overlap() {\n if (arguments.length === 2) {\n const seg1 = arguments[0], seg2 = arguments[1]\n } else if (arguments.length === 4) {\n const mc1 = arguments[0], start1 = arguments[1], mc2 = arguments[2], start2 = arguments[3]\n mc1.getLineSegment(start1, this._overlapSeg1)\n mc2.getLineSegment(start2, this._overlapSeg2)\n this.overlap(this._overlapSeg1, this._overlapSeg2)\n }\n }\n}\n","import Envelope from '../../geom/Envelope.js'\nexport default class MonotoneChain {\n constructor() {\n MonotoneChain.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pts = null\n this._start = null\n this._end = null\n this._env = null\n this._context = null\n this._id = null\n const pts = arguments[0], start = arguments[1], end = arguments[2], context = arguments[3]\n this._pts = pts\n this._start = start\n this._end = end\n this._context = context\n }\n getLineSegment(index, ls) {\n ls.p0 = this._pts[index]\n ls.p1 = this._pts[index + 1]\n }\n computeSelect(searchEnv, start0, end0, mcs) {\n const p0 = this._pts[start0]\n const p1 = this._pts[end0]\n if (end0 - start0 === 1) {\n mcs.select(this, start0)\n return null\n }\n if (!searchEnv.intersects(p0, p1)) return null\n const mid = Math.trunc((start0 + end0) / 2)\n if (start0 < mid) \n this.computeSelect(searchEnv, start0, mid, mcs)\n \n if (mid < end0) \n this.computeSelect(searchEnv, mid, end0, mcs)\n \n }\n getCoordinates() {\n const coord = new Array(this._end - this._start + 1).fill(null)\n let index = 0\n for (let i = this._start; i <= this._end; i++) \n coord[index++] = this._pts[i]\n \n return coord\n }\n computeOverlaps() {\n if (arguments.length === 2) {\n const mc = arguments[0], mco = arguments[1]\n this.computeOverlaps(this._start, this._end, mc, mc._start, mc._end, mco)\n } else if (arguments.length === 6) {\n const start0 = arguments[0], end0 = arguments[1], mc = arguments[2], start1 = arguments[3], end1 = arguments[4], mco = arguments[5]\n if (end0 - start0 === 1 && end1 - start1 === 1) {\n mco.overlap(this, start0, mc, start1)\n return null\n }\n if (!this.overlaps(start0, end0, mc, start1, end1)) return null\n const mid0 = Math.trunc((start0 + end0) / 2)\n const mid1 = Math.trunc((start1 + end1) / 2)\n if (start0 < mid0) {\n if (start1 < mid1) this.computeOverlaps(start0, mid0, mc, start1, mid1, mco)\n if (mid1 < end1) this.computeOverlaps(start0, mid0, mc, mid1, end1, mco)\n }\n if (mid0 < end0) {\n if (start1 < mid1) this.computeOverlaps(mid0, end0, mc, start1, mid1, mco)\n if (mid1 < end1) this.computeOverlaps(mid0, end0, mc, mid1, end1, mco)\n }\n }\n }\n setId(id) {\n this._id = id\n }\n select(searchEnv, mcs) {\n this.computeSelect(searchEnv, this._start, this._end, mcs)\n }\n getEnvelope() {\n if (this._env === null) {\n const p0 = this._pts[this._start]\n const p1 = this._pts[this._end]\n this._env = new Envelope(p0, p1)\n }\n return this._env\n }\n overlaps(start0, end0, mc, start1, end1) {\n return Envelope.intersects(this._pts[start0], this._pts[end0], mc._pts[start1], mc._pts[end1])\n }\n getEndIndex() {\n return this._end\n }\n getStartIndex() {\n return this._start\n }\n getContext() {\n return this._context\n }\n getId() {\n return this._id\n }\n}\n","import MonotoneChain from './MonotoneChain.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Quadrant from '../../geomgraph/Quadrant.js'\nexport default class MonotoneChainBuilder {\n static findChainEnd(pts, start) {\n let safeStart = start\n while (safeStart < pts.length - 1 && pts[safeStart].equals2D(pts[safeStart + 1])) \n safeStart++\n \n if (safeStart >= pts.length - 1) \n return pts.length - 1\n \n const chainQuad = Quadrant.quadrant(pts[safeStart], pts[safeStart + 1])\n let last = start + 1\n while (last < pts.length) {\n if (!pts[last - 1].equals2D(pts[last])) {\n const quad = Quadrant.quadrant(pts[last - 1], pts[last])\n if (quad !== chainQuad) break\n }\n last++\n }\n return last - 1\n }\n static getChains() {\n if (arguments.length === 1) {\n const pts = arguments[0]\n return MonotoneChainBuilder.getChains(pts, null)\n } else if (arguments.length === 2) {\n const pts = arguments[0], context = arguments[1]\n const mcList = new ArrayList()\n let chainStart = 0\n do {\n const chainEnd = MonotoneChainBuilder.findChainEnd(pts, chainStart)\n const mc = new MonotoneChain(pts, chainStart, chainEnd, context)\n mcList.add(mc)\n chainStart = chainEnd\n } while (chainStart < pts.length - 1)\n return mcList\n }\n }\n}\n","export default class Noder {\n computeNodes(segStrings) {}\n getNodedSubstrings() {}\n}\n","import Noder from './Noder.js'\nexport default class SinglePassNoder {\n constructor() {\n SinglePassNoder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._segInt = null\n if (arguments.length === 0) {} else if (arguments.length === 1) {\n const segInt = arguments[0]\n this.setSegmentIntersector(segInt)\n }\n }\n setSegmentIntersector(segInt) {\n this._segInt = segInt\n }\n get interfaces_() {\n return [Noder]\n }\n}\n","import STRtree from '../index/strtree/STRtree.js'\nimport NodedSegmentString from './NodedSegmentString.js'\nimport MonotoneChainOverlapAction from '../index/chain/MonotoneChainOverlapAction.js'\nimport MonotoneChainBuilder from '../index/chain/MonotoneChainBuilder.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport SinglePassNoder from './SinglePassNoder.js'\nexport default class MCIndexNoder extends SinglePassNoder {\n constructor() {\n super()\n MCIndexNoder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._monoChains = new ArrayList()\n this._index = new STRtree()\n this._idCounter = 0\n this._nodedSegStrings = null\n this._nOverlaps = 0\n if (arguments.length === 0) {} else if (arguments.length === 1) {\n const si = arguments[0]\n SinglePassNoder.constructor_.call(this, si)\n }\n }\n getMonotoneChains() {\n return this._monoChains\n }\n getNodedSubstrings() {\n return NodedSegmentString.getNodedSubstrings(this._nodedSegStrings)\n }\n getIndex() {\n return this._index\n }\n add(segStr) {\n const segChains = MonotoneChainBuilder.getChains(segStr.getCoordinates(), segStr)\n for (let i = segChains.iterator(); i.hasNext(); ) {\n const mc = i.next()\n mc.setId(this._idCounter++)\n this._index.insert(mc.getEnvelope(), mc)\n this._monoChains.add(mc)\n }\n }\n computeNodes(inputSegStrings) {\n this._nodedSegStrings = inputSegStrings\n for (let i = inputSegStrings.iterator(); i.hasNext(); ) \n this.add(i.next())\n \n this.intersectChains()\n }\n intersectChains() {\n const overlapAction = new SegmentOverlapAction(this._segInt)\n for (let i = this._monoChains.iterator(); i.hasNext(); ) {\n const queryChain = i.next()\n const overlapChains = this._index.query(queryChain.getEnvelope())\n for (let j = overlapChains.iterator(); j.hasNext(); ) {\n const testChain = j.next()\n if (testChain.getId() > queryChain.getId()) {\n queryChain.computeOverlaps(testChain, overlapAction)\n this._nOverlaps++\n }\n if (this._segInt.isDone()) return null\n }\n }\n }\n}\nclass SegmentOverlapAction extends MonotoneChainOverlapAction {\n constructor() {\n super()\n SegmentOverlapAction.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._si = null\n const si = arguments[0]\n this._si = si\n }\n overlap() {\n if (arguments.length === 4) {\n const mc1 = arguments[0], start1 = arguments[1], mc2 = arguments[2], start2 = arguments[3]\n const ss1 = mc1.getContext()\n const ss2 = mc2.getContext()\n this._si.processIntersections(ss1, start1, ss2, start2)\n } else {\n return super.overlap.apply(this, arguments)\n }\n }\n}\nMCIndexNoder.SegmentOverlapAction = SegmentOverlapAction\n","import hasInterface from '../../../../hasInterface.js'\nimport Collection from '../../../../java/util/Collection.js'\nimport Noder from './Noder.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport NodedSegmentString from './NodedSegmentString.js'\nimport System from '../../../../java/lang/System.js'\nimport CoordinateArrays from '../geom/CoordinateArrays.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nexport default class ScaledNoder {\n constructor() {\n ScaledNoder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._noder = null\n this._scaleFactor = null\n this._offsetX = null\n this._offsetY = null\n this._isScaled = false\n if (arguments.length === 2) {\n const noder = arguments[0], scaleFactor = arguments[1]\n ScaledNoder.constructor_.call(this, noder, scaleFactor, 0, 0)\n } else if (arguments.length === 4) {\n const noder = arguments[0], scaleFactor = arguments[1], offsetX = arguments[2], offsetY = arguments[3]\n this._noder = noder\n this._scaleFactor = scaleFactor\n this._isScaled = !this.isIntegerPrecision()\n }\n }\n rescale() {\n if (hasInterface(arguments[0], Collection)) {\n const segStrings = arguments[0]\n for (let i = segStrings.iterator(); i.hasNext(); ) {\n const ss = i.next()\n this.rescale(ss.getCoordinates())\n }\n } else if (arguments[0] instanceof Array) {\n const pts = arguments[0]\n for (let i = 0; i < pts.length; i++) {\n pts[i].x = pts[i].x / this._scaleFactor + this._offsetX\n pts[i].y = pts[i].y / this._scaleFactor + this._offsetY\n }\n if (pts.length === 2 && pts[0].equals2D(pts[1])) \n System.out.println(pts)\n \n }\n }\n scale() {\n if (hasInterface(arguments[0], Collection)) {\n const segStrings = arguments[0]\n const nodedSegmentStrings = new ArrayList(segStrings.size())\n for (let i = segStrings.iterator(); i.hasNext(); ) {\n const ss = i.next()\n nodedSegmentStrings.add(new NodedSegmentString(this.scale(ss.getCoordinates()), ss.getData()))\n }\n return nodedSegmentStrings\n } else if (arguments[0] instanceof Array) {\n const pts = arguments[0]\n const roundPts = new Array(pts.length).fill(null)\n for (let i = 0; i < pts.length; i++) \n roundPts[i] = new Coordinate(Math.round((pts[i].x - this._offsetX) * this._scaleFactor), Math.round((pts[i].y - this._offsetY) * this._scaleFactor), pts[i].getZ())\n \n const roundPtsNoDup = CoordinateArrays.removeRepeatedPoints(roundPts)\n return roundPtsNoDup\n }\n }\n isIntegerPrecision() {\n return this._scaleFactor === 1.0\n }\n getNodedSubstrings() {\n const splitSS = this._noder.getNodedSubstrings()\n if (this._isScaled) this.rescale(splitSS)\n return splitSS\n }\n computeNodes(inputSegStrings) {\n let intSegStrings = inputSegStrings\n if (this._isScaled) intSegStrings = this.scale(inputSegStrings)\n this._noder.computeNodes(intSegStrings)\n }\n get interfaces_() {\n return [Noder]\n }\n}\n","import LineString from '../geom/LineString.js'\nimport BoundaryNodeRule from '../algorithm/BoundaryNodeRule.js'\nimport CoordinateArrays from '../geom/CoordinateArrays.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport TreeMap from '../../../../java/util/TreeMap.js'\nimport MultiLineString from '../geom/MultiLineString.js'\nexport default class BoundaryOp {\n constructor() {\n BoundaryOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geom = null\n this._geomFact = null\n this._bnRule = null\n this._endpointMap = null\n if (arguments.length === 1) {\n const geom = arguments[0]\n BoundaryOp.constructor_.call(this, geom, BoundaryNodeRule.MOD2_BOUNDARY_RULE)\n } else if (arguments.length === 2) {\n const geom = arguments[0], bnRule = arguments[1]\n this._geom = geom\n this._geomFact = geom.getFactory()\n this._bnRule = bnRule\n }\n }\n static getBoundary() {\n if (arguments.length === 1) {\n const g = arguments[0]\n const bop = new BoundaryOp(g)\n return bop.getBoundary()\n } else if (arguments.length === 2) {\n const g = arguments[0], bnRule = arguments[1]\n const bop = new BoundaryOp(g, bnRule)\n return bop.getBoundary()\n }\n }\n boundaryMultiLineString(mLine) {\n if (this._geom.isEmpty()) \n return this.getEmptyMultiPoint()\n \n const bdyPts = this.computeBoundaryCoordinates(mLine)\n if (bdyPts.length === 1) \n return this._geomFact.createPoint(bdyPts[0])\n \n return this._geomFact.createMultiPointFromCoords(bdyPts)\n }\n getBoundary() {\n if (this._geom instanceof LineString) return this.boundaryLineString(this._geom)\n if (this._geom instanceof MultiLineString) return this.boundaryMultiLineString(this._geom)\n return this._geom.getBoundary()\n }\n boundaryLineString(line) {\n if (this._geom.isEmpty()) \n return this.getEmptyMultiPoint()\n \n if (line.isClosed()) {\n const closedEndpointOnBoundary = this._bnRule.isInBoundary(2)\n if (closedEndpointOnBoundary) \n return line.getStartPoint()\n else \n return this._geomFact.createMultiPoint()\n \n }\n return this._geomFact.createMultiPoint([line.getStartPoint(), line.getEndPoint()])\n }\n getEmptyMultiPoint() {\n return this._geomFact.createMultiPoint()\n }\n computeBoundaryCoordinates(mLine) {\n const bdyPts = new ArrayList()\n this._endpointMap = new TreeMap()\n for (let i = 0; i < mLine.getNumGeometries(); i++) {\n const line = mLine.getGeometryN(i)\n if (line.getNumPoints() === 0) continue\n this.addEndpoint(line.getCoordinateN(0))\n this.addEndpoint(line.getCoordinateN(line.getNumPoints() - 1))\n }\n for (let it = this._endpointMap.entrySet().iterator(); it.hasNext(); ) {\n const entry = it.next()\n const counter = entry.getValue()\n const valence = counter.count\n if (this._bnRule.isInBoundary(valence)) \n bdyPts.add(entry.getKey())\n \n }\n return CoordinateArrays.toCoordinateArray(bdyPts)\n }\n addEndpoint(pt) {\n let counter = this._endpointMap.get(pt)\n if (counter === null) {\n counter = new Counter()\n this._endpointMap.put(pt, counter)\n }\n counter.count++\n }\n}\nclass Counter {\n constructor() {\n Counter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.count = null\n }\n}\n","import TreeSet from '../../../../java/util/TreeSet.js'\nimport LineString from '../geom/LineString.js'\nimport hasInterface from '../../../../hasInterface.js'\nimport MultiPoint from '../geom/MultiPoint.js'\nimport GeometryGraph from '../geomgraph/GeometryGraph.js'\nimport GeometryCollection from '../geom/GeometryCollection.js'\nimport Polygonal from '../geom/Polygonal.js'\nimport RobustLineIntersector from '../algorithm/RobustLineIntersector.js'\nimport LinearComponentExtracter from '../geom/util/LinearComponentExtracter.js'\nimport TreeMap from '../../../../java/util/TreeMap.js'\nimport MultiLineString from '../geom/MultiLineString.js'\nexport default class IsSimpleOp {\n constructor() {\n IsSimpleOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputGeom = null\n this._isClosedEndpointsInInterior = true\n this._nonSimpleLocation = null\n if (arguments.length === 1) {\n const geom = arguments[0]\n this._inputGeom = geom\n } else if (arguments.length === 2) {\n const geom = arguments[0], boundaryNodeRule = arguments[1]\n this._inputGeom = geom\n this._isClosedEndpointsInInterior = !boundaryNodeRule.isInBoundary(2)\n }\n }\n static isSimple() {\n if (arguments.length === 1) {\n const geom = arguments[0]\n const op = new IsSimpleOp(geom)\n return op.isSimple()\n } else if (arguments.length === 2) {\n const geom = arguments[0], boundaryNodeRule = arguments[1]\n const op = new IsSimpleOp(geom, boundaryNodeRule)\n return op.isSimple()\n }\n }\n isSimpleMultiPoint(mp) {\n if (mp.isEmpty()) return true\n const points = new TreeSet()\n for (let i = 0; i < mp.getNumGeometries(); i++) {\n const pt = mp.getGeometryN(i)\n const p = pt.getCoordinate()\n if (points.contains(p)) {\n this._nonSimpleLocation = p\n return false\n }\n points.add(p)\n }\n return true\n }\n isSimplePolygonal(geom) {\n const rings = LinearComponentExtracter.getLines(geom)\n for (let i = rings.iterator(); i.hasNext(); ) {\n const ring = i.next()\n if (!this.isSimpleLinearGeometry(ring)) return false\n }\n return true\n }\n hasClosedEndpointIntersection(graph) {\n const endPoints = new TreeMap()\n for (let i = graph.getEdgeIterator(); i.hasNext(); ) {\n const e = i.next()\n const isClosed = e.isClosed()\n const p0 = e.getCoordinate(0)\n this.addEndpoint(endPoints, p0, isClosed)\n const p1 = e.getCoordinate(e.getNumPoints() - 1)\n this.addEndpoint(endPoints, p1, isClosed)\n }\n for (let i = endPoints.values().iterator(); i.hasNext(); ) {\n const eiInfo = i.next()\n if (eiInfo.isClosed && eiInfo.degree !== 2) {\n this._nonSimpleLocation = eiInfo.getCoordinate()\n return true\n }\n }\n return false\n }\n getNonSimpleLocation() {\n return this._nonSimpleLocation\n }\n isSimpleLinearGeometry(geom) {\n if (geom.isEmpty()) return true\n const graph = new GeometryGraph(0, geom)\n const li = new RobustLineIntersector()\n const si = graph.computeSelfNodes(li, true)\n if (!si.hasIntersection()) return true\n if (si.hasProperIntersection()) {\n this._nonSimpleLocation = si.getProperIntersectionPoint()\n return false\n }\n if (this.hasNonEndpointIntersection(graph)) return false\n if (this._isClosedEndpointsInInterior) \n if (this.hasClosedEndpointIntersection(graph)) return false\n \n return true\n }\n hasNonEndpointIntersection(graph) {\n for (let i = graph.getEdgeIterator(); i.hasNext(); ) {\n const e = i.next()\n const maxSegmentIndex = e.getMaximumSegmentIndex()\n for (let eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) {\n const ei = eiIt.next()\n if (!ei.isEndPoint(maxSegmentIndex)) {\n this._nonSimpleLocation = ei.getCoordinate()\n return true\n }\n }\n }\n return false\n }\n addEndpoint(endPoints, p, isClosed) {\n let eiInfo = endPoints.get(p)\n if (eiInfo === null) {\n eiInfo = new EndpointInfo(p)\n endPoints.put(p, eiInfo)\n }\n eiInfo.addEndpoint(isClosed)\n }\n computeSimple(geom) {\n this._nonSimpleLocation = null\n if (geom.isEmpty()) return true\n if (geom instanceof LineString) return this.isSimpleLinearGeometry(geom)\n if (geom instanceof MultiLineString) return this.isSimpleLinearGeometry(geom)\n if (geom instanceof MultiPoint) return this.isSimpleMultiPoint(geom)\n if (hasInterface(geom, Polygonal)) return this.isSimplePolygonal(geom)\n if (geom instanceof GeometryCollection) return this.isSimpleGeometryCollection(geom)\n return true\n }\n isSimple() {\n this._nonSimpleLocation = null\n return this.computeSimple(this._inputGeom)\n }\n isSimpleGeometryCollection(geom) {\n for (let i = 0; i < geom.getNumGeometries(); i++) {\n const comp = geom.getGeometryN(i)\n if (!this.computeSimple(comp)) return false\n }\n return true\n }\n}\nclass EndpointInfo {\n constructor() {\n EndpointInfo.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.pt = null\n this.isClosed = null\n this.degree = null\n const pt = arguments[0]\n this.pt = pt\n this.isClosed = false\n this.degree = 0\n }\n addEndpoint(isClosed) {\n this.degree++\n this.isClosed |= isClosed\n }\n getCoordinate() {\n return this.pt\n }\n}\nIsSimpleOp.EndpointInfo = EndpointInfo\n","export default class BufferParameters {\n constructor() {\n BufferParameters.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS\n this._endCapStyle = BufferParameters.CAP_ROUND\n this._joinStyle = BufferParameters.JOIN_ROUND\n this._mitreLimit = BufferParameters.DEFAULT_MITRE_LIMIT\n this._isSingleSided = false\n this._simplifyFactor = BufferParameters.DEFAULT_SIMPLIFY_FACTOR\n if (arguments.length === 0) {} else if (arguments.length === 1) {\n const quadrantSegments = arguments[0]\n this.setQuadrantSegments(quadrantSegments)\n } else if (arguments.length === 2) {\n const quadrantSegments = arguments[0], endCapStyle = arguments[1]\n this.setQuadrantSegments(quadrantSegments)\n this.setEndCapStyle(endCapStyle)\n } else if (arguments.length === 4) {\n const quadrantSegments = arguments[0], endCapStyle = arguments[1], joinStyle = arguments[2], mitreLimit = arguments[3]\n this.setQuadrantSegments(quadrantSegments)\n this.setEndCapStyle(endCapStyle)\n this.setJoinStyle(joinStyle)\n this.setMitreLimit(mitreLimit)\n }\n }\n static bufferDistanceError(quadSegs) {\n const alpha = Math.PI / 2.0 / quadSegs\n return 1 - Math.cos(alpha / 2.0)\n }\n getEndCapStyle() {\n return this._endCapStyle\n }\n isSingleSided() {\n return this._isSingleSided\n }\n setQuadrantSegments(quadSegs) {\n this._quadrantSegments = quadSegs\n if (this._quadrantSegments === 0) this._joinStyle = BufferParameters.JOIN_BEVEL\n if (this._quadrantSegments < 0) {\n this._joinStyle = BufferParameters.JOIN_MITRE\n this._mitreLimit = Math.abs(this._quadrantSegments)\n }\n if (quadSegs <= 0) \n this._quadrantSegments = 1\n \n if (this._joinStyle !== BufferParameters.JOIN_ROUND) \n this._quadrantSegments = BufferParameters.DEFAULT_QUADRANT_SEGMENTS\n \n }\n getJoinStyle() {\n return this._joinStyle\n }\n setJoinStyle(joinStyle) {\n this._joinStyle = joinStyle\n }\n setSimplifyFactor(simplifyFactor) {\n this._simplifyFactor = simplifyFactor < 0 ? 0 : simplifyFactor\n }\n getSimplifyFactor() {\n return this._simplifyFactor\n }\n getQuadrantSegments() {\n return this._quadrantSegments\n }\n setEndCapStyle(endCapStyle) {\n this._endCapStyle = endCapStyle\n }\n getMitreLimit() {\n return this._mitreLimit\n }\n setMitreLimit(mitreLimit) {\n this._mitreLimit = mitreLimit\n }\n setSingleSided(isSingleSided) {\n this._isSingleSided = isSingleSided\n }\n}\nBufferParameters.CAP_ROUND = 1\nBufferParameters.CAP_FLAT = 2\nBufferParameters.CAP_SQUARE = 3\nBufferParameters.JOIN_ROUND = 1\nBufferParameters.JOIN_MITRE = 2\nBufferParameters.JOIN_BEVEL = 3\nBufferParameters.DEFAULT_QUADRANT_SEGMENTS = 8\nBufferParameters.DEFAULT_MITRE_LIMIT = 5.0\nBufferParameters.DEFAULT_SIMPLIFY_FACTOR = 0.01\n","import Position from '../../geomgraph/Position.js'\nimport Orientation from '../../algorithm/Orientation.js'\nimport Assert from '../../util/Assert.js'\nexport default class RightmostEdgeFinder {\n constructor() {\n RightmostEdgeFinder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._minIndex = -1\n this._minCoord = null\n this._minDe = null\n this._orientedDe = null\n }\n getCoordinate() {\n return this._minCoord\n }\n getRightmostSide(de, index) {\n let side = this.getRightmostSideOfSegment(de, index)\n if (side < 0) side = this.getRightmostSideOfSegment(de, index - 1)\n if (side < 0) {\n this._minCoord = null\n this.checkForRightmostCoordinate(de)\n }\n return side\n }\n findRightmostEdgeAtVertex() {\n const pts = this._minDe.getEdge().getCoordinates()\n Assert.isTrue(this._minIndex > 0 && this._minIndex < pts.length, 'rightmost point expected to be interior vertex of edge')\n const pPrev = pts[this._minIndex - 1]\n const pNext = pts[this._minIndex + 1]\n const orientation = Orientation.index(this._minCoord, pNext, pPrev)\n let usePrev = false\n if (pPrev.y < this._minCoord.y && pNext.y < this._minCoord.y && orientation === Orientation.COUNTERCLOCKWISE) \n usePrev = true\n else if (pPrev.y > this._minCoord.y && pNext.y > this._minCoord.y && orientation === Orientation.CLOCKWISE) \n usePrev = true\n \n if (usePrev) \n this._minIndex = this._minIndex - 1\n \n }\n getRightmostSideOfSegment(de, i) {\n const e = de.getEdge()\n const coord = e.getCoordinates()\n if (i < 0 || i + 1 >= coord.length) return -1\n if (coord[i].y === coord[i + 1].y) return -1\n let pos = Position.LEFT\n if (coord[i].y < coord[i + 1].y) pos = Position.RIGHT\n return pos\n }\n getEdge() {\n return this._orientedDe\n }\n checkForRightmostCoordinate(de) {\n const coord = de.getEdge().getCoordinates()\n for (let i = 0; i < coord.length - 1; i++) \n if (this._minCoord === null || coord[i].x > this._minCoord.x) {\n this._minDe = de\n this._minIndex = i\n this._minCoord = coord[i]\n }\n \n }\n findRightmostEdgeAtNode() {\n const node = this._minDe.getNode()\n const star = node.getEdges()\n this._minDe = star.getRightmostEdge()\n if (!this._minDe.isForward()) {\n this._minDe = this._minDe.getSym()\n this._minIndex = this._minDe.getEdge().getCoordinates().length - 1\n }\n }\n findEdge(dirEdgeList) {\n for (let i = dirEdgeList.iterator(); i.hasNext(); ) {\n const de = i.next()\n if (!de.isForward()) continue\n this.checkForRightmostCoordinate(de)\n }\n Assert.isTrue(this._minIndex !== 0 || this._minCoord.equals(this._minDe.getCoordinate()), 'inconsistency in rightmost processing')\n if (this._minIndex === 0) \n this.findRightmostEdgeAtNode()\n else \n this.findRightmostEdgeAtVertex()\n \n this._orientedDe = this._minDe\n const rightmostSide = this.getRightmostSide(this._minDe, this._minIndex)\n if (rightmostSide === Position.LEFT) \n this._orientedDe = this._minDe.getSym()\n \n }\n}\n","export default class LinkedList {\n constructor() {\n this.array = []\n }\n\n addLast(e) {\n this.array.push(e)\n }\n\n removeFirst() {\n return this.array.shift()\n }\n\n isEmpty() {\n return this.array.length === 0\n }\n}\n","import HashSet from '../../../../../java/util/HashSet.js'\nimport Position from '../../geomgraph/Position.js'\nimport Stack from '../../../../../java/util/Stack.js'\nimport RightmostEdgeFinder from './RightmostEdgeFinder.js'\nimport TopologyException from '../../geom/TopologyException.js'\nimport LinkedList from '../../../../../java/util/LinkedList.js'\nimport Comparable from '../../../../../java/lang/Comparable.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Envelope from '../../geom/Envelope.js'\nexport default class BufferSubgraph {\n constructor() {\n BufferSubgraph.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._finder = null\n this._dirEdgeList = new ArrayList()\n this._nodes = new ArrayList()\n this._rightMostCoord = null\n this._env = null\n this._finder = new RightmostEdgeFinder()\n }\n clearVisitedEdges() {\n for (let it = this._dirEdgeList.iterator(); it.hasNext(); ) {\n const de = it.next()\n de.setVisited(false)\n }\n }\n getRightmostCoordinate() {\n return this._rightMostCoord\n }\n computeNodeDepth(n) {\n let startEdge = null\n for (let i = n.getEdges().iterator(); i.hasNext(); ) {\n const de = i.next()\n if (de.isVisited() || de.getSym().isVisited()) {\n startEdge = de\n break\n }\n }\n if (startEdge === null) throw new TopologyException('unable to find edge to compute depths at ' + n.getCoordinate())\n n.getEdges().computeDepths(startEdge)\n for (let i = n.getEdges().iterator(); i.hasNext(); ) {\n const de = i.next()\n de.setVisited(true)\n this.copySymDepths(de)\n }\n }\n computeDepth(outsideDepth) {\n this.clearVisitedEdges()\n const de = this._finder.getEdge()\n const n = de.getNode()\n const label = de.getLabel()\n de.setEdgeDepths(Position.RIGHT, outsideDepth)\n this.copySymDepths(de)\n this.computeDepths(de)\n }\n create(node) {\n this.addReachable(node)\n this._finder.findEdge(this._dirEdgeList)\n this._rightMostCoord = this._finder.getCoordinate()\n }\n findResultEdges() {\n for (let it = this._dirEdgeList.iterator(); it.hasNext(); ) {\n const de = it.next()\n if (de.getDepth(Position.RIGHT) >= 1 && de.getDepth(Position.LEFT) <= 0 && !de.isInteriorAreaEdge()) \n de.setInResult(true)\n \n }\n }\n computeDepths(startEdge) {\n const nodesVisited = new HashSet()\n const nodeQueue = new LinkedList()\n const startNode = startEdge.getNode()\n nodeQueue.addLast(startNode)\n nodesVisited.add(startNode)\n startEdge.setVisited(true)\n while (!nodeQueue.isEmpty()) {\n const n = nodeQueue.removeFirst()\n nodesVisited.add(n)\n this.computeNodeDepth(n)\n for (let i = n.getEdges().iterator(); i.hasNext(); ) {\n const de = i.next()\n const sym = de.getSym()\n if (sym.isVisited()) continue\n const adjNode = sym.getNode()\n if (!nodesVisited.contains(adjNode)) {\n nodeQueue.addLast(adjNode)\n nodesVisited.add(adjNode)\n }\n }\n }\n }\n compareTo(o) {\n const graph = o\n if (this._rightMostCoord.x < graph._rightMostCoord.x) \n return -1\n \n if (this._rightMostCoord.x > graph._rightMostCoord.x) \n return 1\n \n return 0\n }\n getEnvelope() {\n if (this._env === null) {\n const edgeEnv = new Envelope()\n for (let it = this._dirEdgeList.iterator(); it.hasNext(); ) {\n const dirEdge = it.next()\n const pts = dirEdge.getEdge().getCoordinates()\n for (let i = 0; i < pts.length - 1; i++) \n edgeEnv.expandToInclude(pts[i])\n \n }\n this._env = edgeEnv\n }\n return this._env\n }\n addReachable(startNode) {\n const nodeStack = new Stack()\n nodeStack.add(startNode)\n while (!nodeStack.empty()) {\n const node = nodeStack.pop()\n this.add(node, nodeStack)\n }\n }\n copySymDepths(de) {\n const sym = de.getSym()\n sym.setDepth(Position.LEFT, de.getDepth(Position.RIGHT))\n sym.setDepth(Position.RIGHT, de.getDepth(Position.LEFT))\n }\n add(node, nodeStack) {\n node.setVisited(true)\n this._nodes.add(node)\n for (let i = node.getEdges().iterator(); i.hasNext(); ) {\n const de = i.next()\n this._dirEdgeList.add(de)\n const sym = de.getSym()\n const symNode = sym.getNode()\n if (!symNode.isVisited()) nodeStack.push(symNode)\n }\n }\n getNodes() {\n return this._nodes\n }\n getDirectedEdges() {\n return this._dirEdgeList\n }\n get interfaces_() {\n return [Comparable]\n }\n}\n","import Location from '../geom/Location.js'\nimport Position from './Position.js'\nimport PointLocation from '../algorithm/PointLocation.js'\nimport TopologyException from '../geom/TopologyException.js'\nimport Orientation from '../algorithm/Orientation.js'\nimport Label from './Label.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport Assert from '../util/Assert.js'\nexport default class EdgeRing {\n constructor() {\n EdgeRing.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._startDe = null\n this._maxNodeDegree = -1\n this._edges = new ArrayList()\n this._pts = new ArrayList()\n this._label = new Label(Location.NONE)\n this._ring = null\n this._isHole = null\n this._shell = null\n this._holes = new ArrayList()\n this._geometryFactory = null\n if (arguments.length === 0) {} else if (arguments.length === 2) {\n const start = arguments[0], geometryFactory = arguments[1]\n this._geometryFactory = geometryFactory\n this.computePoints(start)\n this.computeRing()\n }\n }\n computeRing() {\n if (this._ring !== null) return null\n const coord = new Array(this._pts.size()).fill(null)\n for (let i = 0; i < this._pts.size(); i++) \n coord[i] = this._pts.get(i)\n \n this._ring = this._geometryFactory.createLinearRing(coord)\n this._isHole = Orientation.isCCW(this._ring.getCoordinates())\n }\n isIsolated() {\n return this._label.getGeometryCount() === 1\n }\n computePoints(start) {\n this._startDe = start\n let de = start\n let isFirstEdge = true\n do {\n if (de === null) throw new TopologyException('Found null DirectedEdge')\n if (de.getEdgeRing() === this) throw new TopologyException('Directed Edge visited twice during ring-building at ' + de.getCoordinate())\n this._edges.add(de)\n const label = de.getLabel()\n Assert.isTrue(label.isArea())\n this.mergeLabel(label)\n this.addPoints(de.getEdge(), de.isForward(), isFirstEdge)\n isFirstEdge = false\n this.setEdgeRing(de, this)\n de = this.getNext(de)\n } while (de !== this._startDe)\n }\n getLinearRing() {\n return this._ring\n }\n getCoordinate(i) {\n return this._pts.get(i)\n }\n computeMaxNodeDegree() {\n this._maxNodeDegree = 0\n let de = this._startDe\n do {\n const node = de.getNode()\n const degree = node.getEdges().getOutgoingDegree(this)\n if (degree > this._maxNodeDegree) this._maxNodeDegree = degree\n de = this.getNext(de)\n } while (de !== this._startDe)\n this._maxNodeDegree *= 2\n }\n addPoints(edge, isForward, isFirstEdge) {\n const edgePts = edge.getCoordinates()\n if (isForward) {\n let startIndex = 1\n if (isFirstEdge) startIndex = 0\n for (let i = startIndex; i < edgePts.length; i++) \n this._pts.add(edgePts[i])\n \n } else {\n let startIndex = edgePts.length - 2\n if (isFirstEdge) startIndex = edgePts.length - 1\n for (let i = startIndex; i >= 0; i--) \n this._pts.add(edgePts[i])\n \n }\n }\n isHole() {\n return this._isHole\n }\n setInResult() {\n let de = this._startDe\n do {\n de.getEdge().setInResult(true)\n de = de.getNext()\n } while (de !== this._startDe)\n }\n containsPoint(p) {\n const shell = this.getLinearRing()\n const env = shell.getEnvelopeInternal()\n if (!env.contains(p)) return false\n if (!PointLocation.isInRing(p, shell.getCoordinates())) return false\n for (let i = this._holes.iterator(); i.hasNext(); ) {\n const hole = i.next()\n if (hole.containsPoint(p)) return false\n }\n return true\n }\n addHole(ring) {\n this._holes.add(ring)\n }\n isShell() {\n return this._shell === null\n }\n getLabel() {\n return this._label\n }\n getEdges() {\n return this._edges\n }\n getMaxNodeDegree() {\n if (this._maxNodeDegree < 0) this.computeMaxNodeDegree()\n return this._maxNodeDegree\n }\n getShell() {\n return this._shell\n }\n mergeLabel() {\n if (arguments.length === 1) {\n const deLabel = arguments[0]\n this.mergeLabel(deLabel, 0)\n this.mergeLabel(deLabel, 1)\n } else if (arguments.length === 2) {\n const deLabel = arguments[0], geomIndex = arguments[1]\n const loc = deLabel.getLocation(geomIndex, Position.RIGHT)\n if (loc === Location.NONE) return null\n if (this._label.getLocation(geomIndex) === Location.NONE) {\n this._label.setLocation(geomIndex, loc)\n return null\n }\n }\n }\n setShell(shell) {\n this._shell = shell\n if (shell !== null) shell.addHole(this)\n }\n toPolygon(geometryFactory) {\n const holeLR = new Array(this._holes.size()).fill(null)\n for (let i = 0; i < this._holes.size(); i++) \n holeLR[i] = this._holes.get(i).getLinearRing()\n \n const poly = geometryFactory.createPolygon(this.getLinearRing(), holeLR)\n return poly\n }\n}\n","import EdgeRing from '../../geomgraph/EdgeRing.js'\nexport default class MinimalEdgeRing extends EdgeRing {\n constructor() {\n super()\n MinimalEdgeRing.constructor_.apply(this, arguments)\n }\n static constructor_() {\n const start = arguments[0], geometryFactory = arguments[1]\n EdgeRing.constructor_.call(this, start, geometryFactory)\n }\n setEdgeRing(de, er) {\n de.setMinEdgeRing(er)\n }\n getNext(de) {\n return de.getNextMin()\n }\n}\n","import MinimalEdgeRing from './MinimalEdgeRing.js'\nimport EdgeRing from '../../geomgraph/EdgeRing.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nexport default class MaximalEdgeRing extends EdgeRing {\n constructor() {\n super()\n MaximalEdgeRing.constructor_.apply(this, arguments)\n }\n static constructor_() {\n const start = arguments[0], geometryFactory = arguments[1]\n EdgeRing.constructor_.call(this, start, geometryFactory)\n }\n buildMinimalRings() {\n const minEdgeRings = new ArrayList()\n let de = this._startDe\n do {\n if (de.getMinEdgeRing() === null) {\n const minEr = new MinimalEdgeRing(de, this._geometryFactory)\n minEdgeRings.add(minEr)\n }\n de = de.getNext()\n } while (de !== this._startDe)\n return minEdgeRings\n }\n setEdgeRing(de, er) {\n de.setEdgeRing(er)\n }\n linkDirectedEdgesForMinimalEdgeRings() {\n let de = this._startDe\n do {\n const node = de.getNode()\n node.getEdges().linkMinimalDirectedEdges(this)\n de = de.getNext()\n } while (de !== this._startDe)\n }\n getNext(de) {\n return de.getNext()\n }\n}\n","import PointLocation from '../../algorithm/PointLocation.js'\nimport TopologyException from '../../geom/TopologyException.js'\nimport MaximalEdgeRing from './MaximalEdgeRing.js'\nimport CoordinateArrays from '../../geom/CoordinateArrays.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Assert from '../../util/Assert.js'\nimport PlanarGraph from '../../geomgraph/PlanarGraph.js'\nexport default class PolygonBuilder {\n constructor() {\n PolygonBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geometryFactory = null\n this._shellList = new ArrayList()\n const geometryFactory = arguments[0]\n this._geometryFactory = geometryFactory\n }\n static findEdgeRingContaining(testEr, shellList) {\n const testRing = testEr.getLinearRing()\n const testEnv = testRing.getEnvelopeInternal()\n let testPt = testRing.getCoordinateN(0)\n let minShell = null\n let minShellEnv = null\n for (let it = shellList.iterator(); it.hasNext(); ) {\n const tryShell = it.next()\n const tryShellRing = tryShell.getLinearRing()\n const tryShellEnv = tryShellRing.getEnvelopeInternal()\n if (tryShellEnv.equals(testEnv)) continue\n if (!tryShellEnv.contains(testEnv)) continue\n testPt = CoordinateArrays.ptNotInList(testRing.getCoordinates(), tryShellRing.getCoordinates())\n let isContained = false\n if (PointLocation.isInRing(testPt, tryShellRing.getCoordinates())) isContained = true\n if (isContained) \n if (minShell === null || minShellEnv.contains(tryShellEnv)) {\n minShell = tryShell\n minShellEnv = minShell.getLinearRing().getEnvelopeInternal()\n }\n \n }\n return minShell\n }\n sortShellsAndHoles(edgeRings, shellList, freeHoleList) {\n for (let it = edgeRings.iterator(); it.hasNext(); ) {\n const er = it.next()\n if (er.isHole()) \n freeHoleList.add(er)\n else \n shellList.add(er)\n \n }\n }\n computePolygons(shellList) {\n const resultPolyList = new ArrayList()\n for (let it = shellList.iterator(); it.hasNext(); ) {\n const er = it.next()\n const poly = er.toPolygon(this._geometryFactory)\n resultPolyList.add(poly)\n }\n return resultPolyList\n }\n placeFreeHoles(shellList, freeHoleList) {\n for (let it = freeHoleList.iterator(); it.hasNext(); ) {\n const hole = it.next()\n if (hole.getShell() === null) {\n const shell = PolygonBuilder.findEdgeRingContaining(hole, shellList)\n if (shell === null) throw new TopologyException('unable to assign hole to a shell', hole.getCoordinate(0))\n hole.setShell(shell)\n }\n }\n }\n buildMinimalEdgeRings(maxEdgeRings, shellList, freeHoleList) {\n const edgeRings = new ArrayList()\n for (let it = maxEdgeRings.iterator(); it.hasNext(); ) {\n const er = it.next()\n if (er.getMaxNodeDegree() > 2) {\n er.linkDirectedEdgesForMinimalEdgeRings()\n const minEdgeRings = er.buildMinimalRings()\n const shell = this.findShell(minEdgeRings)\n if (shell !== null) {\n this.placePolygonHoles(shell, minEdgeRings)\n shellList.add(shell)\n } else {\n freeHoleList.addAll(minEdgeRings)\n }\n } else {\n edgeRings.add(er)\n }\n }\n return edgeRings\n }\n buildMaximalEdgeRings(dirEdges) {\n const maxEdgeRings = new ArrayList()\n for (let it = dirEdges.iterator(); it.hasNext(); ) {\n const de = it.next()\n if (de.isInResult() && de.getLabel().isArea()) \n if (de.getEdgeRing() === null) {\n const er = new MaximalEdgeRing(de, this._geometryFactory)\n maxEdgeRings.add(er)\n er.setInResult()\n }\n \n }\n return maxEdgeRings\n }\n placePolygonHoles(shell, minEdgeRings) {\n for (let it = minEdgeRings.iterator(); it.hasNext(); ) {\n const er = it.next()\n if (er.isHole()) \n er.setShell(shell)\n \n }\n }\n getPolygons() {\n const resultPolyList = this.computePolygons(this._shellList)\n return resultPolyList\n }\n findShell(minEdgeRings) {\n let shellCount = 0\n let shell = null\n for (let it = minEdgeRings.iterator(); it.hasNext(); ) {\n const er = it.next()\n if (!er.isHole()) {\n shell = er\n shellCount++\n }\n }\n Assert.isTrue(shellCount <= 1, 'found two shells in MinimalEdgeRing list')\n return shell\n }\n add() {\n if (arguments.length === 1) {\n const graph = arguments[0]\n this.add(graph.getEdgeEnds(), graph.getNodes())\n } else if (arguments.length === 2) {\n const dirEdges = arguments[0], nodes = arguments[1]\n PlanarGraph.linkResultDirectedEdges(nodes)\n const maxEdgeRings = this.buildMaximalEdgeRings(dirEdges)\n const freeHoleList = new ArrayList()\n const edgeRings = this.buildMinimalEdgeRings(maxEdgeRings, this._shellList, freeHoleList)\n this.sortShellsAndHoles(edgeRings, this._shellList, freeHoleList)\n this.placeFreeHoles(this._shellList, freeHoleList)\n }\n }\n}\n","import CoordinateList from '../../geom/CoordinateList.js'\nimport Orientation from '../../algorithm/Orientation.js'\nimport Distance from '../../algorithm/Distance.js'\nexport default class BufferInputLineSimplifier {\n constructor() {\n BufferInputLineSimplifier.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputLine = null\n this._distanceTol = null\n this._isDeleted = null\n this._angleOrientation = Orientation.COUNTERCLOCKWISE\n const inputLine = arguments[0]\n this._inputLine = inputLine\n }\n static simplify(inputLine, distanceTol) {\n const simp = new BufferInputLineSimplifier(inputLine)\n return simp.simplify(distanceTol)\n }\n isDeletable(i0, i1, i2, distanceTol) {\n const p0 = this._inputLine[i0]\n const p1 = this._inputLine[i1]\n const p2 = this._inputLine[i2]\n if (!this.isConcave(p0, p1, p2)) return false\n if (!this.isShallow(p0, p1, p2, distanceTol)) return false\n return this.isShallowSampled(p0, p1, i0, i2, distanceTol)\n }\n deleteShallowConcavities() {\n let index = 1\n let midIndex = this.findNextNonDeletedIndex(index)\n let lastIndex = this.findNextNonDeletedIndex(midIndex)\n let isChanged = false\n while (lastIndex < this._inputLine.length) {\n let isMiddleVertexDeleted = false\n if (this.isDeletable(index, midIndex, lastIndex, this._distanceTol)) {\n this._isDeleted[midIndex] = BufferInputLineSimplifier.DELETE\n isMiddleVertexDeleted = true\n isChanged = true\n }\n if (isMiddleVertexDeleted) index = lastIndex; else index = midIndex\n midIndex = this.findNextNonDeletedIndex(index)\n lastIndex = this.findNextNonDeletedIndex(midIndex)\n }\n return isChanged\n }\n isShallowConcavity(p0, p1, p2, distanceTol) {\n const orientation = Orientation.index(p0, p1, p2)\n const isAngleToSimplify = orientation === this._angleOrientation\n if (!isAngleToSimplify) return false\n const dist = Distance.pointToSegment(p1, p0, p2)\n return dist < distanceTol\n }\n isShallowSampled(p0, p2, i0, i2, distanceTol) {\n let inc = Math.trunc((i2 - i0) / BufferInputLineSimplifier.NUM_PTS_TO_CHECK)\n if (inc <= 0) inc = 1\n for (let i = i0; i < i2; i += inc) \n if (!this.isShallow(p0, p2, this._inputLine[i], distanceTol)) return false\n \n return true\n }\n isConcave(p0, p1, p2) {\n const orientation = Orientation.index(p0, p1, p2)\n const isConcave = orientation === this._angleOrientation\n return isConcave\n }\n simplify(distanceTol) {\n this._distanceTol = Math.abs(distanceTol)\n if (distanceTol < 0) this._angleOrientation = Orientation.CLOCKWISE\n this._isDeleted = new Array(this._inputLine.length).fill(null)\n let isChanged = false\n do \n isChanged = this.deleteShallowConcavities()\n while (isChanged)\n return this.collapseLine()\n }\n findNextNonDeletedIndex(index) {\n let next = index + 1\n while (next < this._inputLine.length && this._isDeleted[next] === BufferInputLineSimplifier.DELETE) next++\n return next\n }\n isShallow(p0, p1, p2, distanceTol) {\n const dist = Distance.pointToSegment(p1, p0, p2)\n return dist < distanceTol\n }\n collapseLine() {\n const coordList = new CoordinateList()\n for (let i = 0; i < this._inputLine.length; i++) \n if (this._isDeleted[i] !== BufferInputLineSimplifier.DELETE) coordList.add(this._inputLine[i])\n \n return coordList.toCoordinateArray()\n }\n}\nBufferInputLineSimplifier.INIT = 0\nBufferInputLineSimplifier.DELETE = 1\nBufferInputLineSimplifier.KEEP = 1\nBufferInputLineSimplifier.NUM_PTS_TO_CHECK = 10\n","import GeometryFactory from '../../geom/GeometryFactory.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nexport default class OffsetSegmentString {\n constructor() {\n OffsetSegmentString.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._ptList = null\n this._precisionModel = null\n this._minimimVertexDistance = 0.0\n this._ptList = new ArrayList()\n }\n getCoordinates() {\n const coord = this._ptList.toArray(OffsetSegmentString.COORDINATE_ARRAY_TYPE)\n return coord\n }\n setPrecisionModel(precisionModel) {\n this._precisionModel = precisionModel\n }\n addPt(pt) {\n const bufPt = new Coordinate(pt)\n this._precisionModel.makePrecise(bufPt)\n if (this.isRedundant(bufPt)) return null\n this._ptList.add(bufPt)\n }\n reverse() {}\n addPts(pt, isForward) {\n if (isForward) \n for (let i = 0; i < pt.length; i++) \n this.addPt(pt[i])\n \n else \n for (let i = pt.length - 1; i >= 0; i--) \n this.addPt(pt[i])\n \n \n }\n isRedundant(pt) {\n if (this._ptList.size() < 1) return false\n const lastPt = this._ptList.get(this._ptList.size() - 1)\n const ptDist = pt.distance(lastPt)\n if (ptDist < this._minimimVertexDistance) return true\n return false\n }\n toString() {\n const fact = new GeometryFactory()\n const line = fact.createLineString(this.getCoordinates())\n return line.toString()\n }\n closeRing() {\n if (this._ptList.size() < 1) return null\n const startPt = new Coordinate(this._ptList.get(0))\n const lastPt = this._ptList.get(this._ptList.size() - 1)\n if (startPt.equals(lastPt)) return null\n this._ptList.add(startPt)\n }\n setMinimumVertexDistance(minimimVertexDistance) {\n this._minimimVertexDistance = minimimVertexDistance\n }\n}\nOffsetSegmentString.COORDINATE_ARRAY_TYPE = new Array(0).fill(null)\n","import BufferParameters from './BufferParameters.js'\nimport Position from '../../geomgraph/Position.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport Orientation from '../../algorithm/Orientation.js'\nimport Intersection from '../../algorithm/Intersection.js'\nimport OffsetSegmentString from './OffsetSegmentString.js'\nimport LineSegment from '../../geom/LineSegment.js'\nimport Angle from '../../algorithm/Angle.js'\nimport RobustLineIntersector from '../../algorithm/RobustLineIntersector.js'\nexport default class OffsetSegmentGenerator {\n constructor() {\n OffsetSegmentGenerator.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._maxCurveSegmentError = 0.0\n this._filletAngleQuantum = null\n this._closingSegLengthFactor = 1\n this._segList = null\n this._distance = 0.0\n this._precisionModel = null\n this._bufParams = null\n this._li = null\n this._s0 = null\n this._s1 = null\n this._s2 = null\n this._seg0 = new LineSegment()\n this._seg1 = new LineSegment()\n this._offset0 = new LineSegment()\n this._offset1 = new LineSegment()\n this._side = 0\n this._hasNarrowConcaveAngle = false\n const precisionModel = arguments[0], bufParams = arguments[1], distance = arguments[2]\n this._precisionModel = precisionModel\n this._bufParams = bufParams\n this._li = new RobustLineIntersector()\n this._filletAngleQuantum = Math.PI / 2.0 / bufParams.getQuadrantSegments()\n if (bufParams.getQuadrantSegments() >= 8 && bufParams.getJoinStyle() === BufferParameters.JOIN_ROUND) this._closingSegLengthFactor = OffsetSegmentGenerator.MAX_CLOSING_SEG_LEN_FACTOR\n this.init(distance)\n }\n addNextSegment(p, addStartPoint) {\n this._s0 = this._s1\n this._s1 = this._s2\n this._s2 = p\n this._seg0.setCoordinates(this._s0, this._s1)\n this.computeOffsetSegment(this._seg0, this._side, this._distance, this._offset0)\n this._seg1.setCoordinates(this._s1, this._s2)\n this.computeOffsetSegment(this._seg1, this._side, this._distance, this._offset1)\n if (this._s1.equals(this._s2)) return null\n const orientation = Orientation.index(this._s0, this._s1, this._s2)\n const outsideTurn = orientation === Orientation.CLOCKWISE && this._side === Position.LEFT || orientation === Orientation.COUNTERCLOCKWISE && this._side === Position.RIGHT\n if (orientation === 0) \n this.addCollinear(addStartPoint)\n else if (outsideTurn) \n this.addOutsideTurn(orientation, addStartPoint)\n else \n this.addInsideTurn(orientation, addStartPoint)\n \n }\n addLineEndCap(p0, p1) {\n const seg = new LineSegment(p0, p1)\n const offsetL = new LineSegment()\n this.computeOffsetSegment(seg, Position.LEFT, this._distance, offsetL)\n const offsetR = new LineSegment()\n this.computeOffsetSegment(seg, Position.RIGHT, this._distance, offsetR)\n const dx = p1.x - p0.x\n const dy = p1.y - p0.y\n const angle = Math.atan2(dy, dx)\n switch (this._bufParams.getEndCapStyle()) {\n case BufferParameters.CAP_ROUND:\n this._segList.addPt(offsetL.p1)\n this.addDirectedFillet(p1, angle + Math.PI / 2, angle - Math.PI / 2, Orientation.CLOCKWISE, this._distance)\n this._segList.addPt(offsetR.p1)\n break\n case BufferParameters.CAP_FLAT:\n this._segList.addPt(offsetL.p1)\n this._segList.addPt(offsetR.p1)\n break\n case BufferParameters.CAP_SQUARE:\n const squareCapSideOffset = new Coordinate()\n squareCapSideOffset.x = Math.abs(this._distance) * Math.cos(angle)\n squareCapSideOffset.y = Math.abs(this._distance) * Math.sin(angle)\n const squareCapLOffset = new Coordinate(offsetL.p1.x + squareCapSideOffset.x, offsetL.p1.y + squareCapSideOffset.y)\n const squareCapROffset = new Coordinate(offsetR.p1.x + squareCapSideOffset.x, offsetR.p1.y + squareCapSideOffset.y)\n this._segList.addPt(squareCapLOffset)\n this._segList.addPt(squareCapROffset)\n break\n }\n }\n getCoordinates() {\n const pts = this._segList.getCoordinates()\n return pts\n }\n addMitreJoin(p, offset0, offset1, distance) {\n const intPt = Intersection.intersection(offset0.p0, offset0.p1, offset1.p0, offset1.p1)\n if (intPt !== null) {\n const mitreRatio = distance <= 0.0 ? 1.0 : intPt.distance(p) / Math.abs(distance)\n if (mitreRatio <= this._bufParams.getMitreLimit()) {\n this._segList.addPt(intPt)\n return null\n }\n }\n this.addLimitedMitreJoin(offset0, offset1, distance, this._bufParams.getMitreLimit())\n }\n addOutsideTurn(orientation, addStartPoint) {\n if (this._offset0.p1.distance(this._offset1.p0) < this._distance * OffsetSegmentGenerator.OFFSET_SEGMENT_SEPARATION_FACTOR) {\n this._segList.addPt(this._offset0.p1)\n return null\n }\n if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_MITRE) {\n this.addMitreJoin(this._s1, this._offset0, this._offset1, this._distance)\n } else if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_BEVEL) {\n this.addBevelJoin(this._offset0, this._offset1)\n } else {\n if (addStartPoint) this._segList.addPt(this._offset0.p1)\n this.addCornerFillet(this._s1, this._offset0.p1, this._offset1.p0, orientation, this._distance)\n this._segList.addPt(this._offset1.p0)\n }\n }\n createSquare(p) {\n this._segList.addPt(new Coordinate(p.x + this._distance, p.y + this._distance))\n this._segList.addPt(new Coordinate(p.x + this._distance, p.y - this._distance))\n this._segList.addPt(new Coordinate(p.x - this._distance, p.y - this._distance))\n this._segList.addPt(new Coordinate(p.x - this._distance, p.y + this._distance))\n this._segList.closeRing()\n }\n addSegments(pt, isForward) {\n this._segList.addPts(pt, isForward)\n }\n addFirstSegment() {\n this._segList.addPt(this._offset1.p0)\n }\n addCornerFillet(p, p0, p1, direction, radius) {\n const dx0 = p0.x - p.x\n const dy0 = p0.y - p.y\n let startAngle = Math.atan2(dy0, dx0)\n const dx1 = p1.x - p.x\n const dy1 = p1.y - p.y\n const endAngle = Math.atan2(dy1, dx1)\n if (direction === Orientation.CLOCKWISE) {\n if (startAngle <= endAngle) startAngle += 2.0 * Math.PI\n } else {\n if (startAngle >= endAngle) startAngle -= 2.0 * Math.PI\n }\n this._segList.addPt(p0)\n this.addDirectedFillet(p, startAngle, endAngle, direction, radius)\n this._segList.addPt(p1)\n }\n addLastSegment() {\n this._segList.addPt(this._offset1.p1)\n }\n initSideSegments(s1, s2, side) {\n this._s1 = s1\n this._s2 = s2\n this._side = side\n this._seg1.setCoordinates(s1, s2)\n this.computeOffsetSegment(this._seg1, side, this._distance, this._offset1)\n }\n addLimitedMitreJoin(offset0, offset1, distance, mitreLimit) {\n const basePt = this._seg0.p1\n const ang0 = Angle.angle(basePt, this._seg0.p0)\n const angDiff = Angle.angleBetweenOriented(this._seg0.p0, basePt, this._seg1.p1)\n const angDiffHalf = angDiff / 2\n const midAng = Angle.normalize(ang0 + angDiffHalf)\n const mitreMidAng = Angle.normalize(midAng + Math.PI)\n const mitreDist = mitreLimit * distance\n const bevelDelta = mitreDist * Math.abs(Math.sin(angDiffHalf))\n const bevelHalfLen = distance - bevelDelta\n const bevelMidX = basePt.x + mitreDist * Math.cos(mitreMidAng)\n const bevelMidY = basePt.y + mitreDist * Math.sin(mitreMidAng)\n const bevelMidPt = new Coordinate(bevelMidX, bevelMidY)\n const mitreMidLine = new LineSegment(basePt, bevelMidPt)\n const bevelEndLeft = mitreMidLine.pointAlongOffset(1.0, bevelHalfLen)\n const bevelEndRight = mitreMidLine.pointAlongOffset(1.0, -bevelHalfLen)\n if (this._side === Position.LEFT) {\n this._segList.addPt(bevelEndLeft)\n this._segList.addPt(bevelEndRight)\n } else {\n this._segList.addPt(bevelEndRight)\n this._segList.addPt(bevelEndLeft)\n }\n }\n addDirectedFillet(p, startAngle, endAngle, direction, radius) {\n const directionFactor = direction === Orientation.CLOCKWISE ? -1 : 1\n const totalAngle = Math.abs(startAngle - endAngle)\n const nSegs = Math.trunc(totalAngle / this._filletAngleQuantum + 0.5)\n if (nSegs < 1) return null\n const angleInc = totalAngle / nSegs\n const pt = new Coordinate()\n for (let i = 0; i < nSegs; i++) {\n const angle = startAngle + directionFactor * i * angleInc\n pt.x = p.x + radius * Math.cos(angle)\n pt.y = p.y + radius * Math.sin(angle)\n this._segList.addPt(pt)\n }\n }\n computeOffsetSegment(seg, side, distance, offset) {\n const sideSign = side === Position.LEFT ? 1 : -1\n const dx = seg.p1.x - seg.p0.x\n const dy = seg.p1.y - seg.p0.y\n const len = Math.sqrt(dx * dx + dy * dy)\n const ux = sideSign * distance * dx / len\n const uy = sideSign * distance * dy / len\n offset.p0.x = seg.p0.x - uy\n offset.p0.y = seg.p0.y + ux\n offset.p1.x = seg.p1.x - uy\n offset.p1.y = seg.p1.y + ux\n }\n addInsideTurn(orientation, addStartPoint) {\n this._li.computeIntersection(this._offset0.p0, this._offset0.p1, this._offset1.p0, this._offset1.p1)\n if (this._li.hasIntersection()) {\n this._segList.addPt(this._li.getIntersection(0))\n } else {\n this._hasNarrowConcaveAngle = true\n if (this._offset0.p1.distance(this._offset1.p0) < this._distance * OffsetSegmentGenerator.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR) {\n this._segList.addPt(this._offset0.p1)\n } else {\n this._segList.addPt(this._offset0.p1)\n if (this._closingSegLengthFactor > 0) {\n const mid0 = new Coordinate((this._closingSegLengthFactor * this._offset0.p1.x + this._s1.x) / (this._closingSegLengthFactor + 1), (this._closingSegLengthFactor * this._offset0.p1.y + this._s1.y) / (this._closingSegLengthFactor + 1))\n this._segList.addPt(mid0)\n const mid1 = new Coordinate((this._closingSegLengthFactor * this._offset1.p0.x + this._s1.x) / (this._closingSegLengthFactor + 1), (this._closingSegLengthFactor * this._offset1.p0.y + this._s1.y) / (this._closingSegLengthFactor + 1))\n this._segList.addPt(mid1)\n } else {\n this._segList.addPt(this._s1)\n }\n this._segList.addPt(this._offset1.p0)\n }\n }\n }\n createCircle(p) {\n const pt = new Coordinate(p.x + this._distance, p.y)\n this._segList.addPt(pt)\n this.addDirectedFillet(p, 0.0, 2.0 * Math.PI, -1, this._distance)\n this._segList.closeRing()\n }\n addBevelJoin(offset0, offset1) {\n this._segList.addPt(offset0.p1)\n this._segList.addPt(offset1.p0)\n }\n init(distance) {\n this._distance = distance\n this._maxCurveSegmentError = distance * (1 - Math.cos(this._filletAngleQuantum / 2.0))\n this._segList = new OffsetSegmentString()\n this._segList.setPrecisionModel(this._precisionModel)\n this._segList.setMinimumVertexDistance(distance * OffsetSegmentGenerator.CURVE_VERTEX_SNAP_DISTANCE_FACTOR)\n }\n addCollinear(addStartPoint) {\n this._li.computeIntersection(this._s0, this._s1, this._s1, this._s2)\n const numInt = this._li.getIntersectionNum()\n if (numInt >= 2) \n if (this._bufParams.getJoinStyle() === BufferParameters.JOIN_BEVEL || this._bufParams.getJoinStyle() === BufferParameters.JOIN_MITRE) {\n if (addStartPoint) this._segList.addPt(this._offset0.p1)\n this._segList.addPt(this._offset1.p0)\n } else {\n this.addCornerFillet(this._s1, this._offset0.p1, this._offset1.p0, Orientation.CLOCKWISE, this._distance)\n }\n \n }\n closeRing() {\n this._segList.closeRing()\n }\n hasNarrowConcaveAngle() {\n return this._hasNarrowConcaveAngle\n }\n}\nOffsetSegmentGenerator.OFFSET_SEGMENT_SEPARATION_FACTOR = 1.0E-3\nOffsetSegmentGenerator.INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR = 1.0E-3\nOffsetSegmentGenerator.CURVE_VERTEX_SNAP_DISTANCE_FACTOR = 1.0E-6\nOffsetSegmentGenerator.MAX_CLOSING_SEG_LEN_FACTOR = 80\n","import BufferParameters from './BufferParameters.js'\nimport Position from '../../geomgraph/Position.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport BufferInputLineSimplifier from './BufferInputLineSimplifier.js'\nimport CoordinateArrays from '../../geom/CoordinateArrays.js'\nimport OffsetSegmentGenerator from './OffsetSegmentGenerator.js'\nexport default class OffsetCurveBuilder {\n constructor() {\n OffsetCurveBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._distance = 0.0\n this._precisionModel = null\n this._bufParams = null\n const precisionModel = arguments[0], bufParams = arguments[1]\n this._precisionModel = precisionModel\n this._bufParams = bufParams\n }\n static copyCoordinates(pts) {\n const copy = new Array(pts.length).fill(null)\n for (let i = 0; i < copy.length; i++) \n copy[i] = new Coordinate(pts[i])\n \n return copy\n }\n getOffsetCurve(inputPts, distance) {\n this._distance = distance\n if (distance === 0.0) return null\n const isRightSide = distance < 0.0\n const posDistance = Math.abs(distance)\n const segGen = this.getSegGen(posDistance)\n if (inputPts.length <= 1) \n this.computePointCurve(inputPts[0], segGen)\n else \n this.computeOffsetCurve(inputPts, isRightSide, segGen)\n \n const curvePts = segGen.getCoordinates()\n if (isRightSide) CoordinateArrays.reverse(curvePts)\n return curvePts\n }\n computeSingleSidedBufferCurve(inputPts, isRightSide, segGen) {\n const distTol = this.simplifyTolerance(this._distance)\n if (isRightSide) {\n segGen.addSegments(inputPts, true)\n const simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol)\n const n2 = simp2.length - 1\n segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT)\n segGen.addFirstSegment()\n for (let i = n2 - 2; i >= 0; i--) \n segGen.addNextSegment(simp2[i], true)\n \n } else {\n segGen.addSegments(inputPts, false)\n const simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol)\n const n1 = simp1.length - 1\n segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT)\n segGen.addFirstSegment()\n for (let i = 2; i <= n1; i++) \n segGen.addNextSegment(simp1[i], true)\n \n }\n segGen.addLastSegment()\n segGen.closeRing()\n }\n computeRingBufferCurve(inputPts, side, segGen) {\n let distTol = this.simplifyTolerance(this._distance)\n if (side === Position.RIGHT) distTol = -distTol\n const simp = BufferInputLineSimplifier.simplify(inputPts, distTol)\n const n = simp.length - 1\n segGen.initSideSegments(simp[n - 1], simp[0], side)\n for (let i = 1; i <= n; i++) {\n const addStartPoint = i !== 1\n segGen.addNextSegment(simp[i], addStartPoint)\n }\n segGen.closeRing()\n }\n computeLineBufferCurve(inputPts, segGen) {\n const distTol = this.simplifyTolerance(this._distance)\n const simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol)\n const n1 = simp1.length - 1\n segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT)\n for (let i = 2; i <= n1; i++) \n segGen.addNextSegment(simp1[i], true)\n \n segGen.addLastSegment()\n segGen.addLineEndCap(simp1[n1 - 1], simp1[n1])\n const simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol)\n const n2 = simp2.length - 1\n segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT)\n for (let i = n2 - 2; i >= 0; i--) \n segGen.addNextSegment(simp2[i], true)\n \n segGen.addLastSegment()\n segGen.addLineEndCap(simp2[1], simp2[0])\n segGen.closeRing()\n }\n computePointCurve(pt, segGen) {\n switch (this._bufParams.getEndCapStyle()) {\n case BufferParameters.CAP_ROUND:\n segGen.createCircle(pt)\n break\n case BufferParameters.CAP_SQUARE:\n segGen.createSquare(pt)\n break\n }\n }\n getLineCurve(inputPts, distance) {\n this._distance = distance\n if (this.isLineOffsetEmpty(distance)) return null\n const posDistance = Math.abs(distance)\n const segGen = this.getSegGen(posDistance)\n if (inputPts.length <= 1) {\n this.computePointCurve(inputPts[0], segGen)\n } else \n if (this._bufParams.isSingleSided()) {\n const isRightSide = distance < 0.0\n this.computeSingleSidedBufferCurve(inputPts, isRightSide, segGen)\n } else {\n this.computeLineBufferCurve(inputPts, segGen)\n }\n \n const lineCoord = segGen.getCoordinates()\n return lineCoord\n }\n getBufferParameters() {\n return this._bufParams\n }\n simplifyTolerance(bufDistance) {\n return bufDistance * this._bufParams.getSimplifyFactor()\n }\n getRingCurve(inputPts, side, distance) {\n this._distance = distance\n if (inputPts.length <= 2) return this.getLineCurve(inputPts, distance)\n if (distance === 0.0) \n return OffsetCurveBuilder.copyCoordinates(inputPts)\n \n const segGen = this.getSegGen(distance)\n this.computeRingBufferCurve(inputPts, side, segGen)\n return segGen.getCoordinates()\n }\n computeOffsetCurve(inputPts, isRightSide, segGen) {\n const distTol = this.simplifyTolerance(this._distance)\n if (isRightSide) {\n const simp2 = BufferInputLineSimplifier.simplify(inputPts, -distTol)\n const n2 = simp2.length - 1\n segGen.initSideSegments(simp2[n2], simp2[n2 - 1], Position.LEFT)\n segGen.addFirstSegment()\n for (let i = n2 - 2; i >= 0; i--) \n segGen.addNextSegment(simp2[i], true)\n \n } else {\n const simp1 = BufferInputLineSimplifier.simplify(inputPts, distTol)\n const n1 = simp1.length - 1\n segGen.initSideSegments(simp1[0], simp1[1], Position.LEFT)\n segGen.addFirstSegment()\n for (let i = 2; i <= n1; i++) \n segGen.addNextSegment(simp1[i], true)\n \n }\n segGen.addLastSegment()\n }\n isLineOffsetEmpty(distance) {\n if (distance === 0.0) return true\n if (distance < 0.0 && !this._bufParams.isSingleSided()) return true\n return false\n }\n getSegGen(distance) {\n return new OffsetSegmentGenerator(this._precisionModel, this._bufParams, distance)\n }\n}\n","import hasInterface from '../../../../../hasInterface.js'\nimport Position from '../../geomgraph/Position.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport Orientation from '../../algorithm/Orientation.js'\nimport Collections from '../../../../../java/util/Collections.js'\nimport DirectedEdge from '../../geomgraph/DirectedEdge.js'\nimport LineSegment from '../../geom/LineSegment.js'\nimport Comparable from '../../../../../java/lang/Comparable.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport List from '../../../../../java/util/List.js'\nexport default class SubgraphDepthLocater {\n constructor() {\n SubgraphDepthLocater.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._subgraphs = null\n this._seg = new LineSegment()\n const subgraphs = arguments[0]\n this._subgraphs = subgraphs\n }\n findStabbedSegments() {\n if (arguments.length === 1) {\n const stabbingRayLeftPt = arguments[0]\n const stabbedSegments = new ArrayList()\n for (let i = this._subgraphs.iterator(); i.hasNext(); ) {\n const bsg = i.next()\n const env = bsg.getEnvelope()\n if (stabbingRayLeftPt.y < env.getMinY() || stabbingRayLeftPt.y > env.getMaxY()) continue\n this.findStabbedSegments(stabbingRayLeftPt, bsg.getDirectedEdges(), stabbedSegments)\n }\n return stabbedSegments\n } else if (arguments.length === 3) {\n if (hasInterface(arguments[2], List) && (arguments[0] instanceof Coordinate && arguments[1] instanceof DirectedEdge)) {\n const stabbingRayLeftPt = arguments[0], dirEdge = arguments[1], stabbedSegments = arguments[2]\n const pts = dirEdge.getEdge().getCoordinates()\n for (let i = 0; i < pts.length - 1; i++) {\n this._seg.p0 = pts[i]\n this._seg.p1 = pts[i + 1]\n if (this._seg.p0.y > this._seg.p1.y) this._seg.reverse()\n const maxx = Math.max(this._seg.p0.x, this._seg.p1.x)\n if (maxx < stabbingRayLeftPt.x) continue\n if (this._seg.isHorizontal()) continue\n if (stabbingRayLeftPt.y < this._seg.p0.y || stabbingRayLeftPt.y > this._seg.p1.y) continue\n if (Orientation.index(this._seg.p0, this._seg.p1, stabbingRayLeftPt) === Orientation.RIGHT) continue\n let depth = dirEdge.getDepth(Position.LEFT)\n if (!this._seg.p0.equals(pts[i])) depth = dirEdge.getDepth(Position.RIGHT)\n const ds = new DepthSegment(this._seg, depth)\n stabbedSegments.add(ds)\n }\n } else if (hasInterface(arguments[2], List) && (arguments[0] instanceof Coordinate && hasInterface(arguments[1], List))) {\n const stabbingRayLeftPt = arguments[0], dirEdges = arguments[1], stabbedSegments = arguments[2]\n for (let i = dirEdges.iterator(); i.hasNext(); ) {\n const de = i.next()\n if (!de.isForward()) continue\n this.findStabbedSegments(stabbingRayLeftPt, de, stabbedSegments)\n }\n }\n }\n }\n getDepth(p) {\n const stabbedSegments = this.findStabbedSegments(p)\n if (stabbedSegments.size() === 0) return 0\n const ds = Collections.min(stabbedSegments)\n return ds._leftDepth\n }\n}\nclass DepthSegment {\n constructor() {\n DepthSegment.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._upwardSeg = null\n this._leftDepth = null\n const seg = arguments[0], depth = arguments[1]\n this._upwardSeg = new LineSegment(seg)\n this._leftDepth = depth\n }\n compareTo(obj) {\n const other = obj\n if (this._upwardSeg.minX() >= other._upwardSeg.maxX()) return 1\n if (this._upwardSeg.maxX() <= other._upwardSeg.minX()) return -1\n let orientIndex = this._upwardSeg.orientationIndex(other._upwardSeg)\n if (orientIndex !== 0) return orientIndex\n orientIndex = -1 * other._upwardSeg.orientationIndex(this._upwardSeg)\n if (orientIndex !== 0) return orientIndex\n return this._upwardSeg.compareTo(other._upwardSeg)\n }\n compareX(seg0, seg1) {\n const compare0 = seg0.p0.compareTo(seg1.p0)\n if (compare0 !== 0) return compare0\n return seg0.p1.compareTo(seg1.p1)\n }\n toString() {\n return this._upwardSeg.toString()\n }\n get interfaces_() {\n return [Comparable]\n }\n}\nSubgraphDepthLocater.DepthSegment = DepthSegment\n","import Location from '../../geom/Location.js'\nimport LineString from '../../geom/LineString.js'\nimport Position from '../../geomgraph/Position.js'\nimport Point from '../../geom/Point.js'\nimport NodedSegmentString from '../../noding/NodedSegmentString.js'\nimport Polygon from '../../geom/Polygon.js'\nimport MultiPoint from '../../geom/MultiPoint.js'\nimport LinearRing from '../../geom/LinearRing.js'\nimport Orientation from '../../algorithm/Orientation.js'\nimport MultiPolygon from '../../geom/MultiPolygon.js'\nimport Label from '../../geomgraph/Label.js'\nimport GeometryCollection from '../../geom/GeometryCollection.js'\nimport UnsupportedOperationException from '../../../../../java/lang/UnsupportedOperationException.js'\nimport CoordinateArrays from '../../geom/CoordinateArrays.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Distance from '../../algorithm/Distance.js'\nimport MultiLineString from '../../geom/MultiLineString.js'\nimport Triangle from '../../geom/Triangle.js'\nexport default class OffsetCurveSetBuilder {\n constructor() {\n OffsetCurveSetBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputGeom = null\n this._distance = null\n this._curveBuilder = null\n this._curveList = new ArrayList()\n const inputGeom = arguments[0], distance = arguments[1], curveBuilder = arguments[2]\n this._inputGeom = inputGeom\n this._distance = distance\n this._curveBuilder = curveBuilder\n }\n addRingSide(coord, offsetDistance, side, cwLeftLoc, cwRightLoc) {\n if (offsetDistance === 0.0 && coord.length < LinearRing.MINIMUM_VALID_SIZE) return null\n let leftLoc = cwLeftLoc\n let rightLoc = cwRightLoc\n if (coord.length >= LinearRing.MINIMUM_VALID_SIZE && Orientation.isCCW(coord)) {\n leftLoc = cwRightLoc\n rightLoc = cwLeftLoc\n side = Position.opposite(side)\n }\n const curve = this._curveBuilder.getRingCurve(coord, side, offsetDistance)\n this.addCurve(curve, leftLoc, rightLoc)\n }\n addRingBothSides(coord, distance) {\n this.addRingSide(coord, distance, Position.LEFT, Location.EXTERIOR, Location.INTERIOR)\n this.addRingSide(coord, distance, Position.RIGHT, Location.INTERIOR, Location.EXTERIOR)\n }\n addPoint(p) {\n if (this._distance <= 0.0) return null\n const coord = p.getCoordinates()\n const curve = this._curveBuilder.getLineCurve(coord, this._distance)\n this.addCurve(curve, Location.EXTERIOR, Location.INTERIOR)\n }\n addPolygon(p) {\n let offsetDistance = this._distance\n let offsetSide = Position.LEFT\n if (this._distance < 0.0) {\n offsetDistance = -this._distance\n offsetSide = Position.RIGHT\n }\n const shell = p.getExteriorRing()\n const shellCoord = CoordinateArrays.removeRepeatedPoints(shell.getCoordinates())\n if (this._distance < 0.0 && this.isErodedCompletely(shell, this._distance)) return null\n if (this._distance <= 0.0 && shellCoord.length < 3) return null\n this.addRingSide(shellCoord, offsetDistance, offsetSide, Location.EXTERIOR, Location.INTERIOR)\n for (let i = 0; i < p.getNumInteriorRing(); i++) {\n const hole = p.getInteriorRingN(i)\n const holeCoord = CoordinateArrays.removeRepeatedPoints(hole.getCoordinates())\n if (this._distance > 0.0 && this.isErodedCompletely(hole, -this._distance)) continue\n this.addRingSide(holeCoord, offsetDistance, Position.opposite(offsetSide), Location.INTERIOR, Location.EXTERIOR)\n }\n }\n isTriangleErodedCompletely(triangleCoord, bufferDistance) {\n const tri = new Triangle(triangleCoord[0], triangleCoord[1], triangleCoord[2])\n const inCentre = tri.inCentre()\n const distToCentre = Distance.pointToSegment(inCentre, tri.p0, tri.p1)\n return distToCentre < Math.abs(bufferDistance)\n }\n addLineString(line) {\n if (this._curveBuilder.isLineOffsetEmpty(this._distance)) return null\n const coord = CoordinateArrays.removeRepeatedPoints(line.getCoordinates())\n if (CoordinateArrays.isRing(coord) && !this._curveBuilder.getBufferParameters().isSingleSided()) {\n this.addRingBothSides(coord, this._distance)\n } else {\n const curve = this._curveBuilder.getLineCurve(coord, this._distance)\n this.addCurve(curve, Location.EXTERIOR, Location.INTERIOR)\n }\n }\n addCurve(coord, leftLoc, rightLoc) {\n if (coord === null || coord.length < 2) return null\n const e = new NodedSegmentString(coord, new Label(0, Location.BOUNDARY, leftLoc, rightLoc))\n this._curveList.add(e)\n }\n getCurves() {\n this.add(this._inputGeom)\n return this._curveList\n }\n add(g) {\n if (g.isEmpty()) return null\n if (g instanceof Polygon) this.addPolygon(g); else if (g instanceof LineString) this.addLineString(g); else if (g instanceof Point) this.addPoint(g); else if (g instanceof MultiPoint) this.addCollection(g); else if (g instanceof MultiLineString) this.addCollection(g); else if (g instanceof MultiPolygon) this.addCollection(g); else if (g instanceof GeometryCollection) this.addCollection(g); else throw new UnsupportedOperationException(g.getGeometryType())\n }\n isErodedCompletely(ring, bufferDistance) {\n const ringCoord = ring.getCoordinates()\n if (ringCoord.length < 4) return bufferDistance < 0\n if (ringCoord.length === 4) return this.isTriangleErodedCompletely(ringCoord, bufferDistance)\n const env = ring.getEnvelopeInternal()\n const envMinDimension = Math.min(env.getHeight(), env.getWidth())\n if (bufferDistance < 0.0 && 2 * Math.abs(bufferDistance) > envMinDimension) return true\n return false\n }\n addCollection(gc) {\n for (let i = 0; i < gc.getNumGeometries(); i++) {\n const g = gc.getGeometryN(i)\n this.add(g)\n }\n }\n}\n","import StringBuffer from '../../../../java/lang/StringBuffer.js'\nimport Location from '../geom/Location.js'\nimport Position from './Position.js'\nimport TopologyException from '../geom/TopologyException.js'\nimport System from '../../../../java/lang/System.js'\nimport SimplePointInAreaLocator from '../algorithm/locate/SimplePointInAreaLocator.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport Assert from '../util/Assert.js'\nimport TreeMap from '../../../../java/util/TreeMap.js'\nexport default class EdgeEndStar {\n constructor() {\n EdgeEndStar.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._edgeMap = new TreeMap()\n this._edgeList = null\n this._ptInAreaLocation = [Location.NONE, Location.NONE]\n }\n getNextCW(ee) {\n this.getEdges()\n const i = this._edgeList.indexOf(ee)\n let iNextCW = i - 1\n if (i === 0) iNextCW = this._edgeList.size() - 1\n return this._edgeList.get(iNextCW)\n }\n propagateSideLabels(geomIndex) {\n let startLoc = Location.NONE\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n const label = e.getLabel()\n if (label.isArea(geomIndex) && label.getLocation(geomIndex, Position.LEFT) !== Location.NONE) startLoc = label.getLocation(geomIndex, Position.LEFT)\n }\n if (startLoc === Location.NONE) return null\n let currLoc = startLoc\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n const label = e.getLabel()\n if (label.getLocation(geomIndex, Position.ON) === Location.NONE) label.setLocation(geomIndex, Position.ON, currLoc)\n if (label.isArea(geomIndex)) {\n const leftLoc = label.getLocation(geomIndex, Position.LEFT)\n const rightLoc = label.getLocation(geomIndex, Position.RIGHT)\n if (rightLoc !== Location.NONE) {\n if (rightLoc !== currLoc) throw new TopologyException('side location conflict', e.getCoordinate())\n if (leftLoc === Location.NONE) \n Assert.shouldNeverReachHere('found single null side (at ' + e.getCoordinate() + ')')\n \n currLoc = leftLoc\n } else {\n Assert.isTrue(label.getLocation(geomIndex, Position.LEFT) === Location.NONE, 'found single null side')\n label.setLocation(geomIndex, Position.RIGHT, currLoc)\n label.setLocation(geomIndex, Position.LEFT, currLoc)\n }\n }\n }\n }\n getCoordinate() {\n const it = this.iterator()\n if (!it.hasNext()) return null\n const e = it.next()\n return e.getCoordinate()\n }\n print(out) {\n System.out.println('EdgeEndStar: ' + this.getCoordinate())\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n e.print(out)\n }\n }\n isAreaLabelsConsistent(geomGraph) {\n this.computeEdgeEndLabels(geomGraph.getBoundaryNodeRule())\n return this.checkAreaLabelsConsistent(0)\n }\n checkAreaLabelsConsistent(geomIndex) {\n const edges = this.getEdges()\n if (edges.size() <= 0) return true\n const lastEdgeIndex = edges.size() - 1\n const startLabel = edges.get(lastEdgeIndex).getLabel()\n const startLoc = startLabel.getLocation(geomIndex, Position.LEFT)\n Assert.isTrue(startLoc !== Location.NONE, 'Found unlabelled area edge')\n let currLoc = startLoc\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n const label = e.getLabel()\n Assert.isTrue(label.isArea(geomIndex), 'Found non-area edge')\n const leftLoc = label.getLocation(geomIndex, Position.LEFT)\n const rightLoc = label.getLocation(geomIndex, Position.RIGHT)\n if (leftLoc === rightLoc) \n return false\n \n if (rightLoc !== currLoc) \n return false\n \n currLoc = leftLoc\n }\n return true\n }\n findIndex(eSearch) {\n this.iterator()\n for (let i = 0; i < this._edgeList.size(); i++) {\n const e = this._edgeList.get(i)\n if (e === eSearch) return i\n }\n return -1\n }\n iterator() {\n return this.getEdges().iterator()\n }\n getEdges() {\n if (this._edgeList === null) \n this._edgeList = new ArrayList(this._edgeMap.values())\n \n return this._edgeList\n }\n getLocation(geomIndex, p, geom) {\n if (this._ptInAreaLocation[geomIndex] === Location.NONE) \n this._ptInAreaLocation[geomIndex] = SimplePointInAreaLocator.locate(p, geom[geomIndex].getGeometry())\n \n return this._ptInAreaLocation[geomIndex]\n }\n toString() {\n const buf = new StringBuffer()\n buf.append('EdgeEndStar: ' + this.getCoordinate())\n buf.append('\\n')\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n buf.append(e)\n buf.append('\\n')\n }\n return buf.toString()\n }\n computeEdgeEndLabels(boundaryNodeRule) {\n for (let it = this.iterator(); it.hasNext(); ) {\n const ee = it.next()\n ee.computeLabel(boundaryNodeRule)\n }\n }\n computeLabelling(geomGraph) {\n this.computeEdgeEndLabels(geomGraph[0].getBoundaryNodeRule())\n this.propagateSideLabels(0)\n this.propagateSideLabels(1)\n const hasDimensionalCollapseEdge = [false, false]\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n const label = e.getLabel()\n for (let geomi = 0; geomi < 2; geomi++) \n if (label.isLine(geomi) && label.getLocation(geomi) === Location.BOUNDARY) hasDimensionalCollapseEdge[geomi] = true\n \n }\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n const label = e.getLabel()\n for (let geomi = 0; geomi < 2; geomi++) \n if (label.isAnyNull(geomi)) {\n let loc = Location.NONE\n if (hasDimensionalCollapseEdge[geomi]) {\n loc = Location.EXTERIOR\n } else {\n const p = e.getCoordinate()\n loc = this.getLocation(geomi, p, geomGraph)\n }\n label.setAllLocationsIfNull(geomi, loc)\n }\n \n }\n }\n getDegree() {\n return this._edgeMap.size()\n }\n insertEdgeEnd(e, obj) {\n this._edgeMap.put(e, obj)\n this._edgeList = null\n }\n}\n","import Location from '../geom/Location.js'\nimport Position from './Position.js'\nimport TopologyException from '../geom/TopologyException.js'\nimport EdgeEndStar from './EdgeEndStar.js'\nimport System from '../../../../java/lang/System.js'\nimport Label from './Label.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport Quadrant from './Quadrant.js'\nimport Assert from '../util/Assert.js'\nexport default class DirectedEdgeStar extends EdgeEndStar {\n constructor() {\n super()\n DirectedEdgeStar.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._resultAreaEdgeList = null\n this._label = null\n this._SCANNING_FOR_INCOMING = 1\n this._LINKING_TO_OUTGOING = 2\n }\n linkResultDirectedEdges() {\n this.getResultAreaEdges()\n let firstOut = null\n let incoming = null\n let state = this._SCANNING_FOR_INCOMING\n for (let i = 0; i < this._resultAreaEdgeList.size(); i++) {\n const nextOut = this._resultAreaEdgeList.get(i)\n const nextIn = nextOut.getSym()\n if (!nextOut.getLabel().isArea()) continue\n if (firstOut === null && nextOut.isInResult()) firstOut = nextOut\n switch (state) {\n case this._SCANNING_FOR_INCOMING:\n if (!nextIn.isInResult()) continue\n incoming = nextIn\n state = this._LINKING_TO_OUTGOING\n break\n case this._LINKING_TO_OUTGOING:\n if (!nextOut.isInResult()) continue\n incoming.setNext(nextOut)\n state = this._SCANNING_FOR_INCOMING\n break\n }\n }\n if (state === this._LINKING_TO_OUTGOING) {\n if (firstOut === null) throw new TopologyException('no outgoing dirEdge found', this.getCoordinate())\n Assert.isTrue(firstOut.isInResult(), 'unable to link last incoming dirEdge')\n incoming.setNext(firstOut)\n }\n }\n insert(ee) {\n const de = ee\n this.insertEdgeEnd(de, de)\n }\n getRightmostEdge() {\n const edges = this.getEdges()\n const size = edges.size()\n if (size < 1) return null\n const de0 = edges.get(0)\n if (size === 1) return de0\n const deLast = edges.get(size - 1)\n const quad0 = de0.getQuadrant()\n const quad1 = deLast.getQuadrant()\n if (Quadrant.isNorthern(quad0) && Quadrant.isNorthern(quad1)) {\n return de0\n } else if (!Quadrant.isNorthern(quad0) && !Quadrant.isNorthern(quad1)) {\n return deLast\n } else {\n const nonHorizontalEdge = null\n if (de0.getDy() !== 0) return de0; else if (deLast.getDy() !== 0) return deLast\n }\n Assert.shouldNeverReachHere('found two horizontal edges incident on node')\n return null\n }\n print(out) {\n System.out.println('DirectedEdgeStar: ' + this.getCoordinate())\n for (let it = this.iterator(); it.hasNext(); ) {\n const de = it.next()\n out.print('out ')\n de.print(out)\n out.println()\n out.print('in ')\n de.getSym().print(out)\n out.println()\n }\n }\n getResultAreaEdges() {\n if (this._resultAreaEdgeList !== null) return this._resultAreaEdgeList\n this._resultAreaEdgeList = new ArrayList()\n for (let it = this.iterator(); it.hasNext(); ) {\n const de = it.next()\n if (de.isInResult() || de.getSym().isInResult()) this._resultAreaEdgeList.add(de)\n }\n return this._resultAreaEdgeList\n }\n updateLabelling(nodeLabel) {\n for (let it = this.iterator(); it.hasNext(); ) {\n const de = it.next()\n const label = de.getLabel()\n label.setAllLocationsIfNull(0, nodeLabel.getLocation(0))\n label.setAllLocationsIfNull(1, nodeLabel.getLocation(1))\n }\n }\n linkAllDirectedEdges() {\n this.getEdges()\n let prevOut = null\n let firstIn = null\n for (let i = this._edgeList.size() - 1; i >= 0; i--) {\n const nextOut = this._edgeList.get(i)\n const nextIn = nextOut.getSym()\n if (firstIn === null) firstIn = nextIn\n if (prevOut !== null) nextIn.setNext(prevOut)\n prevOut = nextOut\n }\n firstIn.setNext(prevOut)\n }\n computeDepths() {\n if (arguments.length === 1) {\n const de = arguments[0]\n const edgeIndex = this.findIndex(de)\n const startDepth = de.getDepth(Position.LEFT)\n const targetLastDepth = de.getDepth(Position.RIGHT)\n const nextDepth = this.computeDepths(edgeIndex + 1, this._edgeList.size(), startDepth)\n const lastDepth = this.computeDepths(0, edgeIndex, nextDepth)\n if (lastDepth !== targetLastDepth) throw new TopologyException('depth mismatch at ' + de.getCoordinate())\n } else if (arguments.length === 3) {\n const startIndex = arguments[0], endIndex = arguments[1], startDepth = arguments[2]\n let currDepth = startDepth\n for (let i = startIndex; i < endIndex; i++) {\n const nextDe = this._edgeList.get(i)\n nextDe.setEdgeDepths(Position.RIGHT, currDepth)\n currDepth = nextDe.getDepth(Position.LEFT)\n }\n return currDepth\n }\n }\n mergeSymLabels() {\n for (let it = this.iterator(); it.hasNext(); ) {\n const de = it.next()\n const label = de.getLabel()\n label.merge(de.getSym().getLabel())\n }\n }\n linkMinimalDirectedEdges(er) {\n let firstOut = null\n let incoming = null\n let state = this._SCANNING_FOR_INCOMING\n for (let i = this._resultAreaEdgeList.size() - 1; i >= 0; i--) {\n const nextOut = this._resultAreaEdgeList.get(i)\n const nextIn = nextOut.getSym()\n if (firstOut === null && nextOut.getEdgeRing() === er) firstOut = nextOut\n switch (state) {\n case this._SCANNING_FOR_INCOMING:\n if (nextIn.getEdgeRing() !== er) continue\n incoming = nextIn\n state = this._LINKING_TO_OUTGOING\n break\n case this._LINKING_TO_OUTGOING:\n if (nextOut.getEdgeRing() !== er) continue\n incoming.setNextMin(nextOut)\n state = this._SCANNING_FOR_INCOMING\n break\n }\n }\n if (state === this._LINKING_TO_OUTGOING) {\n Assert.isTrue(firstOut !== null, 'found null for first outgoing dirEdge')\n Assert.isTrue(firstOut.getEdgeRing() === er, 'unable to link last incoming dirEdge')\n incoming.setNextMin(firstOut)\n }\n }\n getOutgoingDegree() {\n if (arguments.length === 0) {\n let degree = 0\n for (let it = this.iterator(); it.hasNext(); ) {\n const de = it.next()\n if (de.isInResult()) degree++\n }\n return degree\n } else if (arguments.length === 1) {\n const er = arguments[0]\n let degree = 0\n for (let it = this.iterator(); it.hasNext(); ) {\n const de = it.next()\n if (de.getEdgeRing() === er) degree++\n }\n return degree\n }\n }\n getLabel() {\n return this._label\n }\n findCoveredLineEdges() {\n let startLoc = Location.NONE\n for (let it = this.iterator(); it.hasNext(); ) {\n const nextOut = it.next()\n const nextIn = nextOut.getSym()\n if (!nextOut.isLineEdge()) {\n if (nextOut.isInResult()) {\n startLoc = Location.INTERIOR\n break\n }\n if (nextIn.isInResult()) {\n startLoc = Location.EXTERIOR\n break\n }\n }\n }\n if (startLoc === Location.NONE) return null\n let currLoc = startLoc\n for (let it = this.iterator(); it.hasNext(); ) {\n const nextOut = it.next()\n const nextIn = nextOut.getSym()\n if (nextOut.isLineEdge()) {\n nextOut.getEdge().setCovered(currLoc === Location.INTERIOR)\n } else {\n if (nextOut.isInResult()) currLoc = Location.EXTERIOR\n if (nextIn.isInResult()) currLoc = Location.INTERIOR\n }\n }\n }\n computeLabelling(geom) {\n super.computeLabelling.call(this, geom)\n this._label = new Label(Location.NONE)\n for (let it = this.iterator(); it.hasNext(); ) {\n const ee = it.next()\n const e = ee.getEdge()\n const eLabel = e.getLabel()\n for (let i = 0; i < 2; i++) {\n const eLoc = eLabel.getLocation(i)\n if (eLoc === Location.INTERIOR || eLoc === Location.BOUNDARY) this._label.setLocation(i, Location.INTERIOR)\n }\n }\n }\n}\n","import DirectedEdgeStar from '../../geomgraph/DirectedEdgeStar.js'\nimport Node from '../../geomgraph/Node.js'\nimport NodeFactory from '../../geomgraph/NodeFactory.js'\nexport default class OverlayNodeFactory extends NodeFactory {\n constructor() {\n super()\n }\n createNode(coord) {\n return new Node(coord, new DirectedEdgeStar())\n }\n}\n","import Comparable from '../../../../java/lang/Comparable.js'\nimport CoordinateArrays from '../geom/CoordinateArrays.js'\nexport default class OrientedCoordinateArray {\n constructor() {\n OrientedCoordinateArray.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pts = null\n this._orientation = null\n const pts = arguments[0]\n this._pts = pts\n this._orientation = OrientedCoordinateArray.orientation(pts)\n }\n static orientation(pts) {\n return CoordinateArrays.increasingDirection(pts) === 1\n }\n static compareOriented(pts1, orientation1, pts2, orientation2) {\n const dir1 = orientation1 ? 1 : -1\n const dir2 = orientation2 ? 1 : -1\n const limit1 = orientation1 ? pts1.length : -1\n const limit2 = orientation2 ? pts2.length : -1\n let i1 = orientation1 ? 0 : pts1.length - 1\n let i2 = orientation2 ? 0 : pts2.length - 1\n while (true) {\n const compPt = pts1[i1].compareTo(pts2[i2])\n if (compPt !== 0) return compPt\n i1 += dir1\n i2 += dir2\n const done1 = i1 === limit1\n const done2 = i2 === limit2\n if (done1 && !done2) return -1\n if (!done1 && done2) return 1\n if (done1 && done2) return 0\n }\n }\n compareTo(o1) {\n const oca = o1\n const comp = OrientedCoordinateArray.compareOriented(this._pts, this._orientation, oca._pts, oca._orientation)\n return comp\n }\n get interfaces_() {\n return [Comparable]\n }\n}\n","import OrientedCoordinateArray from '../noding/OrientedCoordinateArray.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport TreeMap from '../../../../java/util/TreeMap.js'\nexport default class EdgeList {\n constructor() {\n EdgeList.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._edges = new ArrayList()\n this._ocaMap = new TreeMap()\n }\n print(out) {\n out.print('MULTILINESTRING ( ')\n for (let j = 0; j < this._edges.size(); j++) {\n const e = this._edges.get(j)\n if (j > 0) out.print(',')\n out.print('(')\n const pts = e.getCoordinates()\n for (let i = 0; i < pts.length; i++) {\n if (i > 0) out.print(',')\n out.print(pts[i].x + ' ' + pts[i].y)\n }\n out.println(')')\n }\n out.print(') ')\n }\n addAll(edgeColl) {\n for (let i = edgeColl.iterator(); i.hasNext(); ) \n this.add(i.next())\n \n }\n findEdgeIndex(e) {\n for (let i = 0; i < this._edges.size(); i++) \n if (this._edges.get(i).equals(e)) return i\n \n return -1\n }\n iterator() {\n return this._edges.iterator()\n }\n getEdges() {\n return this._edges\n }\n get(i) {\n return this._edges.get(i)\n }\n findEqualEdge(e) {\n const oca = new OrientedCoordinateArray(e.getCoordinates())\n const matchEdge = this._ocaMap.get(oca)\n return matchEdge\n }\n add(e) {\n this._edges.add(e)\n const oca = new OrientedCoordinateArray(e.getCoordinates())\n this._ocaMap.put(oca, e)\n }\n}\n","export default class SegmentIntersector {\n processIntersections(e0, segIndex0, e1, segIndex1) {}\n isDone() {}\n}\n","import SegmentIntersector from './SegmentIntersector.js'\nexport default class IntersectionAdder {\n constructor() {\n IntersectionAdder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._hasIntersection = false\n this._hasProper = false\n this._hasProperInterior = false\n this._hasInterior = false\n this._properIntersectionPoint = null\n this._li = null\n this._isSelfIntersection = null\n this.numIntersections = 0\n this.numInteriorIntersections = 0\n this.numProperIntersections = 0\n this.numTests = 0\n const li = arguments[0]\n this._li = li\n }\n static isAdjacentSegments(i1, i2) {\n return Math.abs(i1 - i2) === 1\n }\n isTrivialIntersection(e0, segIndex0, e1, segIndex1) {\n if (e0 === e1) \n if (this._li.getIntersectionNum() === 1) {\n if (IntersectionAdder.isAdjacentSegments(segIndex0, segIndex1)) return true\n if (e0.isClosed()) {\n const maxSegIndex = e0.size() - 1\n if (segIndex0 === 0 && segIndex1 === maxSegIndex || segIndex1 === 0 && segIndex0 === maxSegIndex) \n return true\n \n }\n }\n \n return false\n }\n getProperIntersectionPoint() {\n return this._properIntersectionPoint\n }\n hasProperInteriorIntersection() {\n return this._hasProperInterior\n }\n getLineIntersector() {\n return this._li\n }\n hasProperIntersection() {\n return this._hasProper\n }\n processIntersections(e0, segIndex0, e1, segIndex1) {\n if (e0 === e1 && segIndex0 === segIndex1) return null\n this.numTests++\n const p00 = e0.getCoordinates()[segIndex0]\n const p01 = e0.getCoordinates()[segIndex0 + 1]\n const p10 = e1.getCoordinates()[segIndex1]\n const p11 = e1.getCoordinates()[segIndex1 + 1]\n this._li.computeIntersection(p00, p01, p10, p11)\n if (this._li.hasIntersection()) {\n this.numIntersections++\n if (this._li.isInteriorIntersection()) {\n this.numInteriorIntersections++\n this._hasInterior = true\n }\n if (!this.isTrivialIntersection(e0, segIndex0, e1, segIndex1)) {\n this._hasIntersection = true\n e0.addIntersections(this._li, segIndex0, 0)\n e1.addIntersections(this._li, segIndex1, 1)\n if (this._li.isProper()) {\n this.numProperIntersections++\n this._hasProper = true\n this._hasProperInterior = true\n }\n }\n }\n }\n hasIntersection() {\n return this._hasIntersection\n }\n isDone() {\n return false\n }\n hasInteriorIntersection() {\n return this._hasInterior\n }\n get interfaces_() {\n return [SegmentIntersector]\n }\n}\n","import Location from '../../geom/Location.js'\nimport BufferSubgraph from './BufferSubgraph.js'\nimport PolygonBuilder from '../overlay/PolygonBuilder.js'\nimport GeometryFactory from '../../geom/GeometryFactory.js'\nimport Position from '../../geomgraph/Position.js'\nimport MCIndexNoder from '../../noding/MCIndexNoder.js'\nimport OffsetCurveBuilder from './OffsetCurveBuilder.js'\nimport Collections from '../../../../../java/util/Collections.js'\nimport SubgraphDepthLocater from './SubgraphDepthLocater.js'\nimport OffsetCurveSetBuilder from './OffsetCurveSetBuilder.js'\nimport Label from '../../geomgraph/Label.js'\nimport OverlayNodeFactory from '../overlay/OverlayNodeFactory.js'\nimport EdgeList from '../../geomgraph/EdgeList.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport RobustLineIntersector from '../../algorithm/RobustLineIntersector.js'\nimport IntersectionAdder from '../../noding/IntersectionAdder.js'\nimport Edge from '../../geomgraph/Edge.js'\nimport PlanarGraph from '../../geomgraph/PlanarGraph.js'\nexport default class BufferBuilder {\n constructor() {\n BufferBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._bufParams = null\n this._workingPrecisionModel = null\n this._workingNoder = null\n this._geomFact = null\n this._graph = null\n this._edgeList = new EdgeList()\n const bufParams = arguments[0]\n this._bufParams = bufParams\n }\n static depthDelta(label) {\n const lLoc = label.getLocation(0, Position.LEFT)\n const rLoc = label.getLocation(0, Position.RIGHT)\n if (lLoc === Location.INTERIOR && rLoc === Location.EXTERIOR) return 1; else if (lLoc === Location.EXTERIOR && rLoc === Location.INTERIOR) return -1\n return 0\n }\n static convertSegStrings(it) {\n const fact = new GeometryFactory()\n const lines = new ArrayList()\n while (it.hasNext()) {\n const ss = it.next()\n const line = fact.createLineString(ss.getCoordinates())\n lines.add(line)\n }\n return fact.buildGeometry(lines)\n }\n setWorkingPrecisionModel(pm) {\n this._workingPrecisionModel = pm\n }\n insertUniqueEdge(e) {\n const existingEdge = this._edgeList.findEqualEdge(e)\n if (existingEdge !== null) {\n const existingLabel = existingEdge.getLabel()\n let labelToMerge = e.getLabel()\n if (!existingEdge.isPointwiseEqual(e)) {\n labelToMerge = new Label(e.getLabel())\n labelToMerge.flip()\n }\n existingLabel.merge(labelToMerge)\n const mergeDelta = BufferBuilder.depthDelta(labelToMerge)\n const existingDelta = existingEdge.getDepthDelta()\n const newDelta = existingDelta + mergeDelta\n existingEdge.setDepthDelta(newDelta)\n } else {\n this._edgeList.add(e)\n e.setDepthDelta(BufferBuilder.depthDelta(e.getLabel()))\n }\n }\n buildSubgraphs(subgraphList, polyBuilder) {\n const processedGraphs = new ArrayList()\n for (let i = subgraphList.iterator(); i.hasNext(); ) {\n const subgraph = i.next()\n const p = subgraph.getRightmostCoordinate()\n const locater = new SubgraphDepthLocater(processedGraphs)\n const outsideDepth = locater.getDepth(p)\n subgraph.computeDepth(outsideDepth)\n subgraph.findResultEdges()\n processedGraphs.add(subgraph)\n polyBuilder.add(subgraph.getDirectedEdges(), subgraph.getNodes())\n }\n }\n createSubgraphs(graph) {\n const subgraphList = new ArrayList()\n for (let i = graph.getNodes().iterator(); i.hasNext(); ) {\n const node = i.next()\n if (!node.isVisited()) {\n const subgraph = new BufferSubgraph()\n subgraph.create(node)\n subgraphList.add(subgraph)\n }\n }\n Collections.sort(subgraphList, Collections.reverseOrder())\n return subgraphList\n }\n createEmptyResultGeometry() {\n const emptyGeom = this._geomFact.createPolygon()\n return emptyGeom\n }\n getNoder(precisionModel) {\n if (this._workingNoder !== null) return this._workingNoder\n const noder = new MCIndexNoder()\n const li = new RobustLineIntersector()\n li.setPrecisionModel(precisionModel)\n noder.setSegmentIntersector(new IntersectionAdder(li))\n return noder\n }\n buffer(g, distance) {\n let precisionModel = this._workingPrecisionModel\n if (precisionModel === null) precisionModel = g.getPrecisionModel()\n this._geomFact = g.getFactory()\n const curveBuilder = new OffsetCurveBuilder(precisionModel, this._bufParams)\n const curveSetBuilder = new OffsetCurveSetBuilder(g, distance, curveBuilder)\n const bufferSegStrList = curveSetBuilder.getCurves()\n if (bufferSegStrList.size() <= 0) \n return this.createEmptyResultGeometry()\n \n this.computeNodedEdges(bufferSegStrList, precisionModel)\n this._graph = new PlanarGraph(new OverlayNodeFactory())\n this._graph.addEdges(this._edgeList.getEdges())\n const subgraphList = this.createSubgraphs(this._graph)\n const polyBuilder = new PolygonBuilder(this._geomFact)\n this.buildSubgraphs(subgraphList, polyBuilder)\n const resultPolyList = polyBuilder.getPolygons()\n if (resultPolyList.size() <= 0) \n return this.createEmptyResultGeometry()\n \n const resultGeom = this._geomFact.buildGeometry(resultPolyList)\n return resultGeom\n }\n computeNodedEdges(bufferSegStrList, precisionModel) {\n const noder = this.getNoder(precisionModel)\n noder.computeNodes(bufferSegStrList)\n const nodedSegStrings = noder.getNodedSubstrings()\n for (let i = nodedSegStrings.iterator(); i.hasNext(); ) {\n const segStr = i.next()\n const pts = segStr.getCoordinates()\n if (pts.length === 2 && pts[0].equals2D(pts[1])) continue\n const oldLabel = segStr.getData()\n const edge = new Edge(segStr.getCoordinates(), new Label(oldLabel))\n this.insertUniqueEdge(edge)\n }\n }\n setNoder(noder) {\n this._workingNoder = noder\n }\n}\n","import GeometryFactory from '../geom/GeometryFactory.js'\nimport RobustLineIntersector from '../algorithm/RobustLineIntersector.js'\nimport RuntimeException from '../../../../java/lang/RuntimeException.js'\nexport default class NodingValidator {\n constructor() {\n NodingValidator.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._li = new RobustLineIntersector()\n this._segStrings = null\n const segStrings = arguments[0]\n this._segStrings = segStrings\n }\n checkEndPtVertexIntersections() {\n if (arguments.length === 0) {\n for (let i = this._segStrings.iterator(); i.hasNext(); ) {\n const ss = i.next()\n const pts = ss.getCoordinates()\n this.checkEndPtVertexIntersections(pts[0], this._segStrings)\n this.checkEndPtVertexIntersections(pts[pts.length - 1], this._segStrings)\n }\n } else if (arguments.length === 2) {\n const testPt = arguments[0], segStrings = arguments[1]\n for (let i = segStrings.iterator(); i.hasNext(); ) {\n const ss = i.next()\n const pts = ss.getCoordinates()\n for (let j = 1; j < pts.length - 1; j++) \n if (pts[j].equals(testPt)) throw new RuntimeException('found endpt/interior pt intersection at index ' + j + ' :pt ' + testPt)\n \n }\n }\n }\n checkInteriorIntersections() {\n if (arguments.length === 0) {\n for (let i = this._segStrings.iterator(); i.hasNext(); ) {\n const ss0 = i.next()\n for (let j = this._segStrings.iterator(); j.hasNext(); ) {\n const ss1 = j.next()\n this.checkInteriorIntersections(ss0, ss1)\n }\n }\n } else if (arguments.length === 2) {\n const ss0 = arguments[0], ss1 = arguments[1]\n const pts0 = ss0.getCoordinates()\n const pts1 = ss1.getCoordinates()\n for (let i0 = 0; i0 < pts0.length - 1; i0++) \n for (let i1 = 0; i1 < pts1.length - 1; i1++) \n this.checkInteriorIntersections(ss0, i0, ss1, i1)\n \n \n } else if (arguments.length === 4) {\n const e0 = arguments[0], segIndex0 = arguments[1], e1 = arguments[2], segIndex1 = arguments[3]\n if (e0 === e1 && segIndex0 === segIndex1) return null\n const p00 = e0.getCoordinates()[segIndex0]\n const p01 = e0.getCoordinates()[segIndex0 + 1]\n const p10 = e1.getCoordinates()[segIndex1]\n const p11 = e1.getCoordinates()[segIndex1 + 1]\n this._li.computeIntersection(p00, p01, p10, p11)\n if (this._li.hasIntersection()) \n if (this._li.isProper() || this.hasInteriorIntersection(this._li, p00, p01) || this.hasInteriorIntersection(this._li, p10, p11)) \n throw new RuntimeException('found non-noded intersection at ' + p00 + '-' + p01 + ' and ' + p10 + '-' + p11)\n \n \n }\n }\n checkValid() {\n this.checkEndPtVertexIntersections()\n this.checkInteriorIntersections()\n this.checkCollapses()\n }\n checkCollapses() {\n if (arguments.length === 0) {\n for (let i = this._segStrings.iterator(); i.hasNext(); ) {\n const ss = i.next()\n this.checkCollapses(ss)\n }\n } else if (arguments.length === 1) {\n const ss = arguments[0]\n const pts = ss.getCoordinates()\n for (let i = 0; i < pts.length - 2; i++) \n this.checkCollapse(pts[i], pts[i + 1], pts[i + 2])\n \n }\n }\n hasInteriorIntersection(li, p0, p1) {\n for (let i = 0; i < li.getIntersectionNum(); i++) {\n const intPt = li.getIntersection(i)\n if (!(intPt.equals(p0) || intPt.equals(p1))) return true\n }\n return false\n }\n checkCollapse(p0, p1, p2) {\n if (p0.equals(p2)) throw new RuntimeException('found non-noded collapse at ' + NodingValidator.fact.createLineString([p0, p1, p2]))\n }\n}\nNodingValidator.fact = new GeometryFactory()\n","import Coordinate from '../../geom/Coordinate.js'\nimport IllegalArgumentException from '../../../../../java/lang/IllegalArgumentException.js'\nimport Envelope from '../../geom/Envelope.js'\nimport Assert from '../../util/Assert.js'\nexport default class HotPixel {\n constructor() {\n HotPixel.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._li = null\n this._pt = null\n this._originalPt = null\n this._ptScaled = null\n this._p0Scaled = null\n this._p1Scaled = null\n this._scaleFactor = null\n this._minx = null\n this._maxx = null\n this._miny = null\n this._maxy = null\n this._corner = new Array(4).fill(null)\n this._safeEnv = null\n const pt = arguments[0], scaleFactor = arguments[1], li = arguments[2]\n this._originalPt = pt\n this._pt = pt\n this._scaleFactor = scaleFactor\n this._li = li\n if (scaleFactor <= 0) throw new IllegalArgumentException('Scale factor must be non-zero')\n if (scaleFactor !== 1.0) {\n this._pt = new Coordinate(this.scale(pt.x), this.scale(pt.y))\n this._p0Scaled = new Coordinate()\n this._p1Scaled = new Coordinate()\n }\n this.initCorners(this._pt)\n }\n intersectsScaled(p0, p1) {\n const segMinx = Math.min(p0.x, p1.x)\n const segMaxx = Math.max(p0.x, p1.x)\n const segMiny = Math.min(p0.y, p1.y)\n const segMaxy = Math.max(p0.y, p1.y)\n const isOutsidePixelEnv = this._maxx < segMinx || this._minx > segMaxx || this._maxy < segMiny || this._miny > segMaxy\n if (isOutsidePixelEnv) return false\n const intersects = this.intersectsToleranceSquare(p0, p1)\n Assert.isTrue(!(isOutsidePixelEnv && intersects), 'Found bad envelope test')\n return intersects\n }\n initCorners(pt) {\n const tolerance = 0.5\n this._minx = pt.x - tolerance\n this._maxx = pt.x + tolerance\n this._miny = pt.y - tolerance\n this._maxy = pt.y + tolerance\n this._corner[0] = new Coordinate(this._maxx, this._maxy)\n this._corner[1] = new Coordinate(this._minx, this._maxy)\n this._corner[2] = new Coordinate(this._minx, this._miny)\n this._corner[3] = new Coordinate(this._maxx, this._miny)\n }\n intersects(p0, p1) {\n if (this._scaleFactor === 1.0) return this.intersectsScaled(p0, p1)\n this.copyScaled(p0, this._p0Scaled)\n this.copyScaled(p1, this._p1Scaled)\n return this.intersectsScaled(this._p0Scaled, this._p1Scaled)\n }\n scale(val) {\n return Math.round(val * this._scaleFactor)\n }\n getCoordinate() {\n return this._originalPt\n }\n copyScaled(p, pScaled) {\n pScaled.x = this.scale(p.x)\n pScaled.y = this.scale(p.y)\n }\n getSafeEnvelope() {\n if (this._safeEnv === null) {\n const safeTolerance = HotPixel.SAFE_ENV_EXPANSION_FACTOR / this._scaleFactor\n this._safeEnv = new Envelope(this._originalPt.x - safeTolerance, this._originalPt.x + safeTolerance, this._originalPt.y - safeTolerance, this._originalPt.y + safeTolerance)\n }\n return this._safeEnv\n }\n intersectsPixelClosure(p0, p1) {\n this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1])\n if (this._li.hasIntersection()) return true\n this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2])\n if (this._li.hasIntersection()) return true\n this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3])\n if (this._li.hasIntersection()) return true\n this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0])\n if (this._li.hasIntersection()) return true\n return false\n }\n intersectsToleranceSquare(p0, p1) {\n let intersectsLeft = false\n let intersectsBottom = false\n this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1])\n if (this._li.isProper()) return true\n this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2])\n if (this._li.isProper()) return true\n if (this._li.hasIntersection()) intersectsLeft = true\n this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3])\n if (this._li.isProper()) return true\n if (this._li.hasIntersection()) intersectsBottom = true\n this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0])\n if (this._li.isProper()) return true\n if (intersectsLeft && intersectsBottom) return true\n if (p0.equals(this._pt)) return true\n if (p1.equals(this._pt)) return true\n return false\n }\n addSnappedNode(segStr, segIndex) {\n const p0 = segStr.getCoordinate(segIndex)\n const p1 = segStr.getCoordinate(segIndex + 1)\n if (this.intersects(p0, p1)) {\n segStr.addIntersection(this.getCoordinate(), segIndex)\n return true\n }\n return false\n }\n}\nHotPixel.SAFE_ENV_EXPANSION_FACTOR = 0.75\n","import LineSegment from '../../geom/LineSegment.js'\nexport default class MonotoneChainSelectAction {\n constructor() {\n MonotoneChainSelectAction.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.selectedSegment = new LineSegment()\n }\n select() {\n if (arguments.length === 1) {\n const seg = arguments[0]\n } else if (arguments.length === 2) {\n const mc = arguments[0], startIndex = arguments[1]\n mc.getLineSegment(startIndex, this.selectedSegment)\n this.select(this.selectedSegment)\n }\n }\n}\n","import MonotoneChainSelectAction from '../../index/chain/MonotoneChainSelectAction.js'\nimport MonotoneChain from '../../index/chain/MonotoneChain.js'\nimport ItemVisitor from '../../index/ItemVisitor.js'\nexport default class MCIndexPointSnapper {\n constructor() {\n MCIndexPointSnapper.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._index = null\n const index = arguments[0]\n this._index = index\n }\n snap() {\n if (arguments.length === 1) {\n const hotPixel = arguments[0]\n return this.snap(hotPixel, null, -1)\n } else if (arguments.length === 3) {\n const hotPixel = arguments[0], parentEdge = arguments[1], hotPixelVertexIndex = arguments[2]\n const pixelEnv = hotPixel.getSafeEnvelope()\n const hotPixelSnapAction = new HotPixelSnapAction(hotPixel, parentEdge, hotPixelVertexIndex)\n this._index.query(pixelEnv, new (class {\n get interfaces_() {\n return [ItemVisitor]\n }\n visitItem(item) {\n const testChain = item\n testChain.select(pixelEnv, hotPixelSnapAction)\n }\n })())\n return hotPixelSnapAction.isNodeAdded()\n }\n }\n}\nclass HotPixelSnapAction extends MonotoneChainSelectAction {\n constructor() {\n super()\n HotPixelSnapAction.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._hotPixel = null\n this._parentEdge = null\n this._hotPixelVertexIndex = null\n this._isNodeAdded = false\n const hotPixel = arguments[0], parentEdge = arguments[1], hotPixelVertexIndex = arguments[2]\n this._hotPixel = hotPixel\n this._parentEdge = parentEdge\n this._hotPixelVertexIndex = hotPixelVertexIndex\n }\n isNodeAdded() {\n return this._isNodeAdded\n }\n select() {\n if (arguments.length === 2 && (Number.isInteger(arguments[1]) && arguments[0] instanceof MonotoneChain)) {\n const mc = arguments[0], startIndex = arguments[1]\n const ss = mc.getContext()\n if (this._parentEdge === ss) \n if (startIndex === this._hotPixelVertexIndex || startIndex + 1 === this._hotPixelVertexIndex) return null\n \n this._isNodeAdded |= this._hotPixel.addSnappedNode(ss, startIndex)\n } else {\n return super.select.apply(this, arguments)\n }\n }\n}\nMCIndexPointSnapper.HotPixelSnapAction = HotPixelSnapAction\n","import SegmentIntersector from './SegmentIntersector.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nexport default class InteriorIntersectionFinderAdder {\n constructor() {\n InteriorIntersectionFinderAdder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._li = null\n this._interiorIntersections = null\n const li = arguments[0]\n this._li = li\n this._interiorIntersections = new ArrayList()\n }\n processIntersections(e0, segIndex0, e1, segIndex1) {\n if (e0 === e1 && segIndex0 === segIndex1) return null\n const p00 = e0.getCoordinates()[segIndex0]\n const p01 = e0.getCoordinates()[segIndex0 + 1]\n const p10 = e1.getCoordinates()[segIndex1]\n const p11 = e1.getCoordinates()[segIndex1 + 1]\n this._li.computeIntersection(p00, p01, p10, p11)\n if (this._li.hasIntersection()) \n if (this._li.isInteriorIntersection()) {\n for (let intIndex = 0; intIndex < this._li.getIntersectionNum(); intIndex++) \n this._interiorIntersections.add(this._li.getIntersection(intIndex))\n \n e0.addIntersections(this._li, segIndex0, 0)\n e1.addIntersections(this._li, segIndex1, 1)\n }\n \n }\n isDone() {\n return false\n }\n getInteriorIntersections() {\n return this._interiorIntersections\n }\n get interfaces_() {\n return [SegmentIntersector]\n }\n}\n","import NodingValidator from '../NodingValidator.js'\nimport hasInterface from '../../../../../hasInterface.js'\nimport Collection from '../../../../../java/util/Collection.js'\nimport Noder from '../Noder.js'\nimport MCIndexNoder from '../MCIndexNoder.js'\nimport NodedSegmentString from '../NodedSegmentString.js'\nimport HotPixel from './HotPixel.js'\nimport Exception from '../../../../../java/lang/Exception.js'\nimport MCIndexPointSnapper from './MCIndexPointSnapper.js'\nimport RobustLineIntersector from '../../algorithm/RobustLineIntersector.js'\nimport InteriorIntersectionFinderAdder from '../InteriorIntersectionFinderAdder.js'\nexport default class MCIndexSnapRounder {\n constructor() {\n MCIndexSnapRounder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pm = null\n this._li = null\n this._scaleFactor = null\n this._noder = null\n this._pointSnapper = null\n this._nodedSegStrings = null\n const pm = arguments[0]\n this._pm = pm\n this._li = new RobustLineIntersector()\n this._li.setPrecisionModel(pm)\n this._scaleFactor = pm.getScale()\n }\n checkCorrectness(inputSegmentStrings) {\n const resultSegStrings = NodedSegmentString.getNodedSubstrings(inputSegmentStrings)\n const nv = new NodingValidator(resultSegStrings)\n try {\n nv.checkValid()\n } catch (ex) {\n if (ex instanceof Exception) \n ex.printStackTrace()\n else throw ex\n } finally {}\n }\n getNodedSubstrings() {\n return NodedSegmentString.getNodedSubstrings(this._nodedSegStrings)\n }\n snapRound(segStrings, li) {\n const intersections = this.findInteriorIntersections(segStrings, li)\n this.computeIntersectionSnaps(intersections)\n this.computeVertexSnaps(segStrings)\n }\n findInteriorIntersections(segStrings, li) {\n const intFinderAdder = new InteriorIntersectionFinderAdder(li)\n this._noder.setSegmentIntersector(intFinderAdder)\n this._noder.computeNodes(segStrings)\n return intFinderAdder.getInteriorIntersections()\n }\n computeVertexSnaps() {\n if (hasInterface(arguments[0], Collection)) {\n const edges = arguments[0]\n for (let i0 = edges.iterator(); i0.hasNext(); ) {\n const edge0 = i0.next()\n this.computeVertexSnaps(edge0)\n }\n } else if (arguments[0] instanceof NodedSegmentString) {\n const e = arguments[0]\n const pts0 = e.getCoordinates()\n for (let i = 0; i < pts0.length; i++) {\n const hotPixel = new HotPixel(pts0[i], this._scaleFactor, this._li)\n const isNodeAdded = this._pointSnapper.snap(hotPixel, e, i)\n if (isNodeAdded) \n e.addIntersection(pts0[i], i)\n \n }\n }\n }\n computeNodes(inputSegmentStrings) {\n this._nodedSegStrings = inputSegmentStrings\n this._noder = new MCIndexNoder()\n this._pointSnapper = new MCIndexPointSnapper(this._noder.getIndex())\n this.snapRound(inputSegmentStrings, this._li)\n }\n computeIntersectionSnaps(snapPts) {\n for (let it = snapPts.iterator(); it.hasNext(); ) {\n const snapPt = it.next()\n const hotPixel = new HotPixel(snapPt, this._scaleFactor, this._li)\n this._pointSnapper.snap(hotPixel)\n }\n }\n get interfaces_() {\n return [Noder]\n }\n}\n","import BufferParameters from './BufferParameters.js'\nimport Geometry from '../../geom/Geometry.js'\nimport BufferBuilder from './BufferBuilder.js'\nimport ScaledNoder from '../../noding/ScaledNoder.js'\nimport TopologyException from '../../geom/TopologyException.js'\nimport MathUtil from '../../math/MathUtil.js'\nimport PrecisionModel from '../../geom/PrecisionModel.js'\nimport RuntimeException from '../../../../../java/lang/RuntimeException.js'\nimport MCIndexSnapRounder from '../../noding/snapround/MCIndexSnapRounder.js'\nexport default class BufferOp {\n constructor() {\n BufferOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._argGeom = null\n this._distance = null\n this._bufParams = new BufferParameters()\n this._resultGeometry = null\n this._saveException = null\n if (arguments.length === 1) {\n const g = arguments[0]\n this._argGeom = g\n } else if (arguments.length === 2) {\n const g = arguments[0], bufParams = arguments[1]\n this._argGeom = g\n this._bufParams = bufParams\n }\n }\n static bufferOp() {\n if (arguments.length === 2) {\n const g = arguments[0], distance = arguments[1]\n const gBuf = new BufferOp(g)\n const geomBuf = gBuf.getResultGeometry(distance)\n return geomBuf\n } else if (arguments.length === 3) {\n if (Number.isInteger(arguments[2]) && (arguments[0] instanceof Geometry && typeof arguments[1] === 'number')) {\n const g = arguments[0], distance = arguments[1], quadrantSegments = arguments[2]\n const bufOp = new BufferOp(g)\n bufOp.setQuadrantSegments(quadrantSegments)\n const geomBuf = bufOp.getResultGeometry(distance)\n return geomBuf\n } else if (arguments[2] instanceof BufferParameters && (arguments[0] instanceof Geometry && typeof arguments[1] === 'number')) {\n const g = arguments[0], distance = arguments[1], params = arguments[2]\n const bufOp = new BufferOp(g, params)\n const geomBuf = bufOp.getResultGeometry(distance)\n return geomBuf\n }\n } else if (arguments.length === 4) {\n const g = arguments[0], distance = arguments[1], quadrantSegments = arguments[2], endCapStyle = arguments[3]\n const bufOp = new BufferOp(g)\n bufOp.setQuadrantSegments(quadrantSegments)\n bufOp.setEndCapStyle(endCapStyle)\n const geomBuf = bufOp.getResultGeometry(distance)\n return geomBuf\n }\n }\n static precisionScaleFactor(g, distance, maxPrecisionDigits) {\n const env = g.getEnvelopeInternal()\n const envMax = MathUtil.max(Math.abs(env.getMaxX()), Math.abs(env.getMaxY()), Math.abs(env.getMinX()), Math.abs(env.getMinY()))\n const expandByDistance = distance > 0.0 ? distance : 0.0\n const bufEnvMax = envMax + 2 * expandByDistance\n const bufEnvPrecisionDigits = Math.trunc(Math.log(bufEnvMax) / Math.log(10) + 1.0)\n const minUnitLog10 = maxPrecisionDigits - bufEnvPrecisionDigits\n const scaleFactor = Math.pow(10.0, minUnitLog10)\n return scaleFactor\n }\n bufferFixedPrecision(fixedPM) {\n const noder = new ScaledNoder(new MCIndexSnapRounder(new PrecisionModel(1.0)), fixedPM.getScale())\n const bufBuilder = new BufferBuilder(this._bufParams)\n bufBuilder.setWorkingPrecisionModel(fixedPM)\n bufBuilder.setNoder(noder)\n this._resultGeometry = bufBuilder.buffer(this._argGeom, this._distance)\n }\n bufferReducedPrecision() {\n if (arguments.length === 0) {\n for (let precDigits = BufferOp.MAX_PRECISION_DIGITS; precDigits >= 0; precDigits--) {\n try {\n this.bufferReducedPrecision(precDigits)\n } catch (ex) {\n if (ex instanceof TopologyException) \n this._saveException = ex\n else throw ex\n } finally {}\n if (this._resultGeometry !== null) return null\n }\n throw this._saveException\n } else if (arguments.length === 1) {\n const precisionDigits = arguments[0]\n const sizeBasedScaleFactor = BufferOp.precisionScaleFactor(this._argGeom, this._distance, precisionDigits)\n const fixedPM = new PrecisionModel(sizeBasedScaleFactor)\n this.bufferFixedPrecision(fixedPM)\n }\n }\n computeGeometry() {\n this.bufferOriginalPrecision()\n if (this._resultGeometry !== null) return null\n const argPM = this._argGeom.getFactory().getPrecisionModel()\n if (argPM.getType() === PrecisionModel.FIXED) this.bufferFixedPrecision(argPM); else this.bufferReducedPrecision()\n }\n setQuadrantSegments(quadrantSegments) {\n this._bufParams.setQuadrantSegments(quadrantSegments)\n }\n bufferOriginalPrecision() {\n try {\n const bufBuilder = new BufferBuilder(this._bufParams)\n this._resultGeometry = bufBuilder.buffer(this._argGeom, this._distance)\n } catch (ex) {\n if (ex instanceof RuntimeException) \n this._saveException = ex\n else throw ex\n } finally {}\n }\n getResultGeometry(distance) {\n this._distance = distance\n this.computeGeometry()\n return this._resultGeometry\n }\n setEndCapStyle(endCapStyle) {\n this._bufParams.setEndCapStyle(endCapStyle)\n }\n}\nBufferOp.CAP_ROUND = BufferParameters.CAP_ROUND\nBufferOp.CAP_BUTT = BufferParameters.CAP_FLAT\nBufferOp.CAP_FLAT = BufferParameters.CAP_FLAT\nBufferOp.CAP_SQUARE = BufferParameters.CAP_SQUARE\nBufferOp.MAX_PRECISION_DIGITS = 12\n","import WKTWriter from '../../io/WKTWriter.js'\nexport default class GeometryLocation {\n constructor() {\n GeometryLocation.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._component = null\n this._segIndex = null\n this._pt = null\n if (arguments.length === 2) {\n const component = arguments[0], pt = arguments[1]\n GeometryLocation.constructor_.call(this, component, GeometryLocation.INSIDE_AREA, pt)\n } else if (arguments.length === 3) {\n const component = arguments[0], segIndex = arguments[1], pt = arguments[2]\n this._component = component\n this._segIndex = segIndex\n this._pt = pt\n }\n }\n getSegmentIndex() {\n return this._segIndex\n }\n getCoordinate() {\n return this._pt\n }\n isInsideArea() {\n return this._segIndex === GeometryLocation.INSIDE_AREA\n }\n toString() {\n return this._component.getGeometryType() + '[' + this._segIndex + ']' + '-' + WKTWriter.toPoint(this._pt)\n }\n getGeometryComponent() {\n return this._component\n }\n}\nGeometryLocation.INSIDE_AREA = -1\n","import LineString from '../../geom/LineString.js'\nimport Point from '../../geom/Point.js'\nimport Polygon from '../../geom/Polygon.js'\nimport GeometryLocation from './GeometryLocation.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport GeometryFilter from '../../geom/GeometryFilter.js'\nexport default class ConnectedElementLocationFilter {\n constructor() {\n ConnectedElementLocationFilter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._locations = null\n const locations = arguments[0]\n this._locations = locations\n }\n static getLocations(geom) {\n const locations = new ArrayList()\n geom.apply(new ConnectedElementLocationFilter(locations))\n return locations\n }\n filter(geom) {\n if (geom.isEmpty()) return null\n if (geom instanceof Point || geom instanceof LineString || geom instanceof Polygon) this._locations.add(new GeometryLocation(geom, 0, geom.getCoordinate()))\n }\n get interfaces_() {\n return [GeometryFilter]\n }\n}\n","import PointLocator from '../../algorithm/PointLocator.js'\nimport PolygonExtracter from '../../geom/util/PolygonExtracter.js'\nimport Location from '../../geom/Location.js'\nimport LineString from '../../geom/LineString.js'\nimport hasInterface from '../../../../../hasInterface.js'\nimport IllegalArgumentException from '../../../../../java/lang/IllegalArgumentException.js'\nimport Point from '../../geom/Point.js'\nimport Polygon from '../../geom/Polygon.js'\nimport GeometryLocation from './GeometryLocation.js'\nimport Double from '../../../../../java/lang/Double.js'\nimport PointExtracter from '../../geom/util/PointExtracter.js'\nimport ConnectedElementLocationFilter from './ConnectedElementLocationFilter.js'\nimport LineSegment from '../../geom/LineSegment.js'\nimport LinearComponentExtracter from '../../geom/util/LinearComponentExtracter.js'\nimport Envelope from '../../geom/Envelope.js'\nimport List from '../../../../../java/util/List.js'\nimport Distance from '../../algorithm/Distance.js'\nexport default class DistanceOp {\n constructor() {\n DistanceOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geom = null\n this._terminateDistance = 0.0\n this._ptLocator = new PointLocator()\n this._minDistanceLocation = null\n this._minDistance = Double.MAX_VALUE\n if (arguments.length === 2) {\n const g0 = arguments[0], g1 = arguments[1]\n DistanceOp.constructor_.call(this, g0, g1, 0.0)\n } else if (arguments.length === 3) {\n const g0 = arguments[0], g1 = arguments[1], terminateDistance = arguments[2]\n this._geom = new Array(2).fill(null)\n this._geom[0] = g0\n this._geom[1] = g1\n this._terminateDistance = terminateDistance\n }\n }\n static distance(g0, g1) {\n const distOp = new DistanceOp(g0, g1)\n return distOp.distance()\n }\n static isWithinDistance(g0, g1, distance) {\n const envDist = g0.getEnvelopeInternal().distance(g1.getEnvelopeInternal())\n if (envDist > distance) return false\n const distOp = new DistanceOp(g0, g1, distance)\n return distOp.distance() <= distance\n }\n static nearestPoints(g0, g1) {\n const distOp = new DistanceOp(g0, g1)\n return distOp.nearestPoints()\n }\n computeContainmentDistance() {\n if (arguments.length === 0) {\n const locPtPoly = new Array(2).fill(null)\n this.computeContainmentDistance(0, locPtPoly)\n if (this._minDistance <= this._terminateDistance) return null\n this.computeContainmentDistance(1, locPtPoly)\n } else if (arguments.length === 2) {\n const polyGeomIndex = arguments[0], locPtPoly = arguments[1]\n const polyGeom = this._geom[polyGeomIndex]\n if (polyGeom.getDimension() < 2) return null\n const locationsIndex = 1 - polyGeomIndex\n const polys = PolygonExtracter.getPolygons(polyGeom)\n if (polys.size() > 0) {\n const insideLocs = ConnectedElementLocationFilter.getLocations(this._geom[locationsIndex])\n this.computeContainmentDistance(insideLocs, polys, locPtPoly)\n if (this._minDistance <= this._terminateDistance) {\n this._minDistanceLocation[locationsIndex] = locPtPoly[0]\n this._minDistanceLocation[polyGeomIndex] = locPtPoly[1]\n return null\n }\n }\n } else if (arguments.length === 3) {\n if (arguments[2] instanceof Array && (hasInterface(arguments[0], List) && hasInterface(arguments[1], List))) {\n const locs = arguments[0], polys = arguments[1], locPtPoly = arguments[2]\n for (let i = 0; i < locs.size(); i++) {\n const loc = locs.get(i)\n for (let j = 0; j < polys.size(); j++) {\n this.computeContainmentDistance(loc, polys.get(j), locPtPoly)\n if (this._minDistance <= this._terminateDistance) return null\n }\n }\n } else if (arguments[2] instanceof Array && (arguments[0] instanceof GeometryLocation && arguments[1] instanceof Polygon)) {\n const ptLoc = arguments[0], poly = arguments[1], locPtPoly = arguments[2]\n const pt = ptLoc.getCoordinate()\n if (Location.EXTERIOR !== this._ptLocator.locate(pt, poly)) {\n this._minDistance = 0.0\n locPtPoly[0] = ptLoc\n locPtPoly[1] = new GeometryLocation(poly, pt)\n \n return null\n }\n }\n }\n }\n computeMinDistanceLinesPoints(lines, points, locGeom) {\n for (let i = 0; i < lines.size(); i++) {\n const line = lines.get(i)\n for (let j = 0; j < points.size(); j++) {\n const pt = points.get(j)\n this.computeMinDistance(line, pt, locGeom)\n if (this._minDistance <= this._terminateDistance) return null\n }\n }\n }\n computeFacetDistance() {\n const locGeom = new Array(2).fill(null)\n const lines0 = LinearComponentExtracter.getLines(this._geom[0])\n const lines1 = LinearComponentExtracter.getLines(this._geom[1])\n const pts0 = PointExtracter.getPoints(this._geom[0])\n const pts1 = PointExtracter.getPoints(this._geom[1])\n this.computeMinDistanceLines(lines0, lines1, locGeom)\n this.updateMinDistance(locGeom, false)\n if (this._minDistance <= this._terminateDistance) return null\n locGeom[0] = null\n locGeom[1] = null\n this.computeMinDistanceLinesPoints(lines0, pts1, locGeom)\n this.updateMinDistance(locGeom, false)\n if (this._minDistance <= this._terminateDistance) return null\n locGeom[0] = null\n locGeom[1] = null\n this.computeMinDistanceLinesPoints(lines1, pts0, locGeom)\n this.updateMinDistance(locGeom, true)\n if (this._minDistance <= this._terminateDistance) return null\n locGeom[0] = null\n locGeom[1] = null\n this.computeMinDistancePoints(pts0, pts1, locGeom)\n this.updateMinDistance(locGeom, false)\n }\n nearestLocations() {\n this.computeMinDistance()\n return this._minDistanceLocation\n }\n updateMinDistance(locGeom, flip) {\n if (locGeom[0] === null) return null\n if (flip) {\n this._minDistanceLocation[0] = locGeom[1]\n this._minDistanceLocation[1] = locGeom[0]\n } else {\n this._minDistanceLocation[0] = locGeom[0]\n this._minDistanceLocation[1] = locGeom[1]\n }\n }\n nearestPoints() {\n this.computeMinDistance()\n const nearestPts = [this._minDistanceLocation[0].getCoordinate(), this._minDistanceLocation[1].getCoordinate()]\n return nearestPts\n }\n computeMinDistance() {\n if (arguments.length === 0) {\n if (this._minDistanceLocation !== null) return null\n this._minDistanceLocation = new Array(2).fill(null)\n this.computeContainmentDistance()\n if (this._minDistance <= this._terminateDistance) return null\n this.computeFacetDistance()\n } else if (arguments.length === 3) {\n if (arguments[2] instanceof Array && (arguments[0] instanceof LineString && arguments[1] instanceof Point)) {\n const line = arguments[0], pt = arguments[1], locGeom = arguments[2]\n if (line.getEnvelopeInternal().distance(pt.getEnvelopeInternal()) > this._minDistance) return null\n const coord0 = line.getCoordinates()\n const coord = pt.getCoordinate()\n for (let i = 0; i < coord0.length - 1; i++) {\n const dist = Distance.pointToSegment(coord, coord0[i], coord0[i + 1])\n if (dist < this._minDistance) {\n this._minDistance = dist\n const seg = new LineSegment(coord0[i], coord0[i + 1])\n const segClosestPoint = seg.closestPoint(coord)\n locGeom[0] = new GeometryLocation(line, i, segClosestPoint)\n locGeom[1] = new GeometryLocation(pt, 0, coord)\n }\n if (this._minDistance <= this._terminateDistance) return null\n }\n } else if (arguments[2] instanceof Array && (arguments[0] instanceof LineString && arguments[1] instanceof LineString)) {\n const line0 = arguments[0], line1 = arguments[1], locGeom = arguments[2]\n if (line0.getEnvelopeInternal().distance(line1.getEnvelopeInternal()) > this._minDistance) return null\n const coord0 = line0.getCoordinates()\n const coord1 = line1.getCoordinates()\n for (let i = 0; i < coord0.length - 1; i++) {\n const segEnv0 = new Envelope(coord0[i], coord0[i + 1])\n if (segEnv0.distance(line1.getEnvelopeInternal()) > this._minDistance) continue\n for (let j = 0; j < coord1.length - 1; j++) {\n const segEnv1 = new Envelope(coord1[j], coord1[j + 1])\n if (segEnv0.distance(segEnv1) > this._minDistance) continue\n const dist = Distance.segmentToSegment(coord0[i], coord0[i + 1], coord1[j], coord1[j + 1])\n if (dist < this._minDistance) {\n this._minDistance = dist\n const seg0 = new LineSegment(coord0[i], coord0[i + 1])\n const seg1 = new LineSegment(coord1[j], coord1[j + 1])\n const closestPt = seg0.closestPoints(seg1)\n locGeom[0] = new GeometryLocation(line0, i, closestPt[0])\n locGeom[1] = new GeometryLocation(line1, j, closestPt[1])\n }\n if (this._minDistance <= this._terminateDistance) return null\n }\n }\n }\n }\n }\n computeMinDistancePoints(points0, points1, locGeom) {\n for (let i = 0; i < points0.size(); i++) {\n const pt0 = points0.get(i)\n for (let j = 0; j < points1.size(); j++) {\n const pt1 = points1.get(j)\n const dist = pt0.getCoordinate().distance(pt1.getCoordinate())\n if (dist < this._minDistance) {\n this._minDistance = dist\n locGeom[0] = new GeometryLocation(pt0, 0, pt0.getCoordinate())\n locGeom[1] = new GeometryLocation(pt1, 0, pt1.getCoordinate())\n }\n if (this._minDistance <= this._terminateDistance) return null\n }\n }\n }\n distance() {\n if (this._geom[0] === null || this._geom[1] === null) throw new IllegalArgumentException('null geometries are not supported')\n if (this._geom[0].isEmpty() || this._geom[1].isEmpty()) return 0.0\n this.computeMinDistance()\n return this._minDistance\n }\n computeMinDistanceLines(lines0, lines1, locGeom) {\n for (let i = 0; i < lines0.size(); i++) {\n const line0 = lines0.get(i)\n for (let j = 0; j < lines1.size(); j++) {\n const line1 = lines1.get(j)\n this.computeMinDistance(line0, line1, locGeom)\n if (this._minDistance <= this._terminateDistance) return null\n }\n }\n }\n}\n","import CoordinateList from '../../geom/CoordinateList.js'\nimport CoordinateArrays from '../../geom/CoordinateArrays.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nexport default class EdgeString {\n constructor() {\n EdgeString.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._factory = null\n this._directedEdges = new ArrayList()\n this._coordinates = null\n const factory = arguments[0]\n this._factory = factory\n }\n getCoordinates() {\n if (this._coordinates === null) {\n let forwardDirectedEdges = 0\n let reverseDirectedEdges = 0\n const coordinateList = new CoordinateList()\n for (let i = this._directedEdges.iterator(); i.hasNext(); ) {\n const directedEdge = i.next()\n if (directedEdge.getEdgeDirection()) \n forwardDirectedEdges++\n else \n reverseDirectedEdges++\n \n coordinateList.add(directedEdge.getEdge().getLine().getCoordinates(), false, directedEdge.getEdgeDirection())\n }\n this._coordinates = coordinateList.toCoordinateArray()\n if (reverseDirectedEdges > forwardDirectedEdges) \n CoordinateArrays.reverse(this._coordinates)\n \n }\n return this._coordinates\n }\n toLineString() {\n return this._factory.createLineString(this.getCoordinates())\n }\n add(directedEdge) {\n this._directedEdges.add(directedEdge)\n }\n}\n","export default class GraphComponent {\n constructor() {\n GraphComponent.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._isMarked = false\n this._isVisited = false\n this._data = null\n }\n static getComponentWithVisitedState(i, visitedState) {\n while (i.hasNext()) {\n const comp = i.next()\n if (comp.isVisited() === visitedState) return comp\n }\n return null\n }\n static setVisited(i, visited) {\n while (i.hasNext()) {\n const comp = i.next()\n comp.setVisited(visited)\n }\n }\n static setMarked(i, marked) {\n while (i.hasNext()) {\n const comp = i.next()\n comp.setMarked(marked)\n }\n }\n setVisited(isVisited) {\n this._isVisited = isVisited\n }\n isMarked() {\n return this._isMarked\n }\n setData(data) {\n this._data = data\n }\n getData() {\n return this._data\n }\n setMarked(isMarked) {\n this._isMarked = isMarked\n }\n getContext() {\n return this._data\n }\n isVisited() {\n return this._isVisited\n }\n setContext(data) {\n this._data = data\n }\n}\n","import Orientation from '../algorithm/Orientation.js'\nimport Comparable from '../../../../java/lang/Comparable.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport Quadrant from '../geomgraph/Quadrant.js'\nimport GraphComponent from './GraphComponent.js'\nexport default class DirectedEdge extends GraphComponent {\n constructor() {\n super()\n DirectedEdge.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._parentEdge = null\n this._from = null\n this._to = null\n this._p0 = null\n this._p1 = null\n this._sym = null\n this._edgeDirection = null\n this._quadrant = null\n this._angle = null\n if (arguments.length === 0) {} else if (arguments.length === 4) {\n const from = arguments[0], to = arguments[1], directionPt = arguments[2], edgeDirection = arguments[3]\n this._from = from\n this._to = to\n this._edgeDirection = edgeDirection\n this._p0 = from.getCoordinate()\n this._p1 = directionPt\n const dx = this._p1.x - this._p0.x\n const dy = this._p1.y - this._p0.y\n this._quadrant = Quadrant.quadrant(dx, dy)\n this._angle = Math.atan2(dy, dx)\n }\n }\n static toEdges(dirEdges) {\n const edges = new ArrayList()\n for (let i = dirEdges.iterator(); i.hasNext(); ) \n edges.add(i.next()._parentEdge)\n \n return edges\n }\n isRemoved() {\n return this._parentEdge === null\n }\n compareDirection(e) {\n if (this._quadrant > e._quadrant) return 1\n if (this._quadrant < e._quadrant) return -1\n return Orientation.index(e._p0, e._p1, this._p1)\n }\n getCoordinate() {\n return this._from.getCoordinate()\n }\n print(out) {\n const className = this.getClass().getName()\n const lastDotPos = className.lastIndexOf('.')\n const name = className.substring(lastDotPos + 1)\n out.print(' ' + name + ': ' + this._p0 + ' - ' + this._p1 + ' ' + this._quadrant + ':' + this._angle)\n }\n getDirectionPt() {\n return this._p1\n }\n getAngle() {\n return this._angle\n }\n compareTo(obj) {\n const de = obj\n return this.compareDirection(de)\n }\n getFromNode() {\n return this._from\n }\n getSym() {\n return this._sym\n }\n setEdge(parentEdge) {\n this._parentEdge = parentEdge\n }\n remove() {\n this._sym = null\n this._parentEdge = null\n }\n getEdge() {\n return this._parentEdge\n }\n getQuadrant() {\n return this._quadrant\n }\n setSym(sym) {\n this._sym = sym\n }\n getToNode() {\n return this._to\n }\n getEdgeDirection() {\n return this._edgeDirection\n }\n get interfaces_() {\n return [Comparable]\n }\n}\n","import DirectedEdge from '../../planargraph/DirectedEdge.js'\nimport Assert from '../../util/Assert.js'\nexport default class LineMergeDirectedEdge extends DirectedEdge {\n constructor() {\n super()\n LineMergeDirectedEdge.constructor_.apply(this, arguments)\n }\n static constructor_() {\n const from = arguments[0], to = arguments[1], directionPt = arguments[2], edgeDirection = arguments[3]\n DirectedEdge.constructor_.call(this, from, to, directionPt, edgeDirection)\n }\n getNext() {\n if (this.getToNode().getDegree() !== 2) \n return null\n \n if (this.getToNode().getOutEdges().getEdges().get(0) === this.getSym()) \n return this.getToNode().getOutEdges().getEdges().get(1)\n \n Assert.isTrue(this.getToNode().getOutEdges().getEdges().get(1) === this.getSym())\n return this.getToNode().getOutEdges().getEdges().get(0)\n }\n}\n","import Node from './Node.js'\nimport GraphComponent from './GraphComponent.js'\nexport default class Edge extends GraphComponent {\n constructor() {\n super()\n Edge.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._dirEdge = null\n if (arguments.length === 0) {} else if (arguments.length === 2) {\n const de0 = arguments[0], de1 = arguments[1]\n this.setDirectedEdges(de0, de1)\n }\n }\n isRemoved() {\n return this._dirEdge === null\n }\n setDirectedEdges(de0, de1) {\n this._dirEdge = [de0, de1]\n de0.setEdge(this)\n de1.setEdge(this)\n de0.setSym(de1)\n de1.setSym(de0)\n de0.getFromNode().addOutEdge(de0)\n de1.getFromNode().addOutEdge(de1)\n }\n getDirEdge() {\n if (Number.isInteger(arguments[0])) {\n const i = arguments[0]\n return this._dirEdge[i]\n } else if (arguments[0] instanceof Node) {\n const fromNode = arguments[0]\n if (this._dirEdge[0].getFromNode() === fromNode) return this._dirEdge[0]\n if (this._dirEdge[1].getFromNode() === fromNode) return this._dirEdge[1]\n return null\n }\n }\n remove() {\n this._dirEdge = null\n }\n getOppositeNode(node) {\n if (this._dirEdge[0].getFromNode() === node) return this._dirEdge[0].getToNode()\n if (this._dirEdge[1].getFromNode() === node) return this._dirEdge[1].getToNode()\n return null\n }\n}\n","import Collections from '../../../../java/util/Collections.js'\nimport DirectedEdge from './DirectedEdge.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport Edge from './Edge.js'\nexport default class DirectedEdgeStar {\n constructor() {\n DirectedEdgeStar.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._outEdges = new ArrayList()\n this._sorted = false\n }\n getNextEdge(dirEdge) {\n const i = this.getIndex(dirEdge)\n return this._outEdges.get(this.getIndex(i + 1))\n }\n getCoordinate() {\n const it = this.iterator()\n if (!it.hasNext()) return null\n const e = it.next()\n return e.getCoordinate()\n }\n iterator() {\n this.sortEdges()\n return this._outEdges.iterator()\n }\n sortEdges() {\n if (!this._sorted) {\n Collections.sort(this._outEdges)\n this._sorted = true\n }\n }\n remove(de) {\n this._outEdges.remove(de)\n }\n getEdges() {\n this.sortEdges()\n return this._outEdges\n }\n getNextCWEdge(dirEdge) {\n const i = this.getIndex(dirEdge)\n return this._outEdges.get(this.getIndex(i - 1))\n }\n getIndex() {\n if (arguments[0] instanceof Edge) {\n const edge = arguments[0]\n this.sortEdges()\n for (let i = 0; i < this._outEdges.size(); i++) {\n const de = this._outEdges.get(i)\n if (de.getEdge() === edge) return i\n }\n return -1\n } else if (arguments[0] instanceof DirectedEdge) {\n const dirEdge = arguments[0]\n this.sortEdges()\n for (let i = 0; i < this._outEdges.size(); i++) {\n const de = this._outEdges.get(i)\n if (de === dirEdge) return i\n }\n return -1\n } else if (Number.isInteger(arguments[0])) {\n const i = arguments[0]\n let modi = i % this._outEdges.size()\n if (modi < 0) modi += this._outEdges.size()\n return modi\n }\n }\n add(de) {\n this._outEdges.add(de)\n this._sorted = false\n }\n getDegree() {\n return this._outEdges.size()\n }\n}\n","import DirectedEdgeStar from './DirectedEdgeStar.js'\nimport HashSet from '../../../../java/util/HashSet.js'\nimport DirectedEdge from './DirectedEdge.js'\nimport GraphComponent from './GraphComponent.js'\nexport default class Node extends GraphComponent {\n constructor() {\n super()\n Node.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pt = null\n this._deStar = null\n if (arguments.length === 1) {\n const pt = arguments[0]\n Node.constructor_.call(this, pt, new DirectedEdgeStar())\n } else if (arguments.length === 2) {\n const pt = arguments[0], deStar = arguments[1]\n this._pt = pt\n this._deStar = deStar\n }\n }\n static getEdgesBetween(node0, node1) {\n const edges0 = DirectedEdge.toEdges(node0.getOutEdges().getEdges())\n const commonEdges = new HashSet(edges0)\n const edges1 = DirectedEdge.toEdges(node1.getOutEdges().getEdges())\n commonEdges.retainAll(edges1)\n return commonEdges\n }\n isRemoved() {\n return this._pt === null\n }\n addOutEdge(de) {\n this._deStar.add(de)\n }\n getCoordinate() {\n return this._pt\n }\n getOutEdges() {\n return this._deStar\n }\n remove() {\n if (arguments.length === 0) {\n this._pt = null\n } else if (arguments.length === 1) {\n const de = arguments[0]\n this._deStar.remove(de)\n }\n }\n getIndex(edge) {\n return this._deStar.getIndex(edge)\n }\n getDegree() {\n return this._deStar.getDegree()\n }\n}\n","import Edge from '../../planargraph/Edge.js'\nexport default class LineMergeEdge extends Edge {\n constructor() {\n super()\n LineMergeEdge.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._line = null\n const line = arguments[0]\n this._line = line\n }\n getLine() {\n return this._line\n }\n}\n","import TreeMap from '../../../../java/util/TreeMap.js'\nexport default class NodeMap {\n constructor() {\n NodeMap.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._nodeMap = new TreeMap()\n }\n find(coord) {\n return this._nodeMap.get(coord)\n }\n iterator() {\n return this._nodeMap.values().iterator()\n }\n remove(pt) {\n return this._nodeMap.remove(pt)\n }\n values() {\n return this._nodeMap.values()\n }\n add(n) {\n this._nodeMap.put(n.getCoordinate(), n)\n return n\n }\n}\n","import HashSet from '../../../../java/util/HashSet.js'\nimport Node from './Node.js'\nimport NodeMap from './NodeMap.js'\nimport DirectedEdge from './DirectedEdge.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport Edge from './Edge.js'\nexport default class PlanarGraph {\n constructor() {\n PlanarGraph.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._edges = new HashSet()\n this._dirEdges = new HashSet()\n this._nodeMap = new NodeMap()\n }\n findNodesOfDegree(degree) {\n const nodesFound = new ArrayList()\n for (let i = this.nodeIterator(); i.hasNext(); ) {\n const node = i.next()\n if (node.getDegree() === degree) nodesFound.add(node)\n }\n return nodesFound\n }\n dirEdgeIterator() {\n return this._dirEdges.iterator()\n }\n edgeIterator() {\n return this._edges.iterator()\n }\n remove() {\n if (arguments[0] instanceof Edge) {\n const edge = arguments[0]\n this.remove(edge.getDirEdge(0))\n this.remove(edge.getDirEdge(1))\n this._edges.remove(edge)\n edge.remove()\n } else if (arguments[0] instanceof DirectedEdge) {\n const de = arguments[0]\n const sym = de.getSym()\n if (sym !== null) sym.setSym(null)\n de.getFromNode().remove(de)\n de.remove()\n this._dirEdges.remove(de)\n } else if (arguments[0] instanceof Node) {\n const node = arguments[0]\n const outEdges = node.getOutEdges().getEdges()\n for (let i = outEdges.iterator(); i.hasNext(); ) {\n const de = i.next()\n const sym = de.getSym()\n if (sym !== null) this.remove(sym)\n this._dirEdges.remove(de)\n const edge = de.getEdge()\n if (edge !== null) \n this._edges.remove(edge)\n \n }\n this._nodeMap.remove(node.getCoordinate())\n node.remove()\n }\n }\n findNode(pt) {\n return this._nodeMap.find(pt)\n }\n getEdges() {\n return this._edges\n }\n nodeIterator() {\n return this._nodeMap.iterator()\n }\n contains() {\n if (arguments[0] instanceof Edge) {\n const e = arguments[0]\n return this._edges.contains(e)\n } else if (arguments[0] instanceof DirectedEdge) {\n const de = arguments[0]\n return this._dirEdges.contains(de)\n }\n }\n add() {\n if (arguments[0] instanceof Node) {\n const node = arguments[0]\n this._nodeMap.add(node)\n } else if (arguments[0] instanceof Edge) {\n const edge = arguments[0]\n this._edges.add(edge)\n this.add(edge.getDirEdge(0))\n this.add(edge.getDirEdge(1))\n } else if (arguments[0] instanceof DirectedEdge) {\n const dirEdge = arguments[0]\n this._dirEdges.add(dirEdge)\n }\n }\n getNodes() {\n return this._nodeMap.values()\n }\n}\n","import LineMergeDirectedEdge from './LineMergeDirectedEdge.js'\nimport Node from '../../planargraph/Node.js'\nimport CoordinateArrays from '../../geom/CoordinateArrays.js'\nimport LineMergeEdge from './LineMergeEdge.js'\nimport PlanarGraph from '../../planargraph/PlanarGraph.js'\nexport default class LineMergeGraph extends PlanarGraph {\n constructor() {\n super()\n }\n addEdge(lineString) {\n if (lineString.isEmpty()) \n return null\n \n const coordinates = CoordinateArrays.removeRepeatedPoints(lineString.getCoordinates())\n if (coordinates.length <= 1) return null\n const startCoordinate = coordinates[0]\n const endCoordinate = coordinates[coordinates.length - 1]\n const startNode = this.getNode(startCoordinate)\n const endNode = this.getNode(endCoordinate)\n const directedEdge0 = new LineMergeDirectedEdge(startNode, endNode, coordinates[1], true)\n const directedEdge1 = new LineMergeDirectedEdge(endNode, startNode, coordinates[coordinates.length - 2], false)\n const edge = new LineMergeEdge(lineString)\n edge.setDirectedEdges(directedEdge0, directedEdge1)\n this.add(edge)\n }\n getNode(coordinate) {\n let node = this.findNode(coordinate)\n if (node === null) {\n node = new Node(coordinate)\n this.add(node)\n }\n return node\n }\n}\n","import LineString from '../../geom/LineString.js'\nimport Geometry from '../../geom/Geometry.js'\nimport hasInterface from '../../../../../hasInterface.js'\nimport Collection from '../../../../../java/util/Collection.js'\nimport EdgeString from './EdgeString.js'\nimport LineMergeGraph from './LineMergeGraph.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Assert from '../../util/Assert.js'\nimport GraphComponent from '../../planargraph/GraphComponent.js'\nexport default class LineMerger {\n constructor() {\n LineMerger.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._graph = new LineMergeGraph()\n this._mergedLineStrings = null\n this._factory = null\n this._edgeStrings = null\n }\n buildEdgeStringsForUnprocessedNodes() {\n for (let i = this._graph.getNodes().iterator(); i.hasNext(); ) {\n const node = i.next()\n if (!node.isMarked()) {\n Assert.isTrue(node.getDegree() === 2)\n this.buildEdgeStringsStartingAt(node)\n node.setMarked(true)\n }\n }\n }\n buildEdgeStringsForNonDegree2Nodes() {\n for (let i = this._graph.getNodes().iterator(); i.hasNext(); ) {\n const node = i.next()\n if (node.getDegree() !== 2) {\n this.buildEdgeStringsStartingAt(node)\n node.setMarked(true)\n }\n }\n }\n buildEdgeStringsForObviousStartNodes() {\n this.buildEdgeStringsForNonDegree2Nodes()\n }\n getMergedLineStrings() {\n this.merge()\n return this._mergedLineStrings\n }\n buildEdgeStringsStartingAt(node) {\n for (let i = node.getOutEdges().iterator(); i.hasNext(); ) {\n const directedEdge = i.next()\n if (directedEdge.getEdge().isMarked()) \n continue\n \n this._edgeStrings.add(this.buildEdgeStringStartingWith(directedEdge))\n }\n }\n merge() {\n if (this._mergedLineStrings !== null) \n return null\n \n GraphComponent.setMarked(this._graph.nodeIterator(), false)\n GraphComponent.setMarked(this._graph.edgeIterator(), false)\n this._edgeStrings = new ArrayList()\n this.buildEdgeStringsForObviousStartNodes()\n this.buildEdgeStringsForIsolatedLoops()\n this._mergedLineStrings = new ArrayList()\n for (let i = this._edgeStrings.iterator(); i.hasNext(); ) {\n const edgeString = i.next()\n this._mergedLineStrings.add(edgeString.toLineString())\n }\n }\n addLineString(lineString) {\n if (this._factory === null) \n this._factory = lineString.getFactory()\n \n this._graph.addEdge(lineString)\n }\n buildEdgeStringStartingWith(start) {\n const edgeString = new EdgeString(this._factory)\n let current = start\n do {\n edgeString.add(current)\n current.getEdge().setMarked(true)\n current = current.getNext()\n } while (current !== null && current !== start)\n return edgeString\n }\n add() {\n if (arguments[0] instanceof Geometry) {\n const geometry = arguments[0]\n for (let i = 0; i < geometry.getNumGeometries(); i++) {\n const component = geometry.getGeometryN(i)\n if (component instanceof LineString) \n this.addLineString(component)\n \n }\n \n } else if (hasInterface(arguments[0], Collection)) {\n const geometries = arguments[0]\n this._mergedLineStrings = null\n for (let i = geometries.iterator(); i.hasNext(); ) {\n const geometry = i.next()\n this.add(geometry)\n }\n }\n }\n buildEdgeStringsForIsolatedLoops() {\n this.buildEdgeStringsForUnprocessedNodes()\n }\n}\n","import HashSet from '../../../../java/util/HashSet.js'\nimport NodeMap from './NodeMap.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nexport default class Subgraph {\n constructor() {\n Subgraph.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._parentGraph = null\n this._edges = new HashSet()\n this._dirEdges = new ArrayList()\n this._nodeMap = new NodeMap()\n const parentGraph = arguments[0]\n this._parentGraph = parentGraph\n }\n dirEdgeIterator() {\n return this._dirEdges.iterator()\n }\n edgeIterator() {\n return this._edges.iterator()\n }\n getParent() {\n return this._parentGraph\n }\n nodeIterator() {\n return this._nodeMap.iterator()\n }\n contains(e) {\n return this._edges.contains(e)\n }\n add(e) {\n if (this._edges.contains(e)) return null\n this._edges.add(e)\n this._dirEdges.add(e.getDirEdge(0))\n this._dirEdges.add(e.getDirEdge(1))\n this._nodeMap.add(e.getDirEdge(0).getFromNode())\n this._nodeMap.add(e.getDirEdge(1).getFromNode())\n }\n}\n","import Stack from '../../../../../java/util/Stack.js'\nimport Subgraph from '../Subgraph.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport GraphComponent from '../GraphComponent.js'\nexport default class ConnectedSubgraphFinder {\n constructor() {\n ConnectedSubgraphFinder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._graph = null\n const graph = arguments[0]\n this._graph = graph\n }\n addReachable(startNode, subgraph) {\n const nodeStack = new Stack()\n nodeStack.add(startNode)\n while (!nodeStack.empty()) {\n const node = nodeStack.pop()\n this.addEdges(node, nodeStack, subgraph)\n }\n }\n findSubgraph(node) {\n const subgraph = new Subgraph(this._graph)\n this.addReachable(node, subgraph)\n return subgraph\n }\n getConnectedSubgraphs() {\n const subgraphs = new ArrayList()\n GraphComponent.setVisited(this._graph.nodeIterator(), false)\n for (let i = this._graph.edgeIterator(); i.hasNext(); ) {\n const e = i.next()\n const node = e.getDirEdge(0).getFromNode()\n if (!node.isVisited()) \n subgraphs.add(this.findSubgraph(node))\n \n }\n return subgraphs\n }\n addEdges(node, nodeStack, subgraph) {\n node.setVisited(true)\n for (let i = node.getOutEdges().iterator(); i.hasNext(); ) {\n const de = i.next()\n subgraph.add(de.getEdge())\n const toNode = de.getToNode()\n if (!toNode.isVisited()) nodeStack.push(toNode)\n }\n }\n}\n","import TreeSet from '../../../../../java/util/TreeSet.js'\nimport LineString from '../../geom/LineString.js'\nimport Geometry from '../../geom/Geometry.js'\nimport hasInterface from '../../../../../hasInterface.js'\nimport GeometryFactory from '../../geom/GeometryFactory.js'\nimport Collection from '../../../../../java/util/Collection.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport Integer from '../../../../../java/lang/Integer.js'\nimport LineMergeGraph from './LineMergeGraph.js'\nimport LinkedList from '../../../../../java/util/LinkedList.js'\nimport GeometryComponentFilter from '../../geom/GeometryComponentFilter.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport ConnectedSubgraphFinder from '../../planargraph/algorithm/ConnectedSubgraphFinder.js'\nimport Assert from '../../util/Assert.js'\nimport MultiLineString from '../../geom/MultiLineString.js'\nimport GraphComponent from '../../planargraph/GraphComponent.js'\nexport default class LineSequencer {\n constructor() {\n LineSequencer.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._graph = new LineMergeGraph()\n this._factory = new GeometryFactory()\n this._lineCount = 0\n this._isRun = false\n this._sequencedGeometry = null\n this._isSequenceable = false\n }\n static findUnvisitedBestOrientedDE(node) {\n let wellOrientedDE = null\n let unvisitedDE = null\n for (let i = node.getOutEdges().iterator(); i.hasNext(); ) {\n const de = i.next()\n if (!de.getEdge().isVisited()) {\n unvisitedDE = de\n if (de.getEdgeDirection()) wellOrientedDE = de\n }\n }\n if (wellOrientedDE !== null) return wellOrientedDE\n return unvisitedDE\n }\n static findLowestDegreeNode(graph) {\n let minDegree = Integer.MAX_VALUE\n let minDegreeNode = null\n for (let i = graph.nodeIterator(); i.hasNext(); ) {\n const node = i.next()\n if (minDegreeNode === null || node.getDegree() < minDegree) {\n minDegree = node.getDegree()\n minDegreeNode = node\n }\n }\n return minDegreeNode\n }\n static isSequenced(geom) {\n if (!(geom instanceof MultiLineString)) \n return true\n \n const mls = geom\n const prevSubgraphNodes = new TreeSet()\n let lastNode = null\n const currNodes = new ArrayList()\n for (let i = 0; i < mls.getNumGeometries(); i++) {\n const line = mls.getGeometryN(i)\n const startNode = line.getCoordinateN(0)\n const endNode = line.getCoordinateN(line.getNumPoints() - 1)\n if (prevSubgraphNodes.contains(startNode)) return false\n if (prevSubgraphNodes.contains(endNode)) return false\n if (lastNode !== null) \n if (!startNode.equals(lastNode)) {\n prevSubgraphNodes.addAll(currNodes)\n currNodes.clear()\n }\n \n currNodes.add(startNode)\n currNodes.add(endNode)\n lastNode = endNode\n }\n return true\n }\n static reverse(line) {\n const pts = line.getCoordinates()\n const revPts = new Array(pts.length).fill(null)\n const len = pts.length\n for (let i = 0; i < len; i++) \n revPts[len - 1 - i] = new Coordinate(pts[i])\n \n return line.getFactory().createLineString(revPts)\n }\n static sequence(geom) {\n const sequencer = new LineSequencer()\n sequencer.add(geom)\n return sequencer.getSequencedLineStrings()\n }\n addLine(lineString) {\n if (this._factory === null) \n this._factory = lineString.getFactory()\n \n this._graph.addEdge(lineString)\n this._lineCount++\n }\n hasSequence(graph) {\n let oddDegreeCount = 0\n for (let i = graph.nodeIterator(); i.hasNext(); ) {\n const node = i.next()\n if (node.getDegree() % 2 === 1) oddDegreeCount++\n }\n return oddDegreeCount <= 2\n }\n computeSequence() {\n if (this._isRun) \n return null\n \n this._isRun = true\n const sequences = this.findSequences()\n if (sequences === null) return null\n this._sequencedGeometry = this.buildSequencedGeometry(sequences)\n this._isSequenceable = true\n const finalLineCount = this._sequencedGeometry.getNumGeometries()\n Assert.isTrue(this._lineCount === finalLineCount, 'Lines were missing from result')\n Assert.isTrue(this._sequencedGeometry instanceof LineString || this._sequencedGeometry instanceof MultiLineString, 'Result is not lineal')\n }\n findSequences() {\n const sequences = new ArrayList()\n const csFinder = new ConnectedSubgraphFinder(this._graph)\n const subgraphs = csFinder.getConnectedSubgraphs()\n for (let i = subgraphs.iterator(); i.hasNext(); ) {\n const subgraph = i.next()\n if (this.hasSequence(subgraph)) {\n const seq = this.findSequence(subgraph)\n sequences.add(seq)\n } else {\n return null\n }\n }\n return sequences\n }\n addReverseSubpath(de, lit, expectedClosed) {\n const endNode = de.getToNode()\n let fromNode = null\n while (true) {\n lit.add(de.getSym())\n de.getEdge().setVisited(true)\n fromNode = de.getFromNode()\n const unvisitedOutDE = LineSequencer.findUnvisitedBestOrientedDE(fromNode)\n if (unvisitedOutDE === null) break\n de = unvisitedOutDE.getSym()\n }\n if (expectedClosed) \n Assert.isTrue(fromNode === endNode, 'path not contiguous')\n \n }\n findSequence(graph) {\n GraphComponent.setVisited(graph.edgeIterator(), false)\n const startNode = LineSequencer.findLowestDegreeNode(graph)\n const startDE = startNode.getOutEdges().iterator().next()\n const startDESym = startDE.getSym()\n const seq = new LinkedList()\n const lit = seq.listIterator()\n this.addReverseSubpath(startDESym, lit, false)\n while (lit.hasPrevious()) {\n const prev = lit.previous()\n const unvisitedOutDE = LineSequencer.findUnvisitedBestOrientedDE(prev.getFromNode())\n if (unvisitedOutDE !== null) this.addReverseSubpath(unvisitedOutDE.getSym(), lit, true)\n }\n const orientedSeq = this.orient(seq)\n return orientedSeq\n }\n reverse(seq) {\n const newSeq = new LinkedList()\n for (let i = seq.iterator(); i.hasNext(); ) {\n const de = i.next()\n newSeq.addFirst(de.getSym())\n }\n return newSeq\n }\n orient(seq) {\n const startEdge = seq.get(0)\n const endEdge = seq.get(seq.size() - 1)\n const startNode = startEdge.getFromNode()\n const endNode = endEdge.getToNode()\n let flipSeq = false\n const hasDegree1Node = startNode.getDegree() === 1 || endNode.getDegree() === 1\n if (hasDegree1Node) {\n let hasObviousStartNode = false\n if (endEdge.getToNode().getDegree() === 1 && endEdge.getEdgeDirection() === false) {\n hasObviousStartNode = true\n flipSeq = true\n }\n if (startEdge.getFromNode().getDegree() === 1 && startEdge.getEdgeDirection() === true) {\n hasObviousStartNode = true\n flipSeq = false\n }\n if (!hasObviousStartNode) \n if (startEdge.getFromNode().getDegree() === 1) flipSeq = true\n \n }\n if (flipSeq) return this.reverse(seq)\n return seq\n }\n buildSequencedGeometry(sequences) {\n const lines = new ArrayList()\n for (let i1 = sequences.iterator(); i1.hasNext(); ) {\n const seq = i1.next()\n for (let i2 = seq.iterator(); i2.hasNext(); ) {\n const de = i2.next()\n const e = de.getEdge()\n const line = e.getLine()\n let lineToAdd = line\n if (!de.getEdgeDirection() && !line.isClosed()) lineToAdd = LineSequencer.reverse(line)\n lines.add(lineToAdd)\n }\n }\n if (lines.size() === 0) return this._factory.createMultiLineString(new Array(0).fill(null))\n return this._factory.buildGeometry(lines)\n }\n getSequencedLineStrings() {\n this.computeSequence()\n return this._sequencedGeometry\n }\n isSequenceable() {\n this.computeSequence()\n return this._isSequenceable\n }\n add() {\n if (hasInterface(arguments[0], Collection)) {\n const geometries = arguments[0]\n for (let i = geometries.iterator(); i.hasNext(); ) {\n const geometry = i.next()\n this.add(geometry)\n }\n } else if (arguments[0] instanceof Geometry) {\n const geometry = arguments[0]\n geometry.apply(new (class {\n get interfaces_() {\n return [GeometryComponentFilter]\n }\n filter(component) {\n if (component instanceof LineString) \n this.addLine(component)\n \n }\n })())\n }\n }\n}\n","import LineString from '../../../geom/LineString.js'\nimport CoordinateList from '../../../geom/CoordinateList.js'\nimport Coordinate from '../../../geom/Coordinate.js'\nimport Double from '../../../../../../java/lang/Double.js'\nimport LineSegment from '../../../geom/LineSegment.js'\nexport default class LineStringSnapper {\n constructor() {\n LineStringSnapper.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._snapTolerance = 0.0\n this._srcPts = null\n this._seg = new LineSegment()\n this._allowSnappingToSourceVertices = false\n this._isClosed = false\n if (arguments[0] instanceof LineString && typeof arguments[1] === 'number') {\n const srcLine = arguments[0], snapTolerance = arguments[1]\n LineStringSnapper.constructor_.call(this, srcLine.getCoordinates(), snapTolerance)\n } else if (arguments[0] instanceof Array && typeof arguments[1] === 'number') {\n const srcPts = arguments[0], snapTolerance = arguments[1]\n this._srcPts = srcPts\n this._isClosed = LineStringSnapper.isClosed(srcPts)\n this._snapTolerance = snapTolerance\n }\n }\n static isClosed(pts) {\n if (pts.length <= 1) return false\n return pts[0].equals2D(pts[pts.length - 1])\n }\n snapVertices(srcCoords, snapPts) {\n const end = this._isClosed ? srcCoords.size() - 1 : srcCoords.size()\n for (let i = 0; i < end; i++) {\n const srcPt = srcCoords.get(i)\n const snapVert = this.findSnapForVertex(srcPt, snapPts)\n if (snapVert !== null) {\n srcCoords.set(i, new Coordinate(snapVert))\n if (i === 0 && this._isClosed) srcCoords.set(srcCoords.size() - 1, new Coordinate(snapVert))\n }\n }\n }\n findSnapForVertex(pt, snapPts) {\n for (let i = 0; i < snapPts.length; i++) {\n if (pt.equals2D(snapPts[i])) return null\n if (pt.distance(snapPts[i]) < this._snapTolerance) return snapPts[i]\n }\n return null\n }\n snapTo(snapPts) {\n const coordList = new CoordinateList(this._srcPts)\n this.snapVertices(coordList, snapPts)\n this.snapSegments(coordList, snapPts)\n const newPts = coordList.toCoordinateArray()\n return newPts\n }\n snapSegments(srcCoords, snapPts) {\n if (snapPts.length === 0) return null\n let distinctPtCount = snapPts.length\n if (snapPts[0].equals2D(snapPts[snapPts.length - 1])) distinctPtCount = snapPts.length - 1\n for (let i = 0; i < distinctPtCount; i++) {\n const snapPt = snapPts[i]\n const index = this.findSegmentIndexToSnap(snapPt, srcCoords)\n if (index >= 0) \n srcCoords.add(index + 1, new Coordinate(snapPt), false)\n \n }\n }\n findSegmentIndexToSnap(snapPt, srcCoords) {\n let minDist = Double.MAX_VALUE\n let snapIndex = -1\n for (let i = 0; i < srcCoords.size() - 1; i++) {\n this._seg.p0 = srcCoords.get(i)\n this._seg.p1 = srcCoords.get(i + 1)\n if (this._seg.p0.equals2D(snapPt) || this._seg.p1.equals2D(snapPt)) \n if (this._allowSnappingToSourceVertices) continue; else return -1\n \n const dist = this._seg.distance(snapPt)\n if (dist < this._snapTolerance && dist < minDist) {\n minDist = dist\n snapIndex = i\n }\n }\n return snapIndex\n }\n setAllowSnappingToSourceVertices(allowSnappingToSourceVertices) {\n this._allowSnappingToSourceVertices = allowSnappingToSourceVertices\n }\n}\n","import TreeSet from '../../../../../../java/util/TreeSet.js'\nimport GeometryTransformer from '../../../geom/util/GeometryTransformer.js'\nimport hasInterface from '../../../../../../hasInterface.js'\nimport Double from '../../../../../../java/lang/Double.js'\nimport LineStringSnapper from './LineStringSnapper.js'\nimport PrecisionModel from '../../../geom/PrecisionModel.js'\nimport Polygonal from '../../../geom/Polygonal.js'\nexport default class GeometrySnapper {\n constructor() {\n GeometrySnapper.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._srcGeom = null\n const srcGeom = arguments[0]\n this._srcGeom = srcGeom\n }\n static snap(g0, g1, snapTolerance) {\n const snapGeom = new Array(2).fill(null)\n const snapper0 = new GeometrySnapper(g0)\n snapGeom[0] = snapper0.snapTo(g1, snapTolerance)\n const snapper1 = new GeometrySnapper(g1)\n snapGeom[1] = snapper1.snapTo(snapGeom[0], snapTolerance)\n return snapGeom\n }\n static computeOverlaySnapTolerance() {\n if (arguments.length === 1) {\n const g = arguments[0]\n let snapTolerance = GeometrySnapper.computeSizeBasedSnapTolerance(g)\n const pm = g.getPrecisionModel()\n if (pm.getType() === PrecisionModel.FIXED) {\n const fixedSnapTol = 1 / pm.getScale() * 2 / 1.415\n if (fixedSnapTol > snapTolerance) snapTolerance = fixedSnapTol\n }\n return snapTolerance\n } else if (arguments.length === 2) {\n const g0 = arguments[0], g1 = arguments[1]\n return Math.min(GeometrySnapper.computeOverlaySnapTolerance(g0), GeometrySnapper.computeOverlaySnapTolerance(g1))\n }\n }\n static computeSizeBasedSnapTolerance(g) {\n const env = g.getEnvelopeInternal()\n const minDimension = Math.min(env.getHeight(), env.getWidth())\n const snapTol = minDimension * GeometrySnapper.SNAP_PRECISION_FACTOR\n return snapTol\n }\n static snapToSelf(geom, snapTolerance, cleanResult) {\n const snapper0 = new GeometrySnapper(geom)\n return snapper0.snapToSelf(snapTolerance, cleanResult)\n }\n snapTo(snapGeom, snapTolerance) {\n const snapPts = this.extractTargetCoordinates(snapGeom)\n const snapTrans = new SnapTransformer(snapTolerance, snapPts)\n return snapTrans.transform(this._srcGeom)\n }\n snapToSelf(snapTolerance, cleanResult) {\n const snapPts = this.extractTargetCoordinates(this._srcGeom)\n const snapTrans = new SnapTransformer(snapTolerance, snapPts, true)\n const snappedGeom = snapTrans.transform(this._srcGeom)\n let result = snappedGeom\n if (cleanResult && hasInterface(result, Polygonal)) \n result = snappedGeom.buffer(0)\n \n return result\n }\n computeSnapTolerance(ringPts) {\n const minSegLen = this.computeMinimumSegmentLength(ringPts)\n const snapTol = minSegLen / 10\n return snapTol\n }\n extractTargetCoordinates(g) {\n const ptSet = new TreeSet()\n const pts = g.getCoordinates()\n for (let i = 0; i < pts.length; i++) \n ptSet.add(pts[i])\n \n return ptSet.toArray(new Array(0).fill(null))\n }\n computeMinimumSegmentLength(pts) {\n let minSegLen = Double.MAX_VALUE\n for (let i = 0; i < pts.length - 1; i++) {\n const segLen = pts[i].distance(pts[i + 1])\n if (segLen < minSegLen) minSegLen = segLen\n }\n return minSegLen\n }\n}\nGeometrySnapper.SNAP_PRECISION_FACTOR = 1e-9\nclass SnapTransformer extends GeometryTransformer {\n constructor() {\n super()\n SnapTransformer.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._snapTolerance = null\n this._snapPts = null\n this._isSelfSnap = false\n if (arguments.length === 2) {\n const snapTolerance = arguments[0], snapPts = arguments[1]\n this._snapTolerance = snapTolerance\n this._snapPts = snapPts\n } else if (arguments.length === 3) {\n const snapTolerance = arguments[0], snapPts = arguments[1], isSelfSnap = arguments[2]\n this._snapTolerance = snapTolerance\n this._snapPts = snapPts\n this._isSelfSnap = isSelfSnap\n }\n }\n snapLine(srcPts, snapPts) {\n const snapper = new LineStringSnapper(srcPts, this._snapTolerance)\n snapper.setAllowSnappingToSourceVertices(this._isSelfSnap)\n return snapper.snapTo(snapPts)\n }\n transformCoordinates(coords, parent) {\n const srcPts = coords.toCoordinateArray()\n const newPts = this.snapLine(srcPts, this._snapPts)\n return this._factory.getCoordinateSequenceFactory().create(newPts)\n }\n}\n","import WKTWriter from '../io/WKTWriter.js'\nimport CoordinateArraySequence from '../geom/impl/CoordinateArraySequence.js'\nimport Octant from './Octant.js'\nimport SegmentString from './SegmentString.js'\nexport default class BasicSegmentString {\n constructor() {\n BasicSegmentString.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pts = null\n this._data = null\n const pts = arguments[0], data = arguments[1]\n this._pts = pts\n this._data = data\n }\n getCoordinates() {\n return this._pts\n }\n size() {\n return this._pts.length\n }\n getCoordinate(i) {\n return this._pts[i]\n }\n isClosed() {\n return this._pts[0].equals(this._pts[this._pts.length - 1])\n }\n getSegmentOctant(index) {\n if (index === this._pts.length - 1) return -1\n return Octant.octant(this.getCoordinate(index), this.getCoordinate(index + 1))\n }\n setData(data) {\n this._data = data\n }\n getData() {\n return this._data\n }\n toString() {\n return WKTWriter.toLineString(new CoordinateArraySequence(this._pts))\n }\n get interfaces_() {\n return [SegmentString]\n }\n}\n","import SegmentIntersector from './SegmentIntersector.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nexport default class NodingIntersectionFinder {\n constructor() {\n NodingIntersectionFinder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._findAllIntersections = false\n this._isCheckEndSegmentsOnly = false\n this._keepIntersections = true\n this._isInteriorIntersectionsOnly = false\n this._li = null\n this._interiorIntersection = null\n this._intSegments = null\n this._intersections = new ArrayList()\n this._intersectionCount = 0\n const li = arguments[0]\n this._li = li\n this._interiorIntersection = null\n }\n static createAllIntersectionsFinder(li) {\n const finder = new NodingIntersectionFinder(li)\n finder.setFindAllIntersections(true)\n return finder\n }\n static isInteriorVertexIntersection() {\n if (arguments.length === 4) {\n const p0 = arguments[0], p1 = arguments[1], isEnd0 = arguments[2], isEnd1 = arguments[3]\n if (isEnd0 && isEnd1) return false\n if (p0.equals2D(p1)) \n return true\n \n return false\n } else if (arguments.length === 8) {\n const p00 = arguments[0], p01 = arguments[1], p10 = arguments[2], p11 = arguments[3], isEnd00 = arguments[4], isEnd01 = arguments[5], isEnd10 = arguments[6], isEnd11 = arguments[7]\n if (NodingIntersectionFinder.isInteriorVertexIntersection(p00, p10, isEnd00, isEnd10)) return true\n if (NodingIntersectionFinder.isInteriorVertexIntersection(p00, p11, isEnd00, isEnd11)) return true\n if (NodingIntersectionFinder.isInteriorVertexIntersection(p01, p10, isEnd01, isEnd10)) return true\n if (NodingIntersectionFinder.isInteriorVertexIntersection(p01, p11, isEnd01, isEnd11)) return true\n return false\n }\n }\n static createInteriorIntersectionCounter(li) {\n const finder = new NodingIntersectionFinder(li)\n finder.setInteriorIntersectionsOnly(true)\n finder.setFindAllIntersections(true)\n finder.setKeepIntersections(false)\n return finder\n }\n static createIntersectionCounter(li) {\n const finder = new NodingIntersectionFinder(li)\n finder.setFindAllIntersections(true)\n finder.setKeepIntersections(false)\n return finder\n }\n static isEndSegment(segStr, index) {\n if (index === 0) return true\n if (index >= segStr.size() - 2) return true\n return false\n }\n static createAnyIntersectionFinder(li) {\n return new NodingIntersectionFinder(li)\n }\n static createInteriorIntersectionsFinder(li) {\n const finder = new NodingIntersectionFinder(li)\n finder.setFindAllIntersections(true)\n finder.setInteriorIntersectionsOnly(true)\n return finder\n }\n setCheckEndSegmentsOnly(isCheckEndSegmentsOnly) {\n this._isCheckEndSegmentsOnly = isCheckEndSegmentsOnly\n }\n getIntersectionSegments() {\n return this._intSegments\n }\n count() {\n return this._intersectionCount\n }\n getIntersections() {\n return this._intersections\n }\n setFindAllIntersections(findAllIntersections) {\n this._findAllIntersections = findAllIntersections\n }\n setKeepIntersections(keepIntersections) {\n this._keepIntersections = keepIntersections\n }\n getIntersection() {\n return this._interiorIntersection\n }\n processIntersections(e0, segIndex0, e1, segIndex1) {\n if (!this._findAllIntersections && this.hasIntersection()) return null\n const isSameSegString = e0 === e1\n const isSameSegment = isSameSegString && segIndex0 === segIndex1\n if (isSameSegment) return null\n if (this._isCheckEndSegmentsOnly) {\n const isEndSegPresent = NodingIntersectionFinder.isEndSegment(e0, segIndex0) || NodingIntersectionFinder.isEndSegment(e1, segIndex1)\n if (!isEndSegPresent) return null\n }\n const p00 = e0.getCoordinate(segIndex0)\n const p01 = e0.getCoordinate(segIndex0 + 1)\n const p10 = e1.getCoordinate(segIndex1)\n const p11 = e1.getCoordinate(segIndex1 + 1)\n const isEnd00 = segIndex0 === 0\n const isEnd01 = segIndex0 + 2 === e0.size()\n const isEnd10 = segIndex1 === 0\n const isEnd11 = segIndex1 + 2 === e1.size()\n this._li.computeIntersection(p00, p01, p10, p11)\n const isInteriorInt = this._li.hasIntersection() && this._li.isInteriorIntersection()\n let isInteriorVertexInt = false\n if (!this._isInteriorIntersectionsOnly) {\n const isAdjacentSegment = isSameSegString && Math.abs(segIndex1 - segIndex0) <= 1\n isInteriorVertexInt = !isAdjacentSegment && NodingIntersectionFinder.isInteriorVertexIntersection(p00, p01, p10, p11, isEnd00, isEnd01, isEnd10, isEnd11)\n }\n if (isInteriorInt || isInteriorVertexInt) {\n this._intSegments = new Array(4).fill(null)\n this._intSegments[0] = p00\n this._intSegments[1] = p01\n this._intSegments[2] = p10\n this._intSegments[3] = p11\n this._interiorIntersection = this._li.getIntersection(0)\n if (this._keepIntersections) this._intersections.add(this._interiorIntersection)\n this._intersectionCount++\n }\n }\n hasIntersection() {\n return this._interiorIntersection !== null\n }\n isDone() {\n if (this._findAllIntersections) return false\n return this._interiorIntersection !== null\n }\n setInteriorIntersectionsOnly(isInteriorIntersectionsOnly) {\n this._isInteriorIntersectionsOnly = isInteriorIntersectionsOnly\n }\n get interfaces_() {\n return [SegmentIntersector]\n }\n}\n","import WKTWriter from '../io/WKTWriter.js'\nimport MCIndexNoder from './MCIndexNoder.js'\nimport TopologyException from '../geom/TopologyException.js'\nimport RobustLineIntersector from '../algorithm/RobustLineIntersector.js'\nimport NodingIntersectionFinder from './NodingIntersectionFinder.js'\nexport default class FastNodingValidator {\n constructor() {\n FastNodingValidator.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._li = new RobustLineIntersector()\n this._segStrings = null\n this._findAllIntersections = false\n this._segInt = null\n this._isValid = true\n const segStrings = arguments[0]\n this._segStrings = segStrings\n }\n static computeIntersections(segStrings) {\n const nv = new FastNodingValidator(segStrings)\n nv.setFindAllIntersections(true)\n nv.isValid()\n return nv.getIntersections()\n }\n execute() {\n if (this._segInt !== null) return null\n this.checkInteriorIntersections()\n }\n getIntersections() {\n return this._segInt.getIntersections()\n }\n isValid() {\n this.execute()\n return this._isValid\n }\n setFindAllIntersections(findAllIntersections) {\n this._findAllIntersections = findAllIntersections\n }\n checkInteriorIntersections() {\n this._isValid = true\n this._segInt = new NodingIntersectionFinder(this._li)\n this._segInt.setFindAllIntersections(this._findAllIntersections)\n const noder = new MCIndexNoder()\n noder.setSegmentIntersector(this._segInt)\n noder.computeNodes(this._segStrings)\n if (this._segInt.hasIntersection()) {\n this._isValid = false\n return null\n }\n }\n checkValid() {\n this.execute()\n if (!this._isValid) throw new TopologyException(this.getErrorMessage(), this._segInt.getIntersection())\n }\n getErrorMessage() {\n if (this._isValid) return 'no intersections found'\n const intSegs = this._segInt.getIntersectionSegments()\n return 'found non-noded intersection between ' + WKTWriter.toLineString(intSegs[0], intSegs[1]) + ' and ' + WKTWriter.toLineString(intSegs[2], intSegs[3])\n }\n}\n","import BasicSegmentString from '../noding/BasicSegmentString.js'\nimport FastNodingValidator from '../noding/FastNodingValidator.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nexport default class EdgeNodingValidator {\n constructor() {\n EdgeNodingValidator.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._nv = null\n const edges = arguments[0]\n this._nv = new FastNodingValidator(EdgeNodingValidator.toSegmentStrings(edges))\n }\n static toSegmentStrings(edges) {\n const segStrings = new ArrayList()\n for (let i = edges.iterator(); i.hasNext(); ) {\n const e = i.next()\n segStrings.add(new BasicSegmentString(e.getCoordinates(), e))\n }\n return segStrings\n }\n static checkValid(edges) {\n const validator = new EdgeNodingValidator(edges)\n validator.checkValid()\n }\n checkValid() {\n this._nv.checkValid()\n }\n}\n","import ArrayList from '../../../../../java/util/ArrayList.js'\nimport Assert from '../../util/Assert.js'\nimport OverlayOp from './OverlayOp.js'\nexport default class LineBuilder {\n constructor() {\n LineBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._op = null\n this._geometryFactory = null\n this._ptLocator = null\n this._lineEdgesList = new ArrayList()\n this._resultLineList = new ArrayList()\n const op = arguments[0], geometryFactory = arguments[1], ptLocator = arguments[2]\n this._op = op\n this._geometryFactory = geometryFactory\n this._ptLocator = ptLocator\n }\n collectLines(opCode) {\n for (let it = this._op.getGraph().getEdgeEnds().iterator(); it.hasNext(); ) {\n const de = it.next()\n this.collectLineEdge(de, opCode, this._lineEdgesList)\n this.collectBoundaryTouchEdge(de, opCode, this._lineEdgesList)\n }\n }\n labelIsolatedLine(e, targetIndex) {\n const loc = this._ptLocator.locate(e.getCoordinate(), this._op.getArgGeometry(targetIndex))\n e.getLabel().setLocation(targetIndex, loc)\n }\n build(opCode) {\n this.findCoveredLineEdges()\n this.collectLines(opCode)\n this.buildLines(opCode)\n return this._resultLineList\n }\n collectLineEdge(de, opCode, edges) {\n const label = de.getLabel()\n const e = de.getEdge()\n if (de.isLineEdge()) \n if (!de.isVisited() && OverlayOp.isResultOfOp(label, opCode) && !e.isCovered()) {\n edges.add(e)\n de.setVisitedEdge(true)\n }\n \n }\n findCoveredLineEdges() {\n for (let nodeit = this._op.getGraph().getNodes().iterator(); nodeit.hasNext(); ) {\n const node = nodeit.next()\n node.getEdges().findCoveredLineEdges()\n }\n for (let it = this._op.getGraph().getEdgeEnds().iterator(); it.hasNext(); ) {\n const de = it.next()\n const e = de.getEdge()\n if (de.isLineEdge() && !e.isCoveredSet()) {\n const isCovered = this._op.isCoveredByA(de.getCoordinate())\n e.setCovered(isCovered)\n }\n }\n }\n labelIsolatedLines(edgesList) {\n for (let it = edgesList.iterator(); it.hasNext(); ) {\n const e = it.next()\n const label = e.getLabel()\n if (e.isIsolated()) \n if (label.isNull(0)) this.labelIsolatedLine(e, 0); else this.labelIsolatedLine(e, 1)\n \n }\n }\n buildLines(opCode) {\n for (let it = this._lineEdgesList.iterator(); it.hasNext(); ) {\n const e = it.next()\n const line = this._geometryFactory.createLineString(e.getCoordinates())\n this._resultLineList.add(line)\n e.setInResult(true)\n }\n }\n collectBoundaryTouchEdge(de, opCode, edges) {\n const label = de.getLabel()\n if (de.isLineEdge()) return null\n if (de.isVisited()) return null\n if (de.isInteriorAreaEdge()) return null\n if (de.getEdge().isInResult()) return null\n Assert.isTrue(!(de.isInResult() || de.getSym().isInResult()) || !de.getEdge().isInResult())\n if (OverlayOp.isResultOfOp(label, opCode) && opCode === OverlayOp.INTERSECTION) {\n edges.add(de.getEdge())\n de.setVisitedEdge(true)\n }\n }\n}\n","import ArrayList from '../../../../../java/util/ArrayList.js'\nimport OverlayOp from './OverlayOp.js'\nexport default class PointBuilder {\n constructor() {\n PointBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._op = null\n this._geometryFactory = null\n this._resultPointList = new ArrayList()\n const op = arguments[0], geometryFactory = arguments[1], ptLocator = arguments[2]\n this._op = op\n this._geometryFactory = geometryFactory\n }\n filterCoveredNodeToPoint(n) {\n const coord = n.getCoordinate()\n if (!this._op.isCoveredByLA(coord)) {\n const pt = this._geometryFactory.createPoint(coord)\n this._resultPointList.add(pt)\n }\n }\n extractNonCoveredResultNodes(opCode) {\n for (let nodeit = this._op.getGraph().getNodes().iterator(); nodeit.hasNext(); ) {\n const n = nodeit.next()\n if (n.isInResult()) continue\n if (n.isIncidentEdgeInResult()) continue\n if (n.getEdges().getDegree() === 0 || opCode === OverlayOp.INTERSECTION) {\n const label = n.getLabel()\n if (OverlayOp.isResultOfOp(label, opCode)) \n this.filterCoveredNodeToPoint(n)\n \n }\n }\n }\n build(opCode) {\n this.extractNonCoveredResultNodes(opCode)\n return this._resultPointList\n }\n}\n","import Double from '../../../../java/lang/Double.js'\nimport Long from '../../../../java/lang/Long.js'\nexport default class CommonBits {\n constructor() {\n this._isFirst = true\n this._commonMantissaBitsCount = 53\n this._commonBits = new Long()\n this._commonSignExp = null\n }\n\n getCommon() {\n return Double.longBitsToDouble(this._commonBits)\n }\n\n add(num) {\n const numBits = Double.doubleToLongBits(num)\n if (this._isFirst) {\n this._commonBits = numBits\n this._commonSignExp = CommonBits.signExpBits(this._commonBits)\n this._isFirst = false\n return null\n }\n const numSignExp = CommonBits.signExpBits(numBits)\n if (numSignExp !== this._commonSignExp) {\n this._commonBits.high = 0 | 0\n this._commonBits.low = 0 | 0\n return null\n }\n this._commonMantissaBitsCount = CommonBits.numCommonMostSigMantissaBits(this._commonBits, numBits)\n this._commonBits = CommonBits.zeroLowerBits(this._commonBits, 64 - (12 + this._commonMantissaBitsCount))\n }\n\n toString() {\n if (arguments.length === 1) {\n const bits = arguments[0]\n const x = Double.longBitsToDouble(bits)\n const numStr = Long.toBinaryString(bits)\n const padStr = '0000000000000000000000000000000000000000000000000000000000000000' + numStr\n const bitStr = padStr.substring(padStr.length - 64)\n const str = bitStr.substring(0, 1) + ' ' + bitStr.substring(1, 12) + '(exp) ' + bitStr.substring(12) + ' [ ' + x + ' ]'\n return str\n }\n }\n\n getClass() {\n return CommonBits\n }\n\n get interfaces_() {\n return []\n }\n\n static getBit(bits, i) {\n const mask = (1 << (i % 32))\n if (i < 32) return (bits.low & mask) !== 0 ? 1 : 0\n\n return (bits.high & mask) !== 0 ? 1 : 0\n }\n\n static signExpBits(num) {\n return num.high >>> 20\n }\n\n static zeroLowerBits(bits, nBits) {\n let prop = 'low'\n if (nBits > 32) {\n bits.low = 0 | 0\n nBits %= 32\n prop = 'high'\n }\n if (nBits > 0) {\n const mask = (nBits < 32) ? (~((1 << nBits) - 1)) : 0\n bits[prop] &= mask\n }\n return bits\n }\n\n static numCommonMostSigMantissaBits(num1, num2) {\n let count = 0\n for (let i = 52; i >= 0; i--) {\n if (CommonBits.getBit(num1, i) !== CommonBits.getBit(num2, i)) return count\n count++\n }\n return 52\n }\n}\n","import CommonBits from './CommonBits.js'\nimport CoordinateFilter from '../geom/CoordinateFilter.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport CoordinateSequenceFilter from '../geom/CoordinateSequenceFilter.js'\nexport default class CommonBitsRemover {\n constructor() {\n CommonBitsRemover.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._commonCoord = null\n this._ccFilter = new CommonCoordinateFilter()\n }\n addCommonBits(geom) {\n const trans = new Translater(this._commonCoord)\n geom.apply(trans)\n geom.geometryChanged()\n }\n removeCommonBits(geom) {\n if (this._commonCoord.x === 0.0 && this._commonCoord.y === 0.0) return geom\n const invCoord = new Coordinate(this._commonCoord)\n invCoord.x = -invCoord.x\n invCoord.y = -invCoord.y\n const trans = new Translater(invCoord)\n geom.apply(trans)\n geom.geometryChanged()\n return geom\n }\n getCommonCoordinate() {\n return this._commonCoord\n }\n add(geom) {\n geom.apply(this._ccFilter)\n this._commonCoord = this._ccFilter.getCommonCoordinate()\n }\n}\nclass CommonCoordinateFilter {\n constructor() {\n CommonCoordinateFilter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._commonBitsX = new CommonBits()\n this._commonBitsY = new CommonBits()\n }\n filter(coord) {\n this._commonBitsX.add(coord.x)\n this._commonBitsY.add(coord.y)\n }\n getCommonCoordinate() {\n return new Coordinate(this._commonBitsX.getCommon(), this._commonBitsY.getCommon())\n }\n get interfaces_() {\n return [CoordinateFilter]\n }\n}\nclass Translater {\n constructor() {\n Translater.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.trans = null\n const trans = arguments[0]\n this.trans = trans\n }\n filter(seq, i) {\n const xp = seq.getOrdinate(i, 0) + this.trans.x\n const yp = seq.getOrdinate(i, 1) + this.trans.y\n seq.setOrdinate(i, 0, xp)\n seq.setOrdinate(i, 1, yp)\n }\n isDone() {\n return false\n }\n isGeometryChanged() {\n return true\n }\n get interfaces_() {\n return [CoordinateSequenceFilter]\n }\n}\nCommonBitsRemover.CommonCoordinateFilter = CommonCoordinateFilter\nCommonBitsRemover.Translater = Translater\n","import GeometrySnapper from './GeometrySnapper.js'\nimport System from '../../../../../../java/lang/System.js'\nimport CommonBitsRemover from '../../../precision/CommonBitsRemover.js'\nimport OverlayOp from '../OverlayOp.js'\nexport default class SnapOverlayOp {\n constructor() {\n SnapOverlayOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geom = new Array(2).fill(null)\n this._snapTolerance = null\n this._cbr = null\n const g1 = arguments[0], g2 = arguments[1]\n this._geom[0] = g1\n this._geom[1] = g2\n this.computeSnapTolerance()\n }\n static overlayOp(g0, g1, opCode) {\n const op = new SnapOverlayOp(g0, g1)\n return op.getResultGeometry(opCode)\n }\n static union(g0, g1) {\n return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.UNION)\n }\n static intersection(g0, g1) {\n return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.INTERSECTION)\n }\n static symDifference(g0, g1) {\n return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.SYMDIFFERENCE)\n }\n static difference(g0, g1) {\n return SnapOverlayOp.overlayOp(g0, g1, OverlayOp.DIFFERENCE)\n }\n selfSnap(geom) {\n const snapper0 = new GeometrySnapper(geom)\n const snapGeom = snapper0.snapTo(geom, this._snapTolerance)\n return snapGeom\n }\n removeCommonBits(geom) {\n this._cbr = new CommonBitsRemover()\n this._cbr.add(geom[0])\n this._cbr.add(geom[1])\n const remGeom = new Array(2).fill(null)\n remGeom[0] = this._cbr.removeCommonBits(geom[0].copy())\n remGeom[1] = this._cbr.removeCommonBits(geom[1].copy())\n return remGeom\n }\n prepareResult(geom) {\n this._cbr.addCommonBits(geom)\n return geom\n }\n getResultGeometry(opCode) {\n const prepGeom = this.snap(this._geom)\n const result = OverlayOp.overlayOp(prepGeom[0], prepGeom[1], opCode)\n return this.prepareResult(result)\n }\n checkValid(g) {\n if (!g.isValid()) \n System.out.println('Snapped geometry is invalid')\n \n }\n computeSnapTolerance() {\n this._snapTolerance = GeometrySnapper.computeOverlaySnapTolerance(this._geom[0], this._geom[1])\n }\n snap(geom) {\n const remGeom = this.removeCommonBits(geom)\n const snapGeom = GeometrySnapper.snap(remGeom[0], remGeom[1], this._snapTolerance)\n return snapGeom\n }\n}\n","import SnapOverlayOp from './SnapOverlayOp.js'\nimport RuntimeException from '../../../../../../java/lang/RuntimeException.js'\nimport OverlayOp from '../OverlayOp.js'\nexport default class SnapIfNeededOverlayOp {\n constructor() {\n SnapIfNeededOverlayOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geom = new Array(2).fill(null)\n const g1 = arguments[0], g2 = arguments[1]\n this._geom[0] = g1\n this._geom[1] = g2\n }\n static overlayOp(g0, g1, opCode) {\n const op = new SnapIfNeededOverlayOp(g0, g1)\n return op.getResultGeometry(opCode)\n }\n static union(g0, g1) {\n return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.UNION)\n }\n static intersection(g0, g1) {\n return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.INTERSECTION)\n }\n static symDifference(g0, g1) {\n return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.SYMDIFFERENCE)\n }\n static difference(g0, g1) {\n return SnapIfNeededOverlayOp.overlayOp(g0, g1, OverlayOp.DIFFERENCE)\n }\n getResultGeometry(opCode) {\n let result = null\n let isSuccess = false\n let savedException = null\n try {\n result = OverlayOp.overlayOp(this._geom[0], this._geom[1], opCode)\n const isValid = true\n if (isValid) isSuccess = true\n } catch (ex) {\n if (ex instanceof RuntimeException) \n savedException = ex\n else throw ex\n } finally {}\n if (!isSuccess) \n try {\n result = SnapOverlayOp.overlayOp(this._geom[0], this._geom[1], opCode)\n } catch (ex) {\n if (ex instanceof RuntimeException) \n throw savedException\n else throw ex\n } finally {}\n \n return result\n }\n}\n","import BoundaryNodeRule from '../algorithm/BoundaryNodeRule.js'\nimport GeometryGraph from '../geomgraph/GeometryGraph.js'\nimport RobustLineIntersector from '../algorithm/RobustLineIntersector.js'\nexport default class GeometryGraphOperation {\n constructor() {\n GeometryGraphOperation.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._li = new RobustLineIntersector()\n this._resultPrecisionModel = null\n this._arg = null\n if (arguments.length === 1) {\n const g0 = arguments[0]\n this.setComputationPrecision(g0.getPrecisionModel())\n this._arg = new Array(1).fill(null)\n this._arg[0] = new GeometryGraph(0, g0)\n \n } else if (arguments.length === 2) {\n const g0 = arguments[0], g1 = arguments[1]\n GeometryGraphOperation.constructor_.call(this, g0, g1, BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE)\n } else if (arguments.length === 3) {\n const g0 = arguments[0], g1 = arguments[1], boundaryNodeRule = arguments[2]\n if (g0.getPrecisionModel().compareTo(g1.getPrecisionModel()) >= 0) this.setComputationPrecision(g0.getPrecisionModel()); else this.setComputationPrecision(g1.getPrecisionModel())\n this._arg = new Array(2).fill(null)\n this._arg[0] = new GeometryGraph(0, g0, boundaryNodeRule)\n this._arg[1] = new GeometryGraph(1, g1, boundaryNodeRule)\n }\n }\n getArgGeometry(i) {\n return this._arg[i].getGeometry()\n }\n setComputationPrecision(pm) {\n this._resultPrecisionModel = pm\n this._li.setPrecisionModel(this._resultPrecisionModel)\n }\n}\n","import PointLocator from '../../algorithm/PointLocator.js'\nimport Location from '../../geom/Location.js'\nimport EdgeNodingValidator from '../../geomgraph/EdgeNodingValidator.js'\nimport GeometryCollectionMapper from '../../geom/util/GeometryCollectionMapper.js'\nimport PolygonBuilder from './PolygonBuilder.js'\nimport Position from '../../geomgraph/Position.js'\nimport IllegalArgumentException from '../../../../../java/lang/IllegalArgumentException.js'\nimport LineBuilder from './LineBuilder.js'\nimport PointBuilder from './PointBuilder.js'\nimport SnapIfNeededOverlayOp from './snap/SnapIfNeededOverlayOp.js'\nimport Label from '../../geomgraph/Label.js'\nimport OverlayNodeFactory from './OverlayNodeFactory.js'\nimport GeometryGraphOperation from '../GeometryGraphOperation.js'\nimport EdgeList from '../../geomgraph/EdgeList.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Assert from '../../util/Assert.js'\nimport PlanarGraph from '../../geomgraph/PlanarGraph.js'\nexport default class OverlayOp extends GeometryGraphOperation {\n constructor() {\n super()\n OverlayOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._ptLocator = new PointLocator()\n this._geomFact = null\n this._resultGeom = null\n this._graph = null\n this._edgeList = new EdgeList()\n this._resultPolyList = new ArrayList()\n this._resultLineList = new ArrayList()\n this._resultPointList = new ArrayList()\n const g0 = arguments[0], g1 = arguments[1]\n GeometryGraphOperation.constructor_.call(this, g0, g1)\n this._graph = new PlanarGraph(new OverlayNodeFactory())\n this._geomFact = g0.getFactory()\n }\n static overlayOp(geom0, geom1, opCode) {\n const gov = new OverlayOp(geom0, geom1)\n const geomOv = gov.getResultGeometry(opCode)\n return geomOv\n }\n static union(geom, other) {\n if (geom.isEmpty() || other.isEmpty()) {\n if (geom.isEmpty() && other.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.UNION, geom, other, geom.getFactory())\n if (geom.isEmpty()) return other.copy()\n if (other.isEmpty()) return geom.copy()\n }\n if (geom.isGeometryCollection() || other.isGeometryCollection()) throw new IllegalArgumentException('This method does not support GeometryCollection arguments')\n return SnapIfNeededOverlayOp.overlayOp(geom, other, OverlayOp.UNION)\n }\n static intersection(geom, other) {\n if (geom.isEmpty() || other.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.INTERSECTION, geom, other, geom.getFactory())\n if (geom.isGeometryCollection()) {\n const g2 = other\n return GeometryCollectionMapper.map(geom, new (class {\n get interfaces_() {\n return [MapOp]\n }\n map(g) {\n return OverlayOp.intersection(g, g2)\n }\n })())\n }\n return SnapIfNeededOverlayOp.overlayOp(geom, other, OverlayOp.INTERSECTION)\n }\n static symDifference(geom, other) {\n if (geom.isEmpty() || other.isEmpty()) {\n if (geom.isEmpty() && other.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.SYMDIFFERENCE, geom, other, geom.getFactory())\n if (geom.isEmpty()) return other.copy()\n if (other.isEmpty()) return geom.copy()\n }\n if (geom.isGeometryCollection() || other.isGeometryCollection()) throw new IllegalArgumentException('This method does not support GeometryCollection arguments')\n return SnapIfNeededOverlayOp.overlayOp(geom, other, OverlayOp.SYMDIFFERENCE)\n }\n static resultDimension(opCode, g0, g1) {\n const dim0 = g0.getDimension()\n const dim1 = g1.getDimension()\n let resultDimension = -1\n switch (opCode) {\n case OverlayOp.INTERSECTION:\n resultDimension = Math.min(dim0, dim1)\n break\n case OverlayOp.UNION:\n resultDimension = Math.max(dim0, dim1)\n break\n case OverlayOp.DIFFERENCE:\n resultDimension = dim0\n break\n case OverlayOp.SYMDIFFERENCE:\n resultDimension = Math.max(dim0, dim1)\n break\n }\n return resultDimension\n }\n static createEmptyResult(overlayOpCode, a, b, geomFact) {\n let result = null\n const resultDim = OverlayOp.resultDimension(overlayOpCode, a, b)\n return result = geomFact.createEmpty(resultDim)\n }\n static difference(geom, other) {\n if (geom.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.DIFFERENCE, geom, other, geom.getFactory())\n if (other.isEmpty()) return geom.copy()\n if (geom.isGeometryCollection() || other.isGeometryCollection()) throw new IllegalArgumentException('This method does not support GeometryCollection arguments')\n return SnapIfNeededOverlayOp.overlayOp(geom, other, OverlayOp.DIFFERENCE)\n }\n static isResultOfOp() {\n if (arguments.length === 2) {\n const label = arguments[0], opCode = arguments[1]\n const loc0 = label.getLocation(0)\n const loc1 = label.getLocation(1)\n return OverlayOp.isResultOfOp(loc0, loc1, opCode)\n } else if (arguments.length === 3) {\n let loc0 = arguments[0], loc1 = arguments[1], overlayOpCode = arguments[2]\n if (loc0 === Location.BOUNDARY) loc0 = Location.INTERIOR\n if (loc1 === Location.BOUNDARY) loc1 = Location.INTERIOR\n switch (overlayOpCode) {\n case OverlayOp.INTERSECTION:\n return loc0 === Location.INTERIOR && loc1 === Location.INTERIOR\n case OverlayOp.UNION:\n return loc0 === Location.INTERIOR || loc1 === Location.INTERIOR\n case OverlayOp.DIFFERENCE:\n return loc0 === Location.INTERIOR && loc1 !== Location.INTERIOR\n case OverlayOp.SYMDIFFERENCE:\n return loc0 === Location.INTERIOR && loc1 !== Location.INTERIOR || loc0 !== Location.INTERIOR && loc1 === Location.INTERIOR\n }\n return false\n }\n }\n insertUniqueEdge(e) {\n const existingEdge = this._edgeList.findEqualEdge(e)\n if (existingEdge !== null) {\n const existingLabel = existingEdge.getLabel()\n let labelToMerge = e.getLabel()\n if (!existingEdge.isPointwiseEqual(e)) {\n labelToMerge = new Label(e.getLabel())\n labelToMerge.flip()\n }\n const depth = existingEdge.getDepth()\n if (depth.isNull()) \n depth.add(existingLabel)\n \n depth.add(labelToMerge)\n existingLabel.merge(labelToMerge)\n } else {\n this._edgeList.add(e)\n }\n }\n getGraph() {\n return this._graph\n }\n cancelDuplicateResultEdges() {\n for (let it = this._graph.getEdgeEnds().iterator(); it.hasNext(); ) {\n const de = it.next()\n const sym = de.getSym()\n if (de.isInResult() && sym.isInResult()) {\n de.setInResult(false)\n sym.setInResult(false)\n }\n }\n }\n isCoveredByLA(coord) {\n if (this.isCovered(coord, this._resultLineList)) return true\n if (this.isCovered(coord, this._resultPolyList)) return true\n return false\n }\n computeGeometry(resultPointList, resultLineList, resultPolyList, opcode) {\n const geomList = new ArrayList()\n geomList.addAll(resultPointList)\n geomList.addAll(resultLineList)\n geomList.addAll(resultPolyList)\n if (geomList.isEmpty()) return OverlayOp.createEmptyResult(opcode, this._arg[0].getGeometry(), this._arg[1].getGeometry(), this._geomFact)\n return this._geomFact.buildGeometry(geomList)\n }\n mergeSymLabels() {\n for (let nodeit = this._graph.getNodes().iterator(); nodeit.hasNext(); ) {\n const node = nodeit.next()\n node.getEdges().mergeSymLabels()\n }\n }\n isCovered(coord, geomList) {\n for (let it = geomList.iterator(); it.hasNext(); ) {\n const geom = it.next()\n const loc = this._ptLocator.locate(coord, geom)\n if (loc !== Location.EXTERIOR) return true\n }\n return false\n }\n replaceCollapsedEdges() {\n const newEdges = new ArrayList()\n for (let it = this._edgeList.iterator(); it.hasNext(); ) {\n const e = it.next()\n if (e.isCollapsed()) {\n it.remove()\n newEdges.add(e.getCollapsedEdge())\n }\n }\n this._edgeList.addAll(newEdges)\n }\n updateNodeLabelling() {\n for (let nodeit = this._graph.getNodes().iterator(); nodeit.hasNext(); ) {\n const node = nodeit.next()\n const lbl = node.getEdges().getLabel()\n node.getLabel().merge(lbl)\n }\n }\n getResultGeometry(overlayOpCode) {\n this.computeOverlay(overlayOpCode)\n return this._resultGeom\n }\n insertUniqueEdges(edges) {\n for (let i = edges.iterator(); i.hasNext(); ) {\n const e = i.next()\n this.insertUniqueEdge(e)\n }\n }\n computeOverlay(opCode) {\n this.copyPoints(0)\n this.copyPoints(1)\n this._arg[0].computeSelfNodes(this._li, false)\n this._arg[1].computeSelfNodes(this._li, false)\n this._arg[0].computeEdgeIntersections(this._arg[1], this._li, true)\n const baseSplitEdges = new ArrayList()\n this._arg[0].computeSplitEdges(baseSplitEdges)\n this._arg[1].computeSplitEdges(baseSplitEdges)\n const splitEdges = baseSplitEdges\n this.insertUniqueEdges(baseSplitEdges)\n this.computeLabelsFromDepths()\n this.replaceCollapsedEdges()\n EdgeNodingValidator.checkValid(this._edgeList.getEdges())\n this._graph.addEdges(this._edgeList.getEdges())\n this.computeLabelling()\n this.labelIncompleteNodes()\n this.findResultAreaEdges(opCode)\n this.cancelDuplicateResultEdges()\n const polyBuilder = new PolygonBuilder(this._geomFact)\n polyBuilder.add(this._graph)\n this._resultPolyList = polyBuilder.getPolygons()\n const lineBuilder = new LineBuilder(this, this._geomFact, this._ptLocator)\n this._resultLineList = lineBuilder.build(opCode)\n const pointBuilder = new PointBuilder(this, this._geomFact, this._ptLocator)\n this._resultPointList = pointBuilder.build(opCode)\n this._resultGeom = this.computeGeometry(this._resultPointList, this._resultLineList, this._resultPolyList, opCode)\n }\n labelIncompleteNode(n, targetIndex) {\n const loc = this._ptLocator.locate(n.getCoordinate(), this._arg[targetIndex].getGeometry())\n n.getLabel().setLocation(targetIndex, loc)\n }\n copyPoints(argIndex) {\n for (let i = this._arg[argIndex].getNodeIterator(); i.hasNext(); ) {\n const graphNode = i.next()\n const newNode = this._graph.addNode(graphNode.getCoordinate())\n newNode.setLabel(argIndex, graphNode.getLabel().getLocation(argIndex))\n }\n }\n findResultAreaEdges(opCode) {\n for (let it = this._graph.getEdgeEnds().iterator(); it.hasNext(); ) {\n const de = it.next()\n const label = de.getLabel()\n if (label.isArea() && !de.isInteriorAreaEdge() && OverlayOp.isResultOfOp(label.getLocation(0, Position.RIGHT), label.getLocation(1, Position.RIGHT), opCode)) \n de.setInResult(true)\n \n }\n }\n computeLabelsFromDepths() {\n for (let it = this._edgeList.iterator(); it.hasNext(); ) {\n const e = it.next()\n const lbl = e.getLabel()\n const depth = e.getDepth()\n if (!depth.isNull()) {\n depth.normalize()\n for (let i = 0; i < 2; i++) \n if (!lbl.isNull(i) && lbl.isArea() && !depth.isNull(i)) \n if (depth.getDelta(i) === 0) {\n lbl.toLine(i)\n } else {\n Assert.isTrue(!depth.isNull(i, Position.LEFT), 'depth of LEFT side has not been initialized')\n lbl.setLocation(i, Position.LEFT, depth.getLocation(i, Position.LEFT))\n Assert.isTrue(!depth.isNull(i, Position.RIGHT), 'depth of RIGHT side has not been initialized')\n lbl.setLocation(i, Position.RIGHT, depth.getLocation(i, Position.RIGHT))\n }\n \n \n }\n }\n }\n computeLabelling() {\n for (let nodeit = this._graph.getNodes().iterator(); nodeit.hasNext(); ) {\n const node = nodeit.next()\n node.getEdges().computeLabelling(this._arg)\n }\n this.mergeSymLabels()\n this.updateNodeLabelling()\n }\n labelIncompleteNodes() {\n for (let ni = this._graph.getNodes().iterator(); ni.hasNext(); ) {\n const n = ni.next()\n const label = n.getLabel()\n if (n.isIsolated()) \n if (label.isNull(0)) this.labelIncompleteNode(n, 0); else this.labelIncompleteNode(n, 1)\n \n n.getEdges().updateLabelling(label)\n }\n }\n isCoveredByA(coord) {\n if (this.isCovered(coord, this._resultPolyList)) return true\n return false\n }\n}\nOverlayOp.INTERSECTION = 1\nOverlayOp.UNION = 2\nOverlayOp.DIFFERENCE = 3\nOverlayOp.SYMDIFFERENCE = 4\n","import DirectedEdge from '../../planargraph/DirectedEdge.js'\nexport default class PolygonizeDirectedEdge extends DirectedEdge {\n constructor() {\n super()\n PolygonizeDirectedEdge.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._edgeRing = null\n this._next = null\n this._label = -1\n const from = arguments[0], to = arguments[1], directionPt = arguments[2], edgeDirection = arguments[3]\n DirectedEdge.constructor_.call(this, from, to, directionPt, edgeDirection)\n }\n getNext() {\n return this._next\n }\n isInRing() {\n return this._edgeRing !== null\n }\n setRing(edgeRing) {\n this._edgeRing = edgeRing\n }\n setLabel(label) {\n this._label = label\n }\n getLabel() {\n return this._label\n }\n setNext(next) {\n this._next = next\n }\n getRing() {\n return this._edgeRing\n }\n}\n","import Edge from '../../planargraph/Edge.js'\nexport default class PolygonizeEdge extends Edge {\n constructor() {\n super()\n PolygonizeEdge.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._line = null\n const line = arguments[0]\n this._line = line\n }\n getLine() {\n return this._line\n }\n}\n","import Location from '../../geom/Location.js'\nimport GeometryFactory from '../../geom/GeometryFactory.js'\nimport Position from '../../geomgraph/Position.js'\nimport Polygon from '../../geom/Polygon.js'\nimport MultiPolygon from '../../geom/MultiPolygon.js'\nimport MaximalEdgeRing from '../overlay/MaximalEdgeRing.js'\nimport OverlayNodeFactory from '../overlay/OverlayNodeFactory.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Assert from '../../util/Assert.js'\nimport PlanarGraph from '../../geomgraph/PlanarGraph.js'\nexport default class ConnectedInteriorTester {\n constructor() {\n ConnectedInteriorTester.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geometryFactory = new GeometryFactory()\n this._geomGraph = null\n this._disconnectedRingcoord = null\n const geomGraph = arguments[0]\n this._geomGraph = geomGraph\n }\n static findDifferentPoint(coord, pt) {\n for (let i = 0; i < coord.length; i++) \n if (!coord[i].equals(pt)) return coord[i]\n \n return null\n }\n visitInteriorRing(ring, graph) {\n if (ring.isEmpty()) return null\n const pts = ring.getCoordinates()\n const pt0 = pts[0]\n const pt1 = ConnectedInteriorTester.findDifferentPoint(pts, pt0)\n const e = graph.findEdgeInSameDirection(pt0, pt1)\n const de = graph.findEdgeEnd(e)\n let intDe = null\n if (de.getLabel().getLocation(0, Position.RIGHT) === Location.INTERIOR) \n intDe = de\n else if (de.getSym().getLabel().getLocation(0, Position.RIGHT) === Location.INTERIOR) \n intDe = de.getSym()\n \n Assert.isTrue(intDe !== null, 'unable to find dirEdge with Interior on RHS')\n this.visitLinkedDirectedEdges(intDe)\n }\n visitShellInteriors(g, graph) {\n if (g instanceof Polygon) {\n const p = g\n this.visitInteriorRing(p.getExteriorRing(), graph)\n }\n if (g instanceof MultiPolygon) {\n const mp = g\n for (let i = 0; i < mp.getNumGeometries(); i++) {\n const p = mp.getGeometryN(i)\n this.visitInteriorRing(p.getExteriorRing(), graph)\n }\n }\n }\n getCoordinate() {\n return this._disconnectedRingcoord\n }\n setInteriorEdgesInResult(graph) {\n for (let it = graph.getEdgeEnds().iterator(); it.hasNext(); ) {\n const de = it.next()\n if (de.getLabel().getLocation(0, Position.RIGHT) === Location.INTERIOR) \n de.setInResult(true)\n \n }\n }\n visitLinkedDirectedEdges(start) {\n const startDe = start\n let de = start\n do {\n Assert.isTrue(de !== null, 'found null Directed Edge')\n de.setVisited(true)\n de = de.getNext()\n } while (de !== startDe)\n }\n buildEdgeRings(dirEdges) {\n const edgeRings = new ArrayList()\n for (let it = dirEdges.iterator(); it.hasNext(); ) {\n const de = it.next()\n if (de.isInResult() && de.getEdgeRing() === null) {\n const er = new MaximalEdgeRing(de, this._geometryFactory)\n er.linkDirectedEdgesForMinimalEdgeRings()\n const minEdgeRings = er.buildMinimalRings()\n edgeRings.addAll(minEdgeRings)\n }\n }\n return edgeRings\n }\n hasUnvisitedShellEdge(edgeRings) {\n for (let i = 0; i < edgeRings.size(); i++) {\n const er = edgeRings.get(i)\n if (er.isHole()) continue\n const edges = er.getEdges()\n let de = edges.get(0)\n if (de.getLabel().getLocation(0, Position.RIGHT) !== Location.INTERIOR) continue\n for (let j = 0; j < edges.size(); j++) {\n de = edges.get(j)\n if (!de.isVisited()) {\n this._disconnectedRingcoord = de.getCoordinate()\n return true\n }\n }\n }\n return false\n }\n isInteriorsConnected() {\n const splitEdges = new ArrayList()\n this._geomGraph.computeSplitEdges(splitEdges)\n const graph = new PlanarGraph(new OverlayNodeFactory())\n graph.addEdges(splitEdges)\n this.setInteriorEdgesInResult(graph)\n graph.linkResultDirectedEdges()\n const edgeRings = this.buildEdgeRings(graph.getEdgeEnds())\n this.visitShellInteriors(this._geomGraph.getGeometry(), graph)\n return !this.hasUnvisitedShellEdge(edgeRings)\n }\n}\n","import EdgeEnd from '../../geomgraph/EdgeEnd.js'\nimport Label from '../../geomgraph/Label.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nexport default class EdgeEndBuilder {\n createEdgeEndForNext(edge, l, eiCurr, eiNext) {\n const iNext = eiCurr.segmentIndex + 1\n if (iNext >= edge.getNumPoints() && eiNext === null) return null\n let pNext = edge.getCoordinate(iNext)\n if (eiNext !== null && eiNext.segmentIndex === eiCurr.segmentIndex) pNext = eiNext.coord\n const e = new EdgeEnd(edge, eiCurr.coord, pNext, new Label(edge.getLabel()))\n l.add(e)\n }\n createEdgeEndForPrev(edge, l, eiCurr, eiPrev) {\n let iPrev = eiCurr.segmentIndex\n if (eiCurr.dist === 0.0) {\n if (iPrev === 0) return null\n iPrev--\n }\n let pPrev = edge.getCoordinate(iPrev)\n if (eiPrev !== null && eiPrev.segmentIndex >= iPrev) pPrev = eiPrev.coord\n const label = new Label(edge.getLabel())\n label.flip()\n const e = new EdgeEnd(edge, eiCurr.coord, pPrev, label)\n l.add(e)\n }\n computeEdgeEnds() {\n if (arguments.length === 1) {\n const edges = arguments[0]\n const l = new ArrayList()\n for (let i = edges; i.hasNext(); ) {\n const e = i.next()\n this.computeEdgeEnds(e, l)\n }\n return l\n } else if (arguments.length === 2) {\n const edge = arguments[0], l = arguments[1]\n const eiList = edge.getEdgeIntersectionList()\n eiList.addEndpoints()\n const it = eiList.iterator()\n let eiPrev = null\n let eiCurr = null\n if (!it.hasNext()) return null\n let eiNext = it.next()\n do {\n eiPrev = eiCurr\n eiCurr = eiNext\n eiNext = null\n if (it.hasNext()) eiNext = it.next()\n if (eiCurr !== null) {\n this.createEdgeEndForPrev(edge, l, eiCurr, eiPrev)\n this.createEdgeEndForNext(edge, l, eiCurr, eiNext)\n }\n } while (eiCurr !== null)\n }\n }\n}\n","import Location from '../../geom/Location.js'\nimport EdgeEnd from '../../geomgraph/EdgeEnd.js'\nimport Position from '../../geomgraph/Position.js'\nimport GeometryGraph from '../../geomgraph/GeometryGraph.js'\nimport Label from '../../geomgraph/Label.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Edge from '../../geomgraph/Edge.js'\nexport default class EdgeEndBundle extends EdgeEnd {\n constructor() {\n super()\n EdgeEndBundle.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._edgeEnds = new ArrayList()\n if (arguments.length === 1) {\n const e = arguments[0]\n EdgeEndBundle.constructor_.call(this, null, e)\n } else if (arguments.length === 2) {\n const boundaryNodeRule = arguments[0], e = arguments[1]\n EdgeEnd.constructor_.call(this, e.getEdge(), e.getCoordinate(), e.getDirectedCoordinate(), new Label(e.getLabel()))\n this.insert(e)\n }\n }\n insert(e) {\n this._edgeEnds.add(e)\n }\n print(out) {\n out.println('EdgeEndBundle--> Label: ' + this._label)\n for (let it = this.iterator(); it.hasNext(); ) {\n const ee = it.next()\n ee.print(out)\n out.println()\n }\n }\n iterator() {\n return this._edgeEnds.iterator()\n }\n getEdgeEnds() {\n return this._edgeEnds\n }\n computeLabelOn(geomIndex, boundaryNodeRule) {\n let boundaryCount = 0\n let foundInterior = false\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n const loc = e.getLabel().getLocation(geomIndex)\n if (loc === Location.BOUNDARY) boundaryCount++\n if (loc === Location.INTERIOR) foundInterior = true\n }\n let loc = Location.NONE\n if (foundInterior) loc = Location.INTERIOR\n if (boundaryCount > 0) \n loc = GeometryGraph.determineBoundary(boundaryNodeRule, boundaryCount)\n \n this._label.setLocation(geomIndex, loc)\n }\n computeLabelSide(geomIndex, side) {\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n if (e.getLabel().isArea()) {\n const loc = e.getLabel().getLocation(geomIndex, side)\n if (loc === Location.INTERIOR) {\n this._label.setLocation(geomIndex, side, Location.INTERIOR)\n return null\n } else if (loc === Location.EXTERIOR) {\n this._label.setLocation(geomIndex, side, Location.EXTERIOR)\n }\n }\n }\n }\n getLabel() {\n return this._label\n }\n computeLabelSides(geomIndex) {\n this.computeLabelSide(geomIndex, Position.LEFT)\n this.computeLabelSide(geomIndex, Position.RIGHT)\n }\n updateIM(im) {\n Edge.updateIM(this._label, im)\n }\n computeLabel(boundaryNodeRule) {\n let isArea = false\n for (let it = this.iterator(); it.hasNext(); ) {\n const e = it.next()\n if (e.getLabel().isArea()) isArea = true\n }\n if (isArea) this._label = new Label(Location.NONE, Location.NONE, Location.NONE); else this._label = new Label(Location.NONE)\n for (let i = 0; i < 2; i++) {\n this.computeLabelOn(i, boundaryNodeRule)\n if (isArea) this.computeLabelSides(i)\n }\n }\n}\n","import EdgeEndStar from '../../geomgraph/EdgeEndStar.js'\nimport EdgeEndBundle from './EdgeEndBundle.js'\nexport default class EdgeEndBundleStar extends EdgeEndStar {\n constructor() {\n super()\n }\n updateIM(im) {\n for (let it = this.iterator(); it.hasNext(); ) {\n const esb = it.next()\n esb.updateIM(im)\n }\n }\n insert(e) {\n let eb = this._edgeMap.get(e)\n if (eb === null) {\n eb = new EdgeEndBundle(e)\n this.insertEdgeEnd(e, eb)\n } else {\n eb.insert(e)\n }\n }\n}\n","import Node from '../../geomgraph/Node.js'\nexport default class RelateNode extends Node {\n constructor() {\n super()\n RelateNode.constructor_.apply(this, arguments)\n }\n static constructor_() {\n const coord = arguments[0], edges = arguments[1]\n Node.constructor_.call(this, coord, edges)\n }\n updateIMFromEdges(im) {\n this._edges.updateIM(im)\n }\n computeIM(im) {\n im.setAtLeastIfValid(this._label.getLocation(0), this._label.getLocation(1), 0)\n }\n}\n","import EdgeEndBundleStar from './EdgeEndBundleStar.js'\nimport RelateNode from './RelateNode.js'\nimport NodeFactory from '../../geomgraph/NodeFactory.js'\nexport default class RelateNodeFactory extends NodeFactory {\n constructor() {\n super()\n }\n createNode(coord) {\n return new RelateNode(coord, new EdgeEndBundleStar())\n }\n}\n","import Location from '../../geom/Location.js'\nimport EdgeEndBuilder from './EdgeEndBuilder.js'\nimport NodeMap from '../../geomgraph/NodeMap.js'\nimport RelateNodeFactory from './RelateNodeFactory.js'\nexport default class RelateNodeGraph {\n constructor() {\n RelateNodeGraph.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._nodes = new NodeMap(new RelateNodeFactory())\n }\n insertEdgeEnds(ee) {\n for (let i = ee.iterator(); i.hasNext(); ) {\n const e = i.next()\n this._nodes.add(e)\n }\n }\n getNodeIterator() {\n return this._nodes.iterator()\n }\n copyNodesAndLabels(geomGraph, argIndex) {\n for (let nodeIt = geomGraph.getNodeIterator(); nodeIt.hasNext(); ) {\n const graphNode = nodeIt.next()\n const newNode = this._nodes.addNode(graphNode.getCoordinate())\n newNode.setLabel(argIndex, graphNode.getLabel().getLocation(argIndex))\n }\n }\n build(geomGraph) {\n this.computeIntersectionNodes(geomGraph, 0)\n this.copyNodesAndLabels(geomGraph, 0)\n const eeBuilder = new EdgeEndBuilder()\n const eeList = eeBuilder.computeEdgeEnds(geomGraph.getEdgeIterator())\n this.insertEdgeEnds(eeList)\n }\n computeIntersectionNodes(geomGraph, argIndex) {\n for (let edgeIt = geomGraph.getEdgeIterator(); edgeIt.hasNext(); ) {\n const e = edgeIt.next()\n const eLoc = e.getLabel().getLocation(argIndex)\n for (let eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) {\n const ei = eiIt.next()\n const n = this._nodes.addNode(ei.coord)\n if (eLoc === Location.BOUNDARY) n.setLabelBoundary(argIndex); else \n if (n.getLabel().isNull(argIndex)) n.setLabel(argIndex, Location.INTERIOR)\n \n }\n }\n }\n}\n","import RelateNodeGraph from '../relate/RelateNodeGraph.js'\nimport RobustLineIntersector from '../../algorithm/RobustLineIntersector.js'\nexport default class ConsistentAreaTester {\n constructor() {\n ConsistentAreaTester.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._li = new RobustLineIntersector()\n this._geomGraph = null\n this._nodeGraph = new RelateNodeGraph()\n this._invalidPoint = null\n const geomGraph = arguments[0]\n this._geomGraph = geomGraph\n }\n isNodeEdgeAreaLabelsConsistent() {\n for (let nodeIt = this._nodeGraph.getNodeIterator(); nodeIt.hasNext(); ) {\n const node = nodeIt.next()\n if (!node.getEdges().isAreaLabelsConsistent(this._geomGraph)) {\n this._invalidPoint = node.getCoordinate().copy()\n return false\n }\n }\n return true\n }\n getInvalidPoint() {\n return this._invalidPoint\n }\n hasDuplicateRings() {\n for (let nodeIt = this._nodeGraph.getNodeIterator(); nodeIt.hasNext(); ) {\n const node = nodeIt.next()\n for (let i = node.getEdges().iterator(); i.hasNext(); ) {\n const eeb = i.next()\n if (eeb.getEdgeEnds().size() > 1) {\n this._invalidPoint = eeb.getEdge().getCoordinate(0)\n return true\n }\n }\n }\n return false\n }\n isNodeConsistentArea() {\n const intersector = this._geomGraph.computeSelfNodes(this._li, true, true)\n if (intersector.hasProperIntersection()) {\n this._invalidPoint = intersector.getProperIntersectionPoint()\n return false\n }\n this._nodeGraph.build(this._geomGraph)\n return this.isNodeEdgeAreaLabelsConsistent()\n }\n}\n","import STRtree from '../../index/strtree/STRtree.js'\nimport IsValidOp from './IsValidOp.js'\nimport PointLocation from '../../algorithm/PointLocation.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Envelope from '../../geom/Envelope.js'\nexport default class IndexedNestedRingTester {\n constructor() {\n IndexedNestedRingTester.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._graph = null\n this._rings = new ArrayList()\n this._totalEnv = new Envelope()\n this._index = null\n this._nestedPt = null\n const graph = arguments[0]\n this._graph = graph\n }\n buildIndex() {\n this._index = new STRtree()\n for (let i = 0; i < this._rings.size(); i++) {\n const ring = this._rings.get(i)\n const env = ring.getEnvelopeInternal()\n this._index.insert(env, ring)\n }\n }\n getNestedPoint() {\n return this._nestedPt\n }\n isNonNested() {\n this.buildIndex()\n for (let i = 0; i < this._rings.size(); i++) {\n const innerRing = this._rings.get(i)\n const innerRingPts = innerRing.getCoordinates()\n const results = this._index.query(innerRing.getEnvelopeInternal())\n for (let j = 0; j < results.size(); j++) {\n const searchRing = results.get(j)\n const searchRingPts = searchRing.getCoordinates()\n if (innerRing === searchRing) continue\n if (!innerRing.getEnvelopeInternal().intersects(searchRing.getEnvelopeInternal())) continue\n const innerRingPt = IsValidOp.findPtNotNode(innerRingPts, searchRing, this._graph)\n if (innerRingPt === null) continue\n const isInside = PointLocation.isInRing(innerRingPt, searchRingPts)\n if (isInside) {\n this._nestedPt = innerRingPt\n return false\n }\n }\n }\n return true\n }\n add(ring) {\n this._rings.add(ring)\n this._totalEnv.expandToInclude(ring.getEnvelopeInternal())\n }\n}\n","export default class TopologyValidationError {\n constructor() {\n TopologyValidationError.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._errorType = null\n this._pt = null\n if (arguments.length === 1) {\n const errorType = arguments[0]\n TopologyValidationError.constructor_.call(this, errorType, null)\n } else if (arguments.length === 2) {\n const errorType = arguments[0], pt = arguments[1]\n this._errorType = errorType\n if (pt !== null) this._pt = pt.copy()\n }\n }\n getErrorType() {\n return this._errorType\n }\n getMessage() {\n return TopologyValidationError.errMsg[this._errorType]\n }\n getCoordinate() {\n return this._pt\n }\n toString() {\n let locStr = ''\n if (this._pt !== null) locStr = ' at or near point ' + this._pt\n return this.getMessage() + locStr\n }\n}\nTopologyValidationError.ERROR = 0\nTopologyValidationError.REPEATED_POINT = 1\nTopologyValidationError.HOLE_OUTSIDE_SHELL = 2\nTopologyValidationError.NESTED_HOLES = 3\nTopologyValidationError.DISCONNECTED_INTERIOR = 4\nTopologyValidationError.SELF_INTERSECTION = 5\nTopologyValidationError.RING_SELF_INTERSECTION = 6\nTopologyValidationError.NESTED_SHELLS = 7\nTopologyValidationError.DUPLICATE_RINGS = 8\nTopologyValidationError.TOO_FEW_POINTS = 9\nTopologyValidationError.INVALID_COORDINATE = 10\nTopologyValidationError.RING_NOT_CLOSED = 11\nTopologyValidationError.errMsg = ['Topology Validation Error', 'Repeated Point', 'Hole lies outside shell', 'Holes are nested', 'Interior is disconnected', 'Self-intersection', 'Ring Self-intersection', 'Nested shells', 'Duplicate Rings', 'Too few distinct points in geometry component', 'Invalid Coordinate', 'Ring is not closed']\n","import Location from '../../geom/Location.js'\nimport TreeSet from '../../../../../java/util/TreeSet.js'\nimport LineString from '../../geom/LineString.js'\nimport Geometry from '../../geom/Geometry.js'\nimport ConnectedInteriorTester from './ConnectedInteriorTester.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport Point from '../../geom/Point.js'\nimport Polygon from '../../geom/Polygon.js'\nimport MultiPoint from '../../geom/MultiPoint.js'\nimport PointLocation from '../../algorithm/PointLocation.js'\nimport LinearRing from '../../geom/LinearRing.js'\nimport Double from '../../../../../java/lang/Double.js'\nimport GeometryGraph from '../../geomgraph/GeometryGraph.js'\nimport MultiPolygon from '../../geom/MultiPolygon.js'\nimport ConsistentAreaTester from './ConsistentAreaTester.js'\nimport GeometryCollection from '../../geom/GeometryCollection.js'\nimport UnsupportedOperationException from '../../../../../java/lang/UnsupportedOperationException.js'\nimport IndexedNestedRingTester from './IndexedNestedRingTester.js'\nimport RobustLineIntersector from '../../algorithm/RobustLineIntersector.js'\nimport TopologyValidationError from './TopologyValidationError.js'\nimport IndexedPointInAreaLocator from '../../algorithm/locate/IndexedPointInAreaLocator.js'\nimport Assert from '../../util/Assert.js'\nexport default class IsValidOp {\n constructor() {\n IsValidOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._parentGeometry = null\n this._isSelfTouchingRingFormingHoleValid = false\n this._validErr = null\n const parentGeometry = arguments[0]\n this._parentGeometry = parentGeometry\n }\n static findPtNotNode(testCoords, searchRing, graph) {\n const searchEdge = graph.findEdge(searchRing)\n const eiList = searchEdge.getEdgeIntersectionList()\n for (let i = 0; i < testCoords.length; i++) {\n const pt = testCoords[i]\n if (!eiList.isIntersection(pt)) return pt\n }\n return null\n }\n static isValid() {\n if (arguments[0] instanceof Geometry) {\n const geom = arguments[0]\n const isValidOp = new IsValidOp(geom)\n return isValidOp.isValid()\n } else if (arguments[0] instanceof Coordinate) {\n const coord = arguments[0]\n if (Double.isNaN(coord.x)) return false\n if (Double.isInfinite(coord.x)) return false\n if (Double.isNaN(coord.y)) return false\n if (Double.isInfinite(coord.y)) return false\n return true\n }\n }\n checkInvalidCoordinates() {\n if (arguments[0] instanceof Array) {\n const coords = arguments[0]\n for (let i = 0; i < coords.length; i++) \n if (!IsValidOp.isValid(coords[i])) {\n this._validErr = new TopologyValidationError(TopologyValidationError.INVALID_COORDINATE, coords[i])\n return null\n }\n \n } else if (arguments[0] instanceof Polygon) {\n const poly = arguments[0]\n this.checkInvalidCoordinates(poly.getExteriorRing().getCoordinates())\n if (this._validErr !== null) return null\n for (let i = 0; i < poly.getNumInteriorRing(); i++) {\n this.checkInvalidCoordinates(poly.getInteriorRingN(i).getCoordinates())\n if (this._validErr !== null) return null\n }\n }\n }\n checkHolesNotNested(p, graph) {\n if (p.getNumInteriorRing() <= 0) return null\n const nestedTester = new IndexedNestedRingTester(graph)\n for (let i = 0; i < p.getNumInteriorRing(); i++) {\n const innerHole = p.getInteriorRingN(i)\n if (innerHole.isEmpty()) continue\n nestedTester.add(innerHole)\n }\n const isNonNested = nestedTester.isNonNested()\n if (!isNonNested) \n this._validErr = new TopologyValidationError(TopologyValidationError.NESTED_HOLES, nestedTester.getNestedPoint())\n \n }\n checkConsistentArea(graph) {\n const cat = new ConsistentAreaTester(graph)\n const isValidArea = cat.isNodeConsistentArea()\n if (!isValidArea) {\n this._validErr = new TopologyValidationError(TopologyValidationError.SELF_INTERSECTION, cat.getInvalidPoint())\n return null\n }\n if (cat.hasDuplicateRings()) \n this._validErr = new TopologyValidationError(TopologyValidationError.DUPLICATE_RINGS, cat.getInvalidPoint())\n \n }\n isValid() {\n this.checkValid(this._parentGeometry)\n return this._validErr === null\n }\n checkShellInsideHole(shell, hole, graph) {\n const shellPts = shell.getCoordinates()\n const holePts = hole.getCoordinates()\n const shellPt = IsValidOp.findPtNotNode(shellPts, hole, graph)\n if (shellPt !== null) {\n const insideHole = PointLocation.isInRing(shellPt, holePts)\n if (!insideHole) \n return shellPt\n \n }\n const holePt = IsValidOp.findPtNotNode(holePts, shell, graph)\n if (holePt !== null) {\n const insideShell = PointLocation.isInRing(holePt, shellPts)\n if (insideShell) \n return holePt\n \n return null\n }\n Assert.shouldNeverReachHere('points in shell and hole appear to be equal')\n return null\n }\n checkNoSelfIntersectingRings(graph) {\n for (let i = graph.getEdgeIterator(); i.hasNext(); ) {\n const e = i.next()\n this.checkNoSelfIntersectingRing(e.getEdgeIntersectionList())\n if (this._validErr !== null) return null\n }\n }\n checkConnectedInteriors(graph) {\n const cit = new ConnectedInteriorTester(graph)\n if (!cit.isInteriorsConnected()) this._validErr = new TopologyValidationError(TopologyValidationError.DISCONNECTED_INTERIOR, cit.getCoordinate())\n }\n checkNoSelfIntersectingRing(eiList) {\n const nodeSet = new TreeSet()\n let isFirst = true\n for (let i = eiList.iterator(); i.hasNext(); ) {\n const ei = i.next()\n if (isFirst) {\n isFirst = false\n continue\n }\n if (nodeSet.contains(ei.coord)) {\n this._validErr = new TopologyValidationError(TopologyValidationError.RING_SELF_INTERSECTION, ei.coord)\n return null\n } else {\n nodeSet.add(ei.coord)\n }\n }\n }\n checkHolesInShell(p, graph) {\n if (p.getNumInteriorRing() <= 0) return null\n const shell = p.getExteriorRing()\n const isShellEmpty = shell.isEmpty()\n const pir = new IndexedPointInAreaLocator(shell)\n for (let i = 0; i < p.getNumInteriorRing(); i++) {\n const hole = p.getInteriorRingN(i)\n let holePt = null\n if (hole.isEmpty()) continue\n holePt = IsValidOp.findPtNotNode(hole.getCoordinates(), shell, graph)\n if (holePt === null) return null\n const outside = isShellEmpty || Location.EXTERIOR === pir.locate(holePt)\n if (outside) {\n this._validErr = new TopologyValidationError(TopologyValidationError.HOLE_OUTSIDE_SHELL, holePt)\n return null\n }\n }\n }\n checkTooFewPoints(graph) {\n if (graph.hasTooFewPoints()) {\n this._validErr = new TopologyValidationError(TopologyValidationError.TOO_FEW_POINTS, graph.getInvalidPoint())\n return null\n }\n }\n getValidationError() {\n this.checkValid(this._parentGeometry)\n return this._validErr\n }\n checkValid() {\n if (arguments[0] instanceof Point) {\n const g = arguments[0]\n this.checkInvalidCoordinates(g.getCoordinates())\n } else if (arguments[0] instanceof MultiPoint) {\n const g = arguments[0]\n this.checkInvalidCoordinates(g.getCoordinates())\n } else if (arguments[0] instanceof LinearRing) {\n const g = arguments[0]\n this.checkInvalidCoordinates(g.getCoordinates())\n if (this._validErr !== null) return null\n this.checkClosedRing(g)\n if (this._validErr !== null) return null\n const graph = new GeometryGraph(0, g)\n this.checkTooFewPoints(graph)\n if (this._validErr !== null) return null\n const li = new RobustLineIntersector()\n graph.computeSelfNodes(li, true, true)\n this.checkNoSelfIntersectingRings(graph)\n } else if (arguments[0] instanceof LineString) {\n const g = arguments[0]\n this.checkInvalidCoordinates(g.getCoordinates())\n if (this._validErr !== null) return null\n const graph = new GeometryGraph(0, g)\n this.checkTooFewPoints(graph)\n } else if (arguments[0] instanceof Polygon) {\n const g = arguments[0]\n this.checkInvalidCoordinates(g)\n if (this._validErr !== null) return null\n this.checkClosedRings(g)\n if (this._validErr !== null) return null\n const graph = new GeometryGraph(0, g)\n this.checkTooFewPoints(graph)\n if (this._validErr !== null) return null\n this.checkConsistentArea(graph)\n if (this._validErr !== null) return null\n if (!this._isSelfTouchingRingFormingHoleValid) {\n this.checkNoSelfIntersectingRings(graph)\n if (this._validErr !== null) return null\n }\n this.checkHolesInShell(g, graph)\n if (this._validErr !== null) return null\n this.checkHolesNotNested(g, graph)\n if (this._validErr !== null) return null\n this.checkConnectedInteriors(graph)\n } else if (arguments[0] instanceof MultiPolygon) {\n const g = arguments[0]\n for (let i = 0; i < g.getNumGeometries(); i++) {\n const p = g.getGeometryN(i)\n this.checkInvalidCoordinates(p)\n if (this._validErr !== null) return null\n this.checkClosedRings(p)\n if (this._validErr !== null) return null\n }\n const graph = new GeometryGraph(0, g)\n this.checkTooFewPoints(graph)\n if (this._validErr !== null) return null\n this.checkConsistentArea(graph)\n if (this._validErr !== null) return null\n if (!this._isSelfTouchingRingFormingHoleValid) {\n this.checkNoSelfIntersectingRings(graph)\n if (this._validErr !== null) return null\n }\n for (let i = 0; i < g.getNumGeometries(); i++) {\n const p = g.getGeometryN(i)\n this.checkHolesInShell(p, graph)\n if (this._validErr !== null) return null\n }\n for (let i = 0; i < g.getNumGeometries(); i++) {\n const p = g.getGeometryN(i)\n this.checkHolesNotNested(p, graph)\n if (this._validErr !== null) return null\n }\n this.checkShellsNotNested(g, graph)\n if (this._validErr !== null) return null\n this.checkConnectedInteriors(graph)\n } else if (arguments[0] instanceof GeometryCollection) {\n const gc = arguments[0]\n for (let i = 0; i < gc.getNumGeometries(); i++) {\n const g = gc.getGeometryN(i)\n this.checkValid(g)\n if (this._validErr !== null) return null\n }\n } else if (arguments[0] instanceof Geometry) {\n const g = arguments[0]\n this._validErr = null\n if (g.isEmpty()) return null\n if (g instanceof Point) this.checkValid(g); else if (g instanceof MultiPoint) this.checkValid(g); else if (g instanceof LinearRing) this.checkValid(g); else if (g instanceof LineString) this.checkValid(g); else if (g instanceof Polygon) this.checkValid(g); else if (g instanceof MultiPolygon) this.checkValid(g); else if (g instanceof GeometryCollection) this.checkValid(g); else throw new UnsupportedOperationException(g.getGeometryType())\n }\n }\n setSelfTouchingRingFormingHoleValid(isValid) {\n this._isSelfTouchingRingFormingHoleValid = isValid\n }\n checkShellNotNested(shell, p, graph) {\n const shellPts = shell.getCoordinates()\n const polyShell = p.getExteriorRing()\n if (polyShell.isEmpty()) return null\n const polyPts = polyShell.getCoordinates()\n const shellPt = IsValidOp.findPtNotNode(shellPts, polyShell, graph)\n if (shellPt === null) return null\n const insidePolyShell = PointLocation.isInRing(shellPt, polyPts)\n if (!insidePolyShell) return null\n if (p.getNumInteriorRing() <= 0) {\n this._validErr = new TopologyValidationError(TopologyValidationError.NESTED_SHELLS, shellPt)\n return null\n }\n let badNestedPt = null\n for (let i = 0; i < p.getNumInteriorRing(); i++) {\n const hole = p.getInteriorRingN(i)\n badNestedPt = this.checkShellInsideHole(shell, hole, graph)\n if (badNestedPt === null) return null\n }\n this._validErr = new TopologyValidationError(TopologyValidationError.NESTED_SHELLS, badNestedPt)\n }\n checkClosedRings(poly) {\n this.checkClosedRing(poly.getExteriorRing())\n if (this._validErr !== null) return null\n for (let i = 0; i < poly.getNumInteriorRing(); i++) {\n this.checkClosedRing(poly.getInteriorRingN(i))\n if (this._validErr !== null) return null\n }\n }\n checkClosedRing(ring) {\n if (ring.isEmpty()) return null\n if (!ring.isClosed()) {\n let pt = null\n if (ring.getNumPoints() >= 1) pt = ring.getCoordinateN(0)\n this._validErr = new TopologyValidationError(TopologyValidationError.RING_NOT_CLOSED, pt)\n }\n }\n checkShellsNotNested(mp, graph) {\n for (let i = 0; i < mp.getNumGeometries(); i++) {\n const p = mp.getGeometryN(i)\n const shell = p.getExteriorRing()\n for (let j = 0; j < mp.getNumGeometries(); j++) {\n if (i === j) continue\n const p2 = mp.getGeometryN(j)\n this.checkShellNotNested(shell, p2, graph)\n if (this._validErr !== null) return null\n }\n }\n }\n}\n","import Location from '../../geom/Location.js'\nimport CoordinateList from '../../geom/CoordinateList.js'\nimport WKTWriter from '../../io/WKTWriter.js'\nimport CoordinateArraySequence from '../../geom/impl/CoordinateArraySequence.js'\nimport IsValidOp from '../valid/IsValidOp.js'\nimport LinearRing from '../../geom/LinearRing.js'\nimport Exception from '../../../../../java/lang/Exception.js'\nimport Orientation from '../../algorithm/Orientation.js'\nimport System from '../../../../../java/lang/System.js'\nimport CoordinateArrays from '../../geom/CoordinateArrays.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Comparator from '../../../../../java/util/Comparator.js'\nimport IndexedPointInAreaLocator from '../../algorithm/locate/IndexedPointInAreaLocator.js'\nimport Assert from '../../util/Assert.js'\nexport default class EdgeRing {\n constructor() {\n EdgeRing.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._factory = null\n this._deList = new ArrayList()\n this._lowestEdge = null\n this._ring = null\n this._locator = null\n this._ringPts = null\n this._holes = null\n this._shell = null\n this._isHole = null\n this._isProcessed = false\n this._isIncludedSet = false\n this._isIncluded = false\n const factory = arguments[0]\n this._factory = factory\n }\n static findDirEdgesInRing(startDE) {\n let de = startDE\n const edges = new ArrayList()\n do {\n edges.add(de)\n de = de.getNext()\n Assert.isTrue(de !== null, 'found null DE in ring')\n Assert.isTrue(de === startDE || !de.isInRing(), 'found DE already in ring')\n } while (de !== startDE)\n return edges\n }\n static addEdge(coords, isForward, coordList) {\n if (isForward) \n for (let i = 0; i < coords.length; i++) \n coordList.add(coords[i], false)\n \n else \n for (let i = coords.length - 1; i >= 0; i--) \n coordList.add(coords[i], false)\n \n \n }\n static findEdgeRingContaining(testEr, erList) {\n const testRing = testEr.getRing()\n const testEnv = testRing.getEnvelopeInternal()\n let testPt = testRing.getCoordinateN(0)\n let minRing = null\n let minRingEnv = null\n for (let it = erList.iterator(); it.hasNext(); ) {\n const tryEdgeRing = it.next()\n const tryRing = tryEdgeRing.getRing()\n const tryShellEnv = tryRing.getEnvelopeInternal()\n if (tryShellEnv.equals(testEnv)) continue\n if (!tryShellEnv.contains(testEnv)) continue\n testPt = CoordinateArrays.ptNotInList(testRing.getCoordinates(), tryEdgeRing.getCoordinates())\n const isContained = tryEdgeRing.isInRing(testPt)\n if (isContained) \n if (minRing === null || minRingEnv.contains(tryShellEnv)) {\n minRing = tryEdgeRing\n minRingEnv = minRing.getRing().getEnvelopeInternal()\n }\n \n }\n return minRing\n }\n isIncluded() {\n return this._isIncluded\n }\n getCoordinates() {\n if (this._ringPts === null) {\n const coordList = new CoordinateList()\n for (let i = this._deList.iterator(); i.hasNext(); ) {\n const de = i.next()\n const edge = de.getEdge()\n EdgeRing.addEdge(edge.getLine().getCoordinates(), de.getEdgeDirection(), coordList)\n }\n this._ringPts = coordList.toCoordinateArray()\n }\n return this._ringPts\n }\n isIncludedSet() {\n return this._isIncludedSet\n }\n isValid() {\n this.getCoordinates()\n if (this._ringPts.length <= 3) return false\n this.getRing()\n return IsValidOp.isValid(this._ring)\n }\n build(startDE) {\n let de = startDE\n do {\n this.add(de)\n de.setRing(this)\n de = de.getNext()\n Assert.isTrue(de !== null, 'found null DE in ring')\n Assert.isTrue(de === startDE || !de.isInRing(), 'found DE already in ring')\n } while (de !== startDE)\n }\n isInRing(pt) {\n return Location.EXTERIOR !== this.getLocator().locate(pt)\n }\n isOuterHole() {\n if (!this._isHole) return false\n return !this.hasShell()\n }\n getPolygon() {\n let holeLR = null\n if (this._holes !== null) {\n holeLR = new Array(this._holes.size()).fill(null)\n for (let i = 0; i < this._holes.size(); i++) \n holeLR[i] = this._holes.get(i)\n \n }\n const poly = this._factory.createPolygon(this._ring, holeLR)\n return poly\n }\n isHole() {\n return this._isHole\n }\n isProcessed() {\n return this._isProcessed\n }\n addHole() {\n if (arguments[0] instanceof LinearRing) {\n const hole = arguments[0]\n if (this._holes === null) this._holes = new ArrayList()\n this._holes.add(hole)\n } else if (arguments[0] instanceof EdgeRing) {\n const holeER = arguments[0]\n holeER.setShell(this)\n const hole = holeER.getRing()\n if (this._holes === null) this._holes = new ArrayList()\n this._holes.add(hole)\n }\n }\n setIncluded(isIncluded) {\n this._isIncluded = isIncluded\n this._isIncludedSet = true\n }\n getOuterHole() {\n if (this.isHole()) return null\n for (let i = 0; i < this._deList.size(); i++) {\n const de = this._deList.get(i)\n const adjRing = de.getSym().getRing()\n if (adjRing.isOuterHole()) return adjRing\n }\n return null\n }\n computeHole() {\n const ring = this.getRing()\n this._isHole = Orientation.isCCW(ring.getCoordinates())\n }\n hasShell() {\n return this._shell !== null\n }\n isOuterShell() {\n return this.getOuterHole() !== null\n }\n getLineString() {\n this.getCoordinates()\n return this._factory.createLineString(this._ringPts)\n }\n toString() {\n return WKTWriter.toLineString(new CoordinateArraySequence(this.getCoordinates()))\n }\n getLocator() {\n if (this._locator === null) \n this._locator = new IndexedPointInAreaLocator(this.getRing())\n \n return this._locator\n }\n getShell() {\n if (this.isHole()) return this._shell\n return this\n }\n add(de) {\n this._deList.add(de)\n }\n getRing() {\n if (this._ring !== null) return this._ring\n this.getCoordinates()\n if (this._ringPts.length < 3) System.out.println(this._ringPts)\n try {\n this._ring = this._factory.createLinearRing(this._ringPts)\n } catch (ex) {\n if (ex instanceof Exception) \n System.out.println(this._ringPts)\n else throw ex\n } finally {}\n return this._ring\n }\n updateIncluded() {\n if (this.isHole()) return null\n for (let i = 0; i < this._deList.size(); i++) {\n const de = this._deList.get(i)\n const adjShell = de.getSym().getRing().getShell()\n if (adjShell !== null && adjShell.isIncludedSet()) {\n this.setIncluded(!adjShell.isIncluded())\n return null\n }\n }\n }\n setShell(shell) {\n this._shell = shell\n }\n setProcessed(isProcessed) {\n this._isProcessed = isProcessed\n }\n}\nclass EnvelopeComparator {\n compare(obj0, obj1) {\n const r0 = obj0\n const r1 = obj1\n return r0.getRing().getEnvelope().compareTo(r1.getRing().getEnvelope())\n }\n get interfaces_() {\n return [Comparator]\n }\n}\nEdgeRing.EnvelopeComparator = EnvelopeComparator\n","import PolygonizeDirectedEdge from './PolygonizeDirectedEdge.js'\nimport HashSet from '../../../../../java/util/HashSet.js'\nimport Stack from '../../../../../java/util/Stack.js'\nimport Node from '../../planargraph/Node.js'\nimport PolygonizeEdge from './PolygonizeEdge.js'\nimport EdgeRing from './EdgeRing.js'\nimport CoordinateArrays from '../../geom/CoordinateArrays.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Assert from '../../util/Assert.js'\nimport PlanarGraph from '../../planargraph/PlanarGraph.js'\nexport default class PolygonizeGraph extends PlanarGraph {\n constructor() {\n super()\n PolygonizeGraph.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._factory = null\n const factory = arguments[0]\n this._factory = factory\n }\n static findLabeledEdgeRings(dirEdges) {\n const edgeRingStarts = new ArrayList()\n let currLabel = 1\n for (let i = dirEdges.iterator(); i.hasNext(); ) {\n const de = i.next()\n if (de.isMarked()) continue\n if (de.getLabel() >= 0) continue\n edgeRingStarts.add(de)\n const edges = EdgeRing.findDirEdgesInRing(de)\n PolygonizeGraph.label(edges, currLabel)\n currLabel++\n }\n return edgeRingStarts\n }\n static getDegreeNonDeleted(node) {\n const edges = node.getOutEdges().getEdges()\n let degree = 0\n for (let i = edges.iterator(); i.hasNext(); ) {\n const de = i.next()\n if (!de.isMarked()) degree++\n }\n return degree\n }\n static deleteAllEdges(node) {\n const edges = node.getOutEdges().getEdges()\n for (let i = edges.iterator(); i.hasNext(); ) {\n const de = i.next()\n de.setMarked(true)\n const sym = de.getSym()\n if (sym !== null) sym.setMarked(true)\n }\n }\n static label(dirEdges, label) {\n for (let i = dirEdges.iterator(); i.hasNext(); ) {\n const de = i.next()\n de.setLabel(label)\n }\n }\n static computeNextCWEdges(node) {\n const deStar = node.getOutEdges()\n let startDE = null\n let prevDE = null\n for (let i = deStar.getEdges().iterator(); i.hasNext(); ) {\n const outDE = i.next()\n if (outDE.isMarked()) continue\n if (startDE === null) startDE = outDE\n if (prevDE !== null) {\n const sym = prevDE.getSym()\n sym.setNext(outDE)\n }\n prevDE = outDE\n }\n if (prevDE !== null) {\n const sym = prevDE.getSym()\n sym.setNext(startDE)\n }\n }\n static computeNextCCWEdges(node, label) {\n const deStar = node.getOutEdges()\n let firstOutDE = null\n let prevInDE = null\n const edges = deStar.getEdges()\n for (let i = edges.size() - 1; i >= 0; i--) {\n const de = edges.get(i)\n const sym = de.getSym()\n let outDE = null\n if (de.getLabel() === label) outDE = de\n let inDE = null\n if (sym.getLabel() === label) inDE = sym\n if (outDE === null && inDE === null) continue\n if (inDE !== null) \n prevInDE = inDE\n \n if (outDE !== null) {\n if (prevInDE !== null) {\n prevInDE.setNext(outDE)\n prevInDE = null\n }\n if (firstOutDE === null) firstOutDE = outDE\n }\n }\n if (prevInDE !== null) {\n Assert.isTrue(firstOutDE !== null)\n prevInDE.setNext(firstOutDE)\n }\n }\n static getDegree(node, label) {\n const edges = node.getOutEdges().getEdges()\n let degree = 0\n for (let i = edges.iterator(); i.hasNext(); ) {\n const de = i.next()\n if (de.getLabel() === label) degree++\n }\n return degree\n }\n static findIntersectionNodes(startDE, label) {\n let de = startDE\n let intNodes = null\n do {\n const node = de.getFromNode()\n if (PolygonizeGraph.getDegree(node, label) > 1) {\n if (intNodes === null) intNodes = new ArrayList()\n intNodes.add(node)\n }\n de = de.getNext()\n Assert.isTrue(de !== null, 'found null DE in ring')\n Assert.isTrue(de === startDE || !de.isInRing(), 'found DE already in ring')\n } while (de !== startDE)\n return intNodes\n }\n findEdgeRing(startDE) {\n const er = new EdgeRing(this._factory)\n er.build(startDE)\n return er\n }\n computeDepthParity() {\n if (arguments.length === 0) {\n while (true) {\n const de = null\n if (de === null) return null\n this.computeDepthParity(de)\n }\n } else if (arguments.length === 1) {\n const de = arguments[0]\n }\n }\n computeNextCWEdges() {\n for (let iNode = this.nodeIterator(); iNode.hasNext(); ) {\n const node = iNode.next()\n PolygonizeGraph.computeNextCWEdges(node)\n }\n }\n addEdge(line) {\n if (line.isEmpty()) \n return null\n \n const linePts = CoordinateArrays.removeRepeatedPoints(line.getCoordinates())\n if (linePts.length < 2) \n return null\n \n const startPt = linePts[0]\n const endPt = linePts[linePts.length - 1]\n const nStart = this.getNode(startPt)\n const nEnd = this.getNode(endPt)\n const de0 = new PolygonizeDirectedEdge(nStart, nEnd, linePts[1], true)\n const de1 = new PolygonizeDirectedEdge(nEnd, nStart, linePts[linePts.length - 2], false)\n const edge = new PolygonizeEdge(line)\n edge.setDirectedEdges(de0, de1)\n this.add(edge)\n }\n deleteCutEdges() {\n this.computeNextCWEdges()\n PolygonizeGraph.findLabeledEdgeRings(this._dirEdges)\n const cutLines = new ArrayList()\n for (let i = this._dirEdges.iterator(); i.hasNext(); ) {\n const de = i.next()\n if (de.isMarked()) continue\n const sym = de.getSym()\n if (de.getLabel() === sym.getLabel()) {\n de.setMarked(true)\n sym.setMarked(true)\n const e = de.getEdge()\n cutLines.add(e.getLine())\n }\n }\n return cutLines\n }\n getEdgeRings() {\n this.computeNextCWEdges()\n PolygonizeGraph.label(this._dirEdges, -1)\n const maximalRings = PolygonizeGraph.findLabeledEdgeRings(this._dirEdges)\n this.convertMaximalToMinimalEdgeRings(maximalRings)\n const edgeRingList = new ArrayList()\n for (let i = this._dirEdges.iterator(); i.hasNext(); ) {\n const de = i.next()\n if (de.isMarked()) continue\n if (de.isInRing()) continue\n const er = this.findEdgeRing(de)\n edgeRingList.add(er)\n }\n return edgeRingList\n }\n getNode(pt) {\n let node = this.findNode(pt)\n if (node === null) {\n node = new Node(pt)\n this.add(node)\n }\n return node\n }\n convertMaximalToMinimalEdgeRings(ringEdges) {\n for (let i = ringEdges.iterator(); i.hasNext(); ) {\n const de = i.next()\n const label = de.getLabel()\n const intNodes = PolygonizeGraph.findIntersectionNodes(de, label)\n if (intNodes === null) continue\n for (let iNode = intNodes.iterator(); iNode.hasNext(); ) {\n const node = iNode.next()\n PolygonizeGraph.computeNextCCWEdges(node, label)\n }\n }\n }\n deleteDangles() {\n const nodesToRemove = this.findNodesOfDegree(1)\n const dangleLines = new HashSet()\n const nodeStack = new Stack()\n for (let i = nodesToRemove.iterator(); i.hasNext(); ) \n nodeStack.push(i.next())\n \n while (!nodeStack.isEmpty()) {\n const node = nodeStack.pop()\n PolygonizeGraph.deleteAllEdges(node)\n const nodeOutEdges = node.getOutEdges().getEdges()\n for (let i = nodeOutEdges.iterator(); i.hasNext(); ) {\n const de = i.next()\n de.setMarked(true)\n const sym = de.getSym()\n if (sym !== null) sym.setMarked(true)\n const e = de.getEdge()\n dangleLines.add(e.getLine())\n const toNode = de.getToNode()\n if (PolygonizeGraph.getDegreeNonDeleted(toNode) === 1) nodeStack.push(toNode)\n }\n }\n return dangleLines\n }\n}\n","import STRtree from '../../index/strtree/STRtree.js'\nimport EdgeRing from './EdgeRing.js'\nexport default class HoleAssigner {\n constructor() {\n HoleAssigner.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._shells = null\n this._shellIndex = null\n const shells = arguments[0]\n this._shells = shells\n this.buildIndex()\n }\n static assignHolesToShells(holes, shells) {\n const assigner = new HoleAssigner(shells)\n assigner.assignHolesToShells(holes)\n }\n assignHolesToShells(holeList) {\n for (let i = holeList.iterator(); i.hasNext(); ) {\n const holeER = i.next()\n this.assignHoleToShell(holeER)\n }\n }\n buildIndex() {\n this._shellIndex = new STRtree()\n for (const shell of this._shells) \n this._shellIndex.insert(shell.getRing().getEnvelopeInternal(), shell)\n \n }\n queryOverlappingShells(ringEnv) {\n return this._shellIndex.query(ringEnv)\n }\n findShellContaining(testEr) {\n const testEnv = testEr.getRing().getEnvelopeInternal()\n const candidateShells = this.queryOverlappingShells(testEnv)\n return EdgeRing.findEdgeRingContaining(testEr, candidateShells)\n }\n assignHoleToShell(holeER) {\n const shell = this.findShellContaining(holeER)\n if (shell !== null) \n shell.addHole(holeER)\n \n }\n}\n","import LineString from '../../geom/LineString.js'\nimport Geometry from '../../geom/Geometry.js'\nimport PolygonizeGraph from './PolygonizeGraph.js'\nimport hasInterface from '../../../../../hasInterface.js'\nimport GeometryFactory from '../../geom/GeometryFactory.js'\nimport Collection from '../../../../../java/util/Collection.js'\nimport Collections from '../../../../../java/util/Collections.js'\nimport EdgeRing from './EdgeRing.js'\nimport GeometryComponentFilter from '../../geom/GeometryComponentFilter.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport HoleAssigner from './HoleAssigner.js'\nexport default class Polygonizer {\n constructor() {\n Polygonizer.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._lineStringAdder = new LineStringAdder(this)\n this._graph = null\n this._dangles = new ArrayList()\n this._cutEdges = new ArrayList()\n this._invalidRingLines = new ArrayList()\n this._holeList = null\n this._shellList = null\n this._polyList = null\n this._isCheckingRingsValid = true\n this._extractOnlyPolygonal = null\n this._geomFactory = null\n if (arguments.length === 0) {\n Polygonizer.constructor_.call(this, false)\n } else if (arguments.length === 1) {\n const extractOnlyPolygonal = arguments[0]\n this._extractOnlyPolygonal = extractOnlyPolygonal\n }\n }\n static extractPolygons(shellList, includeAll) {\n const polyList = new ArrayList()\n for (let i = shellList.iterator(); i.hasNext(); ) {\n const er = i.next()\n if (includeAll || er.isIncluded()) \n polyList.add(er.getPolygon())\n \n }\n return polyList\n }\n static findOuterShells(shellList) {\n for (let i = shellList.iterator(); i.hasNext(); ) {\n const er = i.next()\n const outerHoleER = er.getOuterHole()\n if (outerHoleER !== null && !outerHoleER.isProcessed()) {\n er.setIncluded(true)\n outerHoleER.setProcessed(true)\n }\n }\n }\n static findDisjointShells(shellList) {\n Polygonizer.findOuterShells(shellList)\n let isMoreToScan = null\n do {\n isMoreToScan = false\n for (let i = shellList.iterator(); i.hasNext(); ) {\n const er = i.next()\n if (er.isIncludedSet()) continue\n er.updateIncluded()\n if (!er.isIncludedSet()) \n isMoreToScan = true\n \n }\n } while (isMoreToScan)\n }\n getGeometry() {\n if (this._geomFactory === null) this._geomFactory = new GeometryFactory()\n this.polygonize()\n if (this._extractOnlyPolygonal) \n return this._geomFactory.buildGeometry(this._polyList)\n \n return this._geomFactory.createGeometryCollection(GeometryFactory.toGeometryArray(this._polyList))\n }\n getInvalidRingLines() {\n this.polygonize()\n return this._invalidRingLines\n }\n findValidRings(edgeRingList, validEdgeRingList, invalidRingList) {\n for (let i = edgeRingList.iterator(); i.hasNext(); ) {\n const er = i.next()\n if (er.isValid()) validEdgeRingList.add(er); else invalidRingList.add(er.getLineString())\n }\n }\n polygonize() {\n if (this._polyList !== null) return null\n this._polyList = new ArrayList()\n if (this._graph === null) return null\n this._dangles = this._graph.deleteDangles()\n this._cutEdges = this._graph.deleteCutEdges()\n const edgeRingList = this._graph.getEdgeRings()\n let validEdgeRingList = new ArrayList()\n this._invalidRingLines = new ArrayList()\n if (this._isCheckingRingsValid) \n this.findValidRings(edgeRingList, validEdgeRingList, this._invalidRingLines)\n else \n validEdgeRingList = edgeRingList\n \n this.findShellsAndHoles(validEdgeRingList)\n HoleAssigner.assignHolesToShells(this._holeList, this._shellList)\n Collections.sort(this._shellList, new EdgeRing.EnvelopeComparator())\n let includeAll = true\n if (this._extractOnlyPolygonal) {\n Polygonizer.findDisjointShells(this._shellList)\n includeAll = false\n }\n this._polyList = Polygonizer.extractPolygons(this._shellList, includeAll)\n }\n getDangles() {\n this.polygonize()\n return this._dangles\n }\n getCutEdges() {\n this.polygonize()\n return this._cutEdges\n }\n getPolygons() {\n this.polygonize()\n return this._polyList\n }\n add() {\n if (hasInterface(arguments[0], Collection)) {\n const geomList = arguments[0]\n for (let i = geomList.iterator(); i.hasNext(); ) {\n const geometry = i.next()\n this.add(geometry)\n }\n } else if (arguments[0] instanceof LineString) {\n const line = arguments[0]\n this._geomFactory = line.getFactory()\n if (this._graph === null) this._graph = new PolygonizeGraph(this._geomFactory)\n this._graph.addEdge(line)\n } else if (arguments[0] instanceof Geometry) {\n const g = arguments[0]\n g.apply(this._lineStringAdder)\n }\n }\n setCheckRingsValid(isCheckingRingsValid) {\n this._isCheckingRingsValid = isCheckingRingsValid\n }\n findShellsAndHoles(edgeRingList) {\n this._holeList = new ArrayList()\n this._shellList = new ArrayList()\n for (let i = edgeRingList.iterator(); i.hasNext(); ) {\n const er = i.next()\n er.computeHole()\n if (er.isHole()) this._holeList.add(er); else this._shellList.add(er)\n }\n }\n}\nclass LineStringAdder {\n constructor() {\n LineStringAdder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.p = null\n const p = arguments[0]\n this.p = p\n }\n filter(g) {\n if (g instanceof LineString) this.p.add(g)\n }\n get interfaces_() {\n return [GeometryComponentFilter]\n }\n}\nPolygonizer.LineStringAdder = LineStringAdder\n","import PointLocator from '../../algorithm/PointLocator.js'\nimport Location from '../../geom/Location.js'\nimport IntersectionMatrix from '../../geom/IntersectionMatrix.js'\nimport EdgeEndBuilder from './EdgeEndBuilder.js'\nimport NodeMap from '../../geomgraph/NodeMap.js'\nimport RelateNodeFactory from './RelateNodeFactory.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport RobustLineIntersector from '../../algorithm/RobustLineIntersector.js'\nimport Assert from '../../util/Assert.js'\nexport default class RelateComputer {\n constructor() {\n RelateComputer.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._li = new RobustLineIntersector()\n this._ptLocator = new PointLocator()\n this._arg = null\n this._nodes = new NodeMap(new RelateNodeFactory())\n this._im = null\n this._isolatedEdges = new ArrayList()\n this._invalidPoint = null\n const arg = arguments[0]\n this._arg = arg\n }\n insertEdgeEnds(ee) {\n for (let i = ee.iterator(); i.hasNext(); ) {\n const e = i.next()\n this._nodes.add(e)\n }\n }\n computeProperIntersectionIM(intersector, im) {\n const dimA = this._arg[0].getGeometry().getDimension()\n const dimB = this._arg[1].getGeometry().getDimension()\n const hasProper = intersector.hasProperIntersection()\n const hasProperInterior = intersector.hasProperInteriorIntersection()\n if (dimA === 2 && dimB === 2) {\n if (hasProper) im.setAtLeast('212101212')\n } else if (dimA === 2 && dimB === 1) {\n if (hasProper) im.setAtLeast('FFF0FFFF2')\n if (hasProperInterior) im.setAtLeast('1FFFFF1FF')\n } else if (dimA === 1 && dimB === 2) {\n if (hasProper) im.setAtLeast('F0FFFFFF2')\n if (hasProperInterior) im.setAtLeast('1F1FFFFFF')\n } else if (dimA === 1 && dimB === 1) {\n if (hasProperInterior) im.setAtLeast('0FFFFFFFF')\n }\n }\n labelIsolatedEdges(thisIndex, targetIndex) {\n for (let ei = this._arg[thisIndex].getEdgeIterator(); ei.hasNext(); ) {\n const e = ei.next()\n if (e.isIsolated()) {\n this.labelIsolatedEdge(e, targetIndex, this._arg[targetIndex].getGeometry())\n this._isolatedEdges.add(e)\n }\n }\n }\n labelIsolatedEdge(e, targetIndex, target) {\n if (target.getDimension() > 0) {\n const loc = this._ptLocator.locate(e.getCoordinate(), target)\n e.getLabel().setAllLocations(targetIndex, loc)\n } else {\n e.getLabel().setAllLocations(targetIndex, Location.EXTERIOR)\n }\n }\n computeIM() {\n const im = new IntersectionMatrix()\n im.set(Location.EXTERIOR, Location.EXTERIOR, 2)\n if (!this._arg[0].getGeometry().getEnvelopeInternal().intersects(this._arg[1].getGeometry().getEnvelopeInternal())) {\n this.computeDisjointIM(im)\n return im\n }\n this._arg[0].computeSelfNodes(this._li, false)\n this._arg[1].computeSelfNodes(this._li, false)\n const intersector = this._arg[0].computeEdgeIntersections(this._arg[1], this._li, false)\n this.computeIntersectionNodes(0)\n this.computeIntersectionNodes(1)\n this.copyNodesAndLabels(0)\n this.copyNodesAndLabels(1)\n this.labelIsolatedNodes()\n this.computeProperIntersectionIM(intersector, im)\n const eeBuilder = new EdgeEndBuilder()\n const ee0 = eeBuilder.computeEdgeEnds(this._arg[0].getEdgeIterator())\n this.insertEdgeEnds(ee0)\n const ee1 = eeBuilder.computeEdgeEnds(this._arg[1].getEdgeIterator())\n this.insertEdgeEnds(ee1)\n this.labelNodeEdges()\n this.labelIsolatedEdges(0, 1)\n this.labelIsolatedEdges(1, 0)\n this.updateIM(im)\n return im\n }\n labelNodeEdges() {\n for (let ni = this._nodes.iterator(); ni.hasNext(); ) {\n const node = ni.next()\n node.getEdges().computeLabelling(this._arg)\n }\n }\n copyNodesAndLabels(argIndex) {\n for (let i = this._arg[argIndex].getNodeIterator(); i.hasNext(); ) {\n const graphNode = i.next()\n const newNode = this._nodes.addNode(graphNode.getCoordinate())\n newNode.setLabel(argIndex, graphNode.getLabel().getLocation(argIndex))\n }\n }\n labelIntersectionNodes(argIndex) {\n for (let i = this._arg[argIndex].getEdgeIterator(); i.hasNext(); ) {\n const e = i.next()\n const eLoc = e.getLabel().getLocation(argIndex)\n for (let eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) {\n const ei = eiIt.next()\n const n = this._nodes.find(ei.coord)\n if (n.getLabel().isNull(argIndex)) \n if (eLoc === Location.BOUNDARY) n.setLabelBoundary(argIndex); else n.setLabel(argIndex, Location.INTERIOR)\n \n }\n }\n }\n labelIsolatedNode(n, targetIndex) {\n const loc = this._ptLocator.locate(n.getCoordinate(), this._arg[targetIndex].getGeometry())\n n.getLabel().setAllLocations(targetIndex, loc)\n }\n computeIntersectionNodes(argIndex) {\n for (let i = this._arg[argIndex].getEdgeIterator(); i.hasNext(); ) {\n const e = i.next()\n const eLoc = e.getLabel().getLocation(argIndex)\n for (let eiIt = e.getEdgeIntersectionList().iterator(); eiIt.hasNext(); ) {\n const ei = eiIt.next()\n const n = this._nodes.addNode(ei.coord)\n if (eLoc === Location.BOUNDARY) n.setLabelBoundary(argIndex); else \n if (n.getLabel().isNull(argIndex)) n.setLabel(argIndex, Location.INTERIOR)\n \n }\n }\n }\n labelIsolatedNodes() {\n for (let ni = this._nodes.iterator(); ni.hasNext(); ) {\n const n = ni.next()\n const label = n.getLabel()\n Assert.isTrue(label.getGeometryCount() > 0, 'node with empty label found')\n if (n.isIsolated()) \n if (label.isNull(0)) this.labelIsolatedNode(n, 0); else this.labelIsolatedNode(n, 1)\n \n }\n }\n updateIM(im) {\n for (let ei = this._isolatedEdges.iterator(); ei.hasNext(); ) {\n const e = ei.next()\n e.updateIM(im)\n }\n for (let ni = this._nodes.iterator(); ni.hasNext(); ) {\n const node = ni.next()\n node.updateIM(im)\n node.updateIMFromEdges(im)\n }\n }\n computeDisjointIM(im) {\n const ga = this._arg[0].getGeometry()\n if (!ga.isEmpty()) {\n im.set(Location.INTERIOR, Location.EXTERIOR, ga.getDimension())\n im.set(Location.BOUNDARY, Location.EXTERIOR, ga.getBoundaryDimension())\n }\n const gb = this._arg[1].getGeometry()\n if (!gb.isEmpty()) {\n im.set(Location.EXTERIOR, Location.INTERIOR, gb.getDimension())\n im.set(Location.EXTERIOR, Location.BOUNDARY, gb.getBoundaryDimension())\n }\n }\n}\n","import LineString from '../../geom/LineString.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport Point from '../../geom/Point.js'\nimport Polygon from '../../geom/Polygon.js'\nexport default class RectangleContains {\n constructor() {\n RectangleContains.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._rectEnv = null\n const rectangle = arguments[0]\n this._rectEnv = rectangle.getEnvelopeInternal()\n }\n static contains(rectangle, b) {\n const rc = new RectangleContains(rectangle)\n return rc.contains(b)\n }\n isContainedInBoundary(geom) {\n if (geom instanceof Polygon) return false\n if (geom instanceof Point) return this.isPointContainedInBoundary(geom)\n if (geom instanceof LineString) return this.isLineStringContainedInBoundary(geom)\n for (let i = 0; i < geom.getNumGeometries(); i++) {\n const comp = geom.getGeometryN(i)\n if (!this.isContainedInBoundary(comp)) return false\n }\n return true\n }\n isLineSegmentContainedInBoundary(p0, p1) {\n if (p0.equals(p1)) return this.isPointContainedInBoundary(p0)\n if (p0.x === p1.x) {\n if (p0.x === this._rectEnv.getMinX() || p0.x === this._rectEnv.getMaxX()) return true\n } else if (p0.y === p1.y) {\n if (p0.y === this._rectEnv.getMinY() || p0.y === this._rectEnv.getMaxY()) return true\n }\n return false\n }\n isLineStringContainedInBoundary(line) {\n const seq = line.getCoordinateSequence()\n const p0 = new Coordinate()\n const p1 = new Coordinate()\n for (let i = 0; i < seq.size() - 1; i++) {\n seq.getCoordinate(i, p0)\n seq.getCoordinate(i + 1, p1)\n if (!this.isLineSegmentContainedInBoundary(p0, p1)) return false\n }\n return true\n }\n isPointContainedInBoundary() {\n if (arguments[0] instanceof Point) {\n const point = arguments[0]\n return this.isPointContainedInBoundary(point.getCoordinate())\n } else if (arguments[0] instanceof Coordinate) {\n const pt = arguments[0]\n return pt.x === this._rectEnv.getMinX() || pt.x === this._rectEnv.getMaxX() || pt.y === this._rectEnv.getMinY() || pt.y === this._rectEnv.getMaxY()\n }\n }\n contains(geom) {\n if (!this._rectEnv.contains(geom.getEnvelopeInternal())) return false\n if (this.isContainedInBoundary(geom)) return false\n return true\n }\n}\n","import Coordinate from '../geom/Coordinate.js'\nimport RobustLineIntersector from './RobustLineIntersector.js'\nimport Envelope from '../geom/Envelope.js'\nexport default class RectangleLineIntersector {\n constructor() {\n RectangleLineIntersector.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._li = new RobustLineIntersector()\n this._rectEnv = null\n this._diagUp0 = null\n this._diagUp1 = null\n this._diagDown0 = null\n this._diagDown1 = null\n const rectEnv = arguments[0]\n this._rectEnv = rectEnv\n this._diagUp0 = new Coordinate(rectEnv.getMinX(), rectEnv.getMinY())\n this._diagUp1 = new Coordinate(rectEnv.getMaxX(), rectEnv.getMaxY())\n this._diagDown0 = new Coordinate(rectEnv.getMinX(), rectEnv.getMaxY())\n this._diagDown1 = new Coordinate(rectEnv.getMaxX(), rectEnv.getMinY())\n }\n intersects(p0, p1) {\n const segEnv = new Envelope(p0, p1)\n if (!this._rectEnv.intersects(segEnv)) return false\n if (this._rectEnv.intersects(p0)) return true\n if (this._rectEnv.intersects(p1)) return true\n if (p0.compareTo(p1) > 0) {\n const tmp = p0\n p0 = p1\n p1 = tmp\n }\n let isSegUpwards = false\n if (p1.y > p0.y) isSegUpwards = true\n if (isSegUpwards) \n this._li.computeIntersection(p0, p1, this._diagDown0, this._diagDown1)\n else \n this._li.computeIntersection(p0, p1, this._diagUp0, this._diagUp1)\n \n if (this._li.hasIntersection()) return true\n return false\n }\n}\n","import Coordinate from '../../geom/Coordinate.js'\nimport Polygon from '../../geom/Polygon.js'\nimport RectangleLineIntersector from '../../algorithm/RectangleLineIntersector.js'\nimport ShortCircuitedGeometryVisitor from '../../geom/util/ShortCircuitedGeometryVisitor.js'\nimport SimplePointInAreaLocator from '../../algorithm/locate/SimplePointInAreaLocator.js'\nimport LinearComponentExtracter from '../../geom/util/LinearComponentExtracter.js'\nexport default class RectangleIntersects {\n constructor() {\n RectangleIntersects.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._rectangle = null\n this._rectEnv = null\n const rectangle = arguments[0]\n this._rectangle = rectangle\n this._rectEnv = rectangle.getEnvelopeInternal()\n }\n static intersects(rectangle, b) {\n const rp = new RectangleIntersects(rectangle)\n return rp.intersects(b)\n }\n intersects(geom) {\n if (!this._rectEnv.intersects(geom.getEnvelopeInternal())) return false\n const visitor = new EnvelopeIntersectsVisitor(this._rectEnv)\n visitor.applyTo(geom)\n if (visitor.intersects()) return true\n const ecpVisitor = new GeometryContainsPointVisitor(this._rectangle)\n ecpVisitor.applyTo(geom)\n if (ecpVisitor.containsPoint()) return true\n const riVisitor = new RectangleIntersectsSegmentVisitor(this._rectangle)\n riVisitor.applyTo(geom)\n if (riVisitor.intersects()) return true\n return false\n }\n}\nclass EnvelopeIntersectsVisitor extends ShortCircuitedGeometryVisitor {\n constructor() {\n super()\n EnvelopeIntersectsVisitor.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._rectEnv = null\n this._intersects = false\n const rectEnv = arguments[0]\n this._rectEnv = rectEnv\n }\n isDone() {\n return this._intersects === true\n }\n visit(element) {\n const elementEnv = element.getEnvelopeInternal()\n if (!this._rectEnv.intersects(elementEnv)) \n return null\n \n if (this._rectEnv.contains(elementEnv)) {\n this._intersects = true\n return null\n }\n if (elementEnv.getMinX() >= this._rectEnv.getMinX() && elementEnv.getMaxX() <= this._rectEnv.getMaxX()) {\n this._intersects = true\n return null\n }\n if (elementEnv.getMinY() >= this._rectEnv.getMinY() && elementEnv.getMaxY() <= this._rectEnv.getMaxY()) {\n this._intersects = true\n return null\n }\n }\n intersects() {\n return this._intersects\n }\n}\nclass GeometryContainsPointVisitor extends ShortCircuitedGeometryVisitor {\n constructor() {\n super()\n GeometryContainsPointVisitor.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._rectSeq = null\n this._rectEnv = null\n this._containsPoint = false\n const rectangle = arguments[0]\n this._rectSeq = rectangle.getExteriorRing().getCoordinateSequence()\n this._rectEnv = rectangle.getEnvelopeInternal()\n }\n isDone() {\n return this._containsPoint === true\n }\n visit(geom) {\n if (!(geom instanceof Polygon)) return null\n const elementEnv = geom.getEnvelopeInternal()\n if (!this._rectEnv.intersects(elementEnv)) return null\n const rectPt = new Coordinate()\n for (let i = 0; i < 4; i++) {\n this._rectSeq.getCoordinate(i, rectPt)\n if (!elementEnv.contains(rectPt)) continue\n if (SimplePointInAreaLocator.containsPointInPolygon(rectPt, geom)) {\n this._containsPoint = true\n return null\n }\n }\n }\n containsPoint() {\n return this._containsPoint\n }\n}\nclass RectangleIntersectsSegmentVisitor extends ShortCircuitedGeometryVisitor {\n constructor() {\n super()\n RectangleIntersectsSegmentVisitor.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._rectEnv = null\n this._rectIntersector = null\n this._hasIntersection = false\n this._p0 = new Coordinate()\n this._p1 = new Coordinate()\n const rectangle = arguments[0]\n this._rectEnv = rectangle.getEnvelopeInternal()\n this._rectIntersector = new RectangleLineIntersector(this._rectEnv)\n }\n intersects() {\n return this._hasIntersection\n }\n isDone() {\n return this._hasIntersection === true\n }\n visit(geom) {\n const elementEnv = geom.getEnvelopeInternal()\n if (!this._rectEnv.intersects(elementEnv)) return null\n const lines = LinearComponentExtracter.getLines(geom)\n this.checkIntersectionWithLineStrings(lines)\n }\n checkIntersectionWithLineStrings(lines) {\n for (let i = lines.iterator(); i.hasNext(); ) {\n const testLine = i.next()\n this.checkIntersectionWithSegments(testLine)\n if (this._hasIntersection) return null\n }\n }\n checkIntersectionWithSegments(testLine) {\n const seq1 = testLine.getCoordinateSequence()\n for (let j = 1; j < seq1.size(); j++) {\n seq1.getCoordinate(j - 1, this._p0)\n seq1.getCoordinate(j, this._p1)\n if (this._rectIntersector.intersects(this._p0, this._p1)) {\n this._hasIntersection = true\n return null\n }\n }\n }\n}\n","import RelateComputer from './RelateComputer.js'\nimport GeometryGraphOperation from '../GeometryGraphOperation.js'\nimport RectangleContains from '../predicate/RectangleContains.js'\nimport RectangleIntersects from '../predicate/RectangleIntersects.js'\nexport default class RelateOp extends GeometryGraphOperation {\n constructor() {\n super()\n RelateOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._relate = null\n if (arguments.length === 2) {\n const g0 = arguments[0], g1 = arguments[1]\n GeometryGraphOperation.constructor_.call(this, g0, g1)\n this._relate = new RelateComputer(this._arg)\n } else if (arguments.length === 3) {\n const g0 = arguments[0], g1 = arguments[1], boundaryNodeRule = arguments[2]\n GeometryGraphOperation.constructor_.call(this, g0, g1, boundaryNodeRule)\n this._relate = new RelateComputer(this._arg)\n }\n }\n static covers(g1, g2) {\n if (g2.getDimension() === 2 && g1.getDimension() < 2) \n return false\n \n if (g2.getDimension() === 1 && g1.getDimension() < 1 && g2.getLength() > 0.0) \n return false\n \n if (!g1.getEnvelopeInternal().covers(g2.getEnvelopeInternal())) return false\n if (g1.isRectangle()) \n return true\n \n return new RelateOp(g1, g2).getIntersectionMatrix().isCovers()\n }\n static intersects(g1, g2) {\n if (!g1.getEnvelopeInternal().intersects(g2.getEnvelopeInternal())) return false\n if (g1.isRectangle()) \n return RectangleIntersects.intersects(g1, g2)\n \n if (g2.isRectangle()) \n return RectangleIntersects.intersects(g2, g1)\n \n if (g1.isGeometryCollection() || g2.isGeometryCollection()) {\n const r = false\n for (let i = 0; i < g1.getNumGeometries(); i++) \n for (let j = 0; j < g2.getNumGeometries(); j++) \n if (g1.getGeometryN(i).intersects(g2.getGeometryN(j))) \n return true\n \n \n \n return false\n }\n return new RelateOp(g1, g2).getIntersectionMatrix().isIntersects()\n }\n static touches(g1, g2) {\n if (!g1.getEnvelopeInternal().intersects(g2.getEnvelopeInternal())) return false\n return new RelateOp(g1, g2).getIntersectionMatrix().isTouches(g1.getDimension(), g2.getDimension())\n }\n static equalsTopo(g1, g2) {\n if (!g1.getEnvelopeInternal().equals(g2.getEnvelopeInternal())) return false\n return RelateOp.relate(g1, g2).isEquals(g1.getDimension(), g2.getDimension())\n }\n static relate() {\n if (arguments.length === 2) {\n const a = arguments[0], b = arguments[1]\n const relOp = new RelateOp(a, b)\n const im = relOp.getIntersectionMatrix()\n return im\n } else if (arguments.length === 3) {\n const a = arguments[0], b = arguments[1], boundaryNodeRule = arguments[2]\n const relOp = new RelateOp(a, b, boundaryNodeRule)\n const im = relOp.getIntersectionMatrix()\n return im\n }\n }\n static overlaps(g1, g2) {\n if (!g1.getEnvelopeInternal().intersects(g2.getEnvelopeInternal())) return false\n return new RelateOp(g1, g2).getIntersectionMatrix().isOverlaps(g1.getDimension(), g2.getDimension())\n }\n static crosses(g1, g2) {\n if (!g1.getEnvelopeInternal().intersects(g2.getEnvelopeInternal())) return false\n return new RelateOp(g1, g2).getIntersectionMatrix().isCrosses(g1.getDimension(), g2.getDimension())\n }\n static contains(g1, g2) {\n if (g2.getDimension() === 2 && g1.getDimension() < 2) \n return false\n \n if (g2.getDimension() === 1 && g1.getDimension() < 1 && g2.getLength() > 0.0) \n return false\n \n if (!g1.getEnvelopeInternal().contains(g2.getEnvelopeInternal())) return false\n if (g1.isRectangle()) \n return RectangleContains.contains(g1, g2)\n \n return new RelateOp(g1, g2).getIntersectionMatrix().isContains()\n }\n getIntersectionMatrix() {\n return this._relate.computeIM()\n }\n}\n","import PointLocator from '../../algorithm/PointLocator.js'\nimport Location from '../../geom/Location.js'\nimport TreeSet from '../../../../../java/util/TreeSet.js'\nimport GeometryCombiner from '../../geom/util/GeometryCombiner.js'\nimport CoordinateArrays from '../../geom/CoordinateArrays.js'\nexport default class PointGeometryUnion {\n constructor() {\n PointGeometryUnion.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pointGeom = null\n this._otherGeom = null\n this._geomFact = null\n const pointGeom = arguments[0], otherGeom = arguments[1]\n this._pointGeom = pointGeom\n this._otherGeom = otherGeom\n this._geomFact = otherGeom.getFactory()\n }\n static union(pointGeom, otherGeom) {\n const unioner = new PointGeometryUnion(pointGeom, otherGeom)\n return unioner.union()\n }\n union() {\n const locater = new PointLocator()\n const exteriorCoords = new TreeSet()\n for (let i = 0; i < this._pointGeom.getNumGeometries(); i++) {\n const point = this._pointGeom.getGeometryN(i)\n const coord = point.getCoordinate()\n const loc = locater.locate(coord, this._otherGeom)\n if (loc === Location.EXTERIOR) exteriorCoords.add(coord)\n }\n if (exteriorCoords.size() === 0) return this._otherGeom\n let ptComp = null\n const coords = CoordinateArrays.toCoordinateArray(exteriorCoords)\n if (coords.length === 1) \n ptComp = this._geomFact.createPoint(coords[0])\n else \n ptComp = this._geomFact.createMultiPointFromCoords(coords)\n \n return GeometryCombiner.combine(ptComp, this._otherGeom)\n }\n}\n","import LineString from '../../geom/LineString.js'\nimport Geometry from '../../geom/Geometry.js'\nimport hasInterface from '../../../../../hasInterface.js'\nimport Collection from '../../../../../java/util/Collection.js'\nimport Point from '../../geom/Point.js'\nimport Polygon from '../../geom/Polygon.js'\nimport GeometryCollection from '../../geom/GeometryCollection.js'\nimport Dimension from '../../geom/Dimension.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport GeometryFilter from '../../geom/GeometryFilter.js'\nimport Assert from '../../util/Assert.js'\nexport default class InputExtracter {\n constructor() {\n InputExtracter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geomFactory = null\n this._polygons = new ArrayList()\n this._lines = new ArrayList()\n this._points = new ArrayList()\n this._dimension = Dimension.FALSE\n }\n static extract() {\n if (hasInterface(arguments[0], Collection)) {\n const geoms = arguments[0]\n const extracter = new InputExtracter()\n extracter.add(geoms)\n return extracter\n } else if (arguments[0] instanceof Geometry) {\n const geom = arguments[0]\n const extracter = new InputExtracter()\n extracter.add(geom)\n return extracter\n }\n }\n getFactory() {\n return this._geomFactory\n }\n recordDimension(dim) {\n if (dim > this._dimension) this._dimension = dim\n }\n getDimension() {\n return this._dimension\n }\n filter(geom) {\n this.recordDimension(geom.getDimension())\n if (geom instanceof GeometryCollection) \n return null\n \n if (geom.isEmpty()) return null\n if (geom instanceof Polygon) {\n this._polygons.add(geom)\n return null\n } else if (geom instanceof LineString) {\n this._lines.add(geom)\n return null\n } else if (geom instanceof Point) {\n this._points.add(geom)\n return null\n }\n Assert.shouldNeverReachHere('Unhandled geometry type: ' + geom.getGeometryType())\n }\n getExtract(dim) {\n switch (dim) {\n case 0:\n return this._points\n case 1:\n return this._lines\n case 2:\n return this._polygons\n }\n Assert.shouldNeverReachHere('Invalid dimension: ' + dim)\n return null\n }\n isEmpty() {\n return this._polygons.isEmpty() && this._lines.isEmpty() && this._points.isEmpty()\n }\n add() {\n if (hasInterface(arguments[0], Collection)) {\n const geoms = arguments[0]\n for (const geom of geoms) \n this.add(geom)\n \n } else if (arguments[0] instanceof Geometry) {\n const geom = arguments[0]\n if (this._geomFactory === null) this._geomFactory = geom.getFactory()\n geom.apply(this)\n }\n }\n get interfaces_() {\n return [GeometryFilter]\n }\n}\n","import HashSet from '../../../../../java/util/HashSet.js'\nimport TopologyException from '../../geom/TopologyException.js'\nimport GeometryCombiner from '../../geom/util/GeometryCombiner.js'\nimport LineSegment from '../../geom/LineSegment.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport CoordinateSequenceFilter from '../../geom/CoordinateSequenceFilter.js'\nexport default class OverlapUnion {\n constructor() {\n OverlapUnion.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geomFactory = null\n this._g0 = null\n this._g1 = null\n this._isUnionSafe = null\n const g0 = arguments[0], g1 = arguments[1]\n this._g0 = g0\n this._g1 = g1\n this._geomFactory = g0.getFactory()\n }\n static containsProperly() {\n if (arguments.length === 2) {\n const env = arguments[0], p = arguments[1]\n if (env.isNull()) return false\n return p.getX() > env.getMinX() && p.getX() < env.getMaxX() && p.getY() > env.getMinY() && p.getY() < env.getMaxY()\n } else if (arguments.length === 3) {\n const env = arguments[0], p0 = arguments[1], p1 = arguments[2]\n return OverlapUnion.containsProperly(env, p0) && OverlapUnion.containsProperly(env, p1)\n }\n }\n static union(g0, g1) {\n const union = new OverlapUnion(g0, g1)\n return union.union()\n }\n static intersects(env, p0, p1) {\n return env.intersects(p0) || env.intersects(p1)\n }\n static overlapEnvelope(g0, g1) {\n const g0Env = g0.getEnvelopeInternal()\n const g1Env = g1.getEnvelopeInternal()\n const overlapEnv = g0Env.intersection(g1Env)\n return overlapEnv\n }\n static extractBorderSegments(geom, env, segs) {\n geom.apply(new (class {\n get interfaces_() {\n return [CoordinateSequenceFilter]\n }\n filter(seq, i) {\n if (i <= 0) return null\n const p0 = seq.getCoordinate(i - 1)\n const p1 = seq.getCoordinate(i)\n const isBorder = OverlapUnion.intersects(env, p0, p1) && !OverlapUnion.containsProperly(env, p0, p1)\n if (isBorder) {\n const seg = new LineSegment(p0, p1)\n segs.add(seg)\n }\n }\n isDone() {\n return false\n }\n isGeometryChanged() {\n return false\n }\n })())\n }\n static unionBuffer(g0, g1) {\n const factory = g0.getFactory()\n const gColl = factory.createGeometryCollection([g0, g1])\n const union = gColl.buffer(0.0)\n return union\n }\n isBorderSegmentsSame(result, env) {\n const segsBefore = this.extractBorderSegments(this._g0, this._g1, env)\n const segsAfter = new ArrayList()\n OverlapUnion.extractBorderSegments(result, env, segsAfter)\n return this.isEqual(segsBefore, segsAfter)\n }\n extractByEnvelope(env, geom, disjointGeoms) {\n const intersectingGeoms = new ArrayList()\n for (let i = 0; i < geom.getNumGeometries(); i++) {\n const elem = geom.getGeometryN(i)\n if (elem.getEnvelopeInternal().intersects(env)) {\n intersectingGeoms.add(elem)\n } else {\n const copy = elem.copy()\n disjointGeoms.add(copy)\n }\n }\n return this._geomFactory.buildGeometry(intersectingGeoms)\n }\n isEqual(segs0, segs1) {\n if (segs0.size() !== segs1.size()) return false\n const segIndex = new HashSet(segs0)\n for (const seg of segs1) \n if (!segIndex.contains(seg)) \n return false\n \n \n return true\n }\n union() {\n const overlapEnv = OverlapUnion.overlapEnvelope(this._g0, this._g1)\n if (overlapEnv.isNull()) {\n const g0Copy = this._g0.copy()\n const g1Copy = this._g1.copy()\n return GeometryCombiner.combine(g0Copy, g1Copy)\n }\n const disjointPolys = new ArrayList()\n const g0Overlap = this.extractByEnvelope(overlapEnv, this._g0, disjointPolys)\n const g1Overlap = this.extractByEnvelope(overlapEnv, this._g1, disjointPolys)\n const unionGeom = this.unionFull(g0Overlap, g1Overlap)\n let result = null\n this._isUnionSafe = this.isBorderSegmentsSame(unionGeom, overlapEnv)\n if (!this._isUnionSafe) \n result = this.unionFull(this._g0, this._g1)\n else \n result = this.combine(unionGeom, disjointPolys)\n \n return result\n }\n combine(unionGeom, disjointPolys) {\n if (disjointPolys.size() <= 0) return unionGeom\n disjointPolys.add(unionGeom)\n const result = GeometryCombiner.combine(disjointPolys)\n return result\n }\n unionFull(geom0, geom1) {\n try {\n return geom0.union(geom1)\n } catch (ex) {\n if (ex instanceof TopologyException) \n return OverlapUnion.unionBuffer(geom0, geom1)\n else throw ex\n } finally {}\n }\n extractBorderSegments(geom0, geom1, env) {\n const segs = new ArrayList()\n OverlapUnion.extractBorderSegments(geom0, env, segs)\n if (geom1 !== null) OverlapUnion.extractBorderSegments(geom1, env, segs)\n return segs\n }\n isUnionOptimized() {\n return this._isUnionSafe\n }\n}\n","import PolygonExtracter from '../../geom/util/PolygonExtracter.js'\nimport OverlapUnion from './OverlapUnion.js'\nimport STRtree from '../../index/strtree/STRtree.js'\nimport Geometry from '../../geom/Geometry.js'\nimport hasInterface from '../../../../../hasInterface.js'\nimport GeometryFactory from '../../geom/GeometryFactory.js'\nimport Polygonal from '../../geom/Polygonal.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport List from '../../../../../java/util/List.js'\nexport default class CascadedPolygonUnion {\n constructor() {\n CascadedPolygonUnion.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputPolys = null\n this._geomFactory = null\n const polys = arguments[0]\n this._inputPolys = polys\n if (this._inputPolys === null) this._inputPolys = new ArrayList()\n }\n static restrictToPolygons(g) {\n if (hasInterface(g, Polygonal)) \n return g\n \n const polygons = PolygonExtracter.getPolygons(g)\n if (polygons.size() === 1) return polygons.get(0)\n return g.getFactory().createMultiPolygon(GeometryFactory.toPolygonArray(polygons))\n }\n static getGeometry(list, index) {\n if (index >= list.size()) return null\n return list.get(index)\n }\n static union(polys) {\n const op = new CascadedPolygonUnion(polys)\n return op.union()\n }\n reduceToGeometries(geomTree) {\n const geoms = new ArrayList()\n for (let i = geomTree.iterator(); i.hasNext(); ) {\n const o = i.next()\n let geom = null\n if (hasInterface(o, List)) \n geom = this.unionTree(o)\n else if (o instanceof Geometry) \n geom = o\n \n geoms.add(geom)\n }\n return geoms\n }\n union() {\n if (this._inputPolys === null) throw new IllegalStateException('union() method cannot be called twice')\n if (this._inputPolys.isEmpty()) return null\n this._geomFactory = this._inputPolys.iterator().next().getFactory()\n const index = new STRtree(CascadedPolygonUnion.STRTREE_NODE_CAPACITY)\n for (let i = this._inputPolys.iterator(); i.hasNext(); ) {\n const item = i.next()\n index.insert(item.getEnvelopeInternal(), item)\n }\n this._inputPolys = null\n const itemTree = index.itemsTree()\n const unionAll = this.unionTree(itemTree)\n return unionAll\n }\n binaryUnion() {\n if (arguments.length === 1) {\n const geoms = arguments[0]\n return this.binaryUnion(geoms, 0, geoms.size())\n } else if (arguments.length === 3) {\n const geoms = arguments[0], start = arguments[1], end = arguments[2]\n if (end - start <= 1) {\n const g0 = CascadedPolygonUnion.getGeometry(geoms, start)\n return this.unionSafe(g0, null)\n } else if (end - start === 2) {\n return this.unionSafe(CascadedPolygonUnion.getGeometry(geoms, start), CascadedPolygonUnion.getGeometry(geoms, start + 1))\n } else {\n const mid = Math.trunc((end + start) / 2)\n const g0 = this.binaryUnion(geoms, start, mid)\n const g1 = this.binaryUnion(geoms, mid, end)\n return this.unionSafe(g0, g1)\n }\n }\n }\n repeatedUnion(geoms) {\n let union = null\n for (let i = geoms.iterator(); i.hasNext(); ) {\n const g = i.next()\n if (union === null) union = g.copy(); else union = union.union(g)\n }\n return union\n }\n unionSafe(g0, g1) {\n if (g0 === null && g1 === null) return null\n if (g0 === null) return g1.copy()\n if (g1 === null) return g0.copy()\n return this.unionActual(g0, g1)\n }\n unionActual(g0, g1) {\n const union = OverlapUnion.union(g0, g1)\n \n return CascadedPolygonUnion.restrictToPolygons(union)\n }\n unionTree(geomTree) {\n const geoms = this.reduceToGeometries(geomTree)\n const union = this.binaryUnion(geoms)\n return union\n }\n bufferUnion() {\n if (arguments.length === 1) {\n const geoms = arguments[0]\n const factory = geoms.get(0).getFactory()\n const gColl = factory.buildGeometry(geoms)\n const unionAll = gColl.buffer(0.0)\n return unionAll\n } else if (arguments.length === 2) {\n const g0 = arguments[0], g1 = arguments[1]\n const factory = g0.getFactory()\n const gColl = factory.createGeometryCollection([g0, g1])\n const unionAll = gColl.buffer(0.0)\n return unionAll\n }\n }\n}\nCascadedPolygonUnion.STRTREE_NODE_CAPACITY = 4\n","import Geometry from '../../geom/Geometry.js'\nimport PointGeometryUnion from './PointGeometryUnion.js'\nimport hasInterface from '../../../../../hasInterface.js'\nimport Collection from '../../../../../java/util/Collection.js'\nimport SnapIfNeededOverlayOp from '../overlay/snap/SnapIfNeededOverlayOp.js'\nimport InputExtracter from './InputExtracter.js'\nimport OverlayOp from '../overlay/OverlayOp.js'\nimport CascadedPolygonUnion from './CascadedPolygonUnion.js'\nexport default class UnaryUnionOp {\n constructor() {\n UnaryUnionOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geomFact = null\n this._extracter = null\n if (arguments.length === 1) {\n if (hasInterface(arguments[0], Collection)) {\n const geoms = arguments[0]\n this.extract(geoms)\n } else if (arguments[0] instanceof Geometry) {\n const geom = arguments[0]\n this.extract(geom)\n }\n } else if (arguments.length === 2) {\n const geoms = arguments[0], geomFact = arguments[1]\n this._geomFact = geomFact\n this.extract(geoms)\n }\n }\n static union() {\n if (arguments.length === 1) {\n if (hasInterface(arguments[0], Collection)) {\n const geoms = arguments[0]\n const op = new UnaryUnionOp(geoms)\n return op.union()\n } else if (arguments[0] instanceof Geometry) {\n const geom = arguments[0]\n const op = new UnaryUnionOp(geom)\n return op.union()\n }\n } else if (arguments.length === 2) {\n const geoms = arguments[0], geomFact = arguments[1]\n const op = new UnaryUnionOp(geoms, geomFact)\n return op.union()\n }\n }\n unionNoOpt(g0) {\n const empty = this._geomFact.createPoint()\n return SnapIfNeededOverlayOp.overlayOp(g0, empty, OverlayOp.UNION)\n }\n unionWithNull(g0, g1) {\n if (g0 === null && g1 === null) return null\n if (g1 === null) return g0\n if (g0 === null) return g1\n return g0.union(g1)\n }\n extract() {\n if (hasInterface(arguments[0], Collection)) {\n const geoms = arguments[0]\n this._extracter = InputExtracter.extract(geoms)\n } else if (arguments[0] instanceof Geometry) {\n const geom = arguments[0]\n this._extracter = InputExtracter.extract(geom)\n }\n }\n union() {\n if (this._geomFact === null) this._geomFact = this._extracter.getFactory()\n if (this._geomFact === null) \n return null\n \n if (this._extracter.isEmpty()) \n return this._geomFact.createEmpty(this._extracter.getDimension())\n \n const points = this._extracter.getExtract(0)\n const lines = this._extracter.getExtract(1)\n const polygons = this._extracter.getExtract(2)\n let unionPoints = null\n if (points.size() > 0) {\n const ptGeom = this._geomFact.buildGeometry(points)\n unionPoints = this.unionNoOpt(ptGeom)\n }\n let unionLines = null\n if (lines.size() > 0) {\n const lineGeom = this._geomFact.buildGeometry(lines)\n unionLines = this.unionNoOpt(lineGeom)\n }\n let unionPolygons = null\n if (polygons.size() > 0) \n unionPolygons = CascadedPolygonUnion.union(polygons)\n \n const unionLA = this.unionWithNull(unionLines, unionPolygons)\n let union = null\n if (unionPoints === null) union = unionLA; else if (unionLA === null) union = unionPoints; else union = PointGeometryUnion.union(unionPoints, unionLA)\n if (union === null) return this._geomFact.createGeometryCollection()\n return union\n }\n}\n","import CommonBitsRemover from './CommonBitsRemover.js'\nexport default class CommonBitsOp {\n constructor() {\n CommonBitsOp.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._returnToOriginalPrecision = true\n this._cbr = null\n if (arguments.length === 0) {\n CommonBitsOp.constructor_.call(this, true)\n } else if (arguments.length === 1) {\n const returnToOriginalPrecision = arguments[0]\n this._returnToOriginalPrecision = returnToOriginalPrecision\n }\n }\n computeResultPrecision(result) {\n if (this._returnToOriginalPrecision) this._cbr.addCommonBits(result)\n return result\n }\n union(geom0, geom1) {\n const geom = this.removeCommonBits(geom0, geom1)\n return this.computeResultPrecision(geom[0].union(geom[1]))\n }\n intersection(geom0, geom1) {\n const geom = this.removeCommonBits(geom0, geom1)\n return this.computeResultPrecision(geom[0].intersection(geom[1]))\n }\n removeCommonBits() {\n if (arguments.length === 1) {\n const geom0 = arguments[0]\n this._cbr = new CommonBitsRemover()\n this._cbr.add(geom0)\n const geom = this._cbr.removeCommonBits(geom0.copy())\n return geom\n } else if (arguments.length === 2) {\n const geom0 = arguments[0], geom1 = arguments[1]\n this._cbr = new CommonBitsRemover()\n this._cbr.add(geom0)\n this._cbr.add(geom1)\n const geom = new Array(2).fill(null)\n geom[0] = this._cbr.removeCommonBits(geom0.copy())\n geom[1] = this._cbr.removeCommonBits(geom1.copy())\n return geom\n }\n }\n buffer(geom0, distance) {\n const geom = this.removeCommonBits(geom0)\n return this.computeResultPrecision(geom.buffer(distance))\n }\n symDifference(geom0, geom1) {\n const geom = this.removeCommonBits(geom0, geom1)\n return this.computeResultPrecision(geom[0].symDifference(geom[1]))\n }\n difference(geom0, geom1) {\n const geom = this.removeCommonBits(geom0, geom1)\n return this.computeResultPrecision(geom[0].difference(geom[1]))\n }\n}\n","import LineString from '../geom/LineString.js'\nimport CoordinateList from '../geom/CoordinateList.js'\nimport Geometry from '../geom/Geometry.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport GeometryEditor from '../geom/util/GeometryEditor.js'\nimport LinearRing from '../geom/LinearRing.js'\nexport default class PrecisionReducerCoordinateOperation extends GeometryEditor.CoordinateOperation {\n constructor() {\n super()\n PrecisionReducerCoordinateOperation.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._targetPM = null\n this._removeCollapsed = true\n const targetPM = arguments[0], removeCollapsed = arguments[1]\n this._targetPM = targetPM\n this._removeCollapsed = removeCollapsed\n }\n edit() {\n if (arguments.length === 2 && (arguments[1] instanceof Geometry && arguments[0] instanceof Array)) {\n const coordinates = arguments[0], geom = arguments[1]\n if (coordinates.length === 0) return null\n const reducedCoords = new Array(coordinates.length).fill(null)\n for (let i = 0; i < coordinates.length; i++) {\n const coord = new Coordinate(coordinates[i])\n this._targetPM.makePrecise(coord)\n reducedCoords[i] = coord\n }\n const noRepeatedCoordList = new CoordinateList(reducedCoords, false)\n const noRepeatedCoords = noRepeatedCoordList.toCoordinateArray()\n let minLength = 0\n if (geom instanceof LineString) minLength = 2\n if (geom instanceof LinearRing) minLength = 4\n let collapsedCoords = reducedCoords\n if (this._removeCollapsed) collapsedCoords = null\n if (noRepeatedCoords.length < minLength) \n return collapsedCoords\n \n return noRepeatedCoords\n } else {\n return super.edit.apply(this, arguments)\n }\n }\n}\n","import hasInterface from '../../../../hasInterface.js'\nimport GeometryFactory from '../geom/GeometryFactory.js'\nimport IsValidOp from '../operation/valid/IsValidOp.js'\nimport GeometryEditor from '../geom/util/GeometryEditor.js'\nimport BufferOp from '../operation/buffer/BufferOp.js'\nimport Polygonal from '../geom/Polygonal.js'\nimport PrecisionReducerCoordinateOperation from './PrecisionReducerCoordinateOperation.js'\nexport default class GeometryPrecisionReducer {\n constructor() {\n GeometryPrecisionReducer.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._targetPM = null\n this._removeCollapsed = true\n this._changePrecisionModel = false\n this._isPointwise = false\n const pm = arguments[0]\n this._targetPM = pm\n }\n static reduce(g, precModel) {\n const reducer = new GeometryPrecisionReducer(precModel)\n return reducer.reduce(g)\n }\n static reducePointwise(g, precModel) {\n const reducer = new GeometryPrecisionReducer(precModel)\n reducer.setPointwise(true)\n return reducer.reduce(g)\n }\n fixPolygonalTopology(geom) {\n let geomToBuffer = geom\n if (!this._changePrecisionModel) \n geomToBuffer = this.changePM(geom, this._targetPM)\n \n const bufGeom = BufferOp.bufferOp(geomToBuffer, 0)\n return bufGeom\n }\n reducePointwise(geom) {\n let geomEdit = null\n if (this._changePrecisionModel) {\n const newFactory = this.createFactory(geom.getFactory(), this._targetPM)\n geomEdit = new GeometryEditor(newFactory)\n } else {\n geomEdit = new GeometryEditor()\n }\n let finalRemoveCollapsed = this._removeCollapsed\n if (geom.getDimension() >= 2) finalRemoveCollapsed = true\n const reduceGeom = geomEdit.edit(geom, new PrecisionReducerCoordinateOperation(this._targetPM, finalRemoveCollapsed))\n return reduceGeom\n }\n changePM(geom, newPM) {\n const geomEditor = this.createEditor(geom.getFactory(), newPM)\n return geomEditor.edit(geom, new GeometryEditor.NoOpGeometryOperation())\n }\n setRemoveCollapsedComponents(removeCollapsed) {\n this._removeCollapsed = removeCollapsed\n }\n createFactory(inputFactory, pm) {\n const newFactory = new GeometryFactory(pm, inputFactory.getSRID(), inputFactory.getCoordinateSequenceFactory())\n return newFactory\n }\n setChangePrecisionModel(changePrecisionModel) {\n this._changePrecisionModel = changePrecisionModel\n }\n reduce(geom) {\n const reducePW = this.reducePointwise(geom)\n if (this._isPointwise) return reducePW\n if (!hasInterface(reducePW, Polygonal)) return reducePW\n if (IsValidOp.isValid(reducePW)) return reducePW\n return this.fixPolygonalTopology(reducePW)\n }\n setPointwise(isPointwise) {\n this._isPointwise = isPointwise\n }\n createEditor(geomFactory, newPM) {\n if (geomFactory.getPrecisionModel() === newPM) return new GeometryEditor()\n const newFactory = this.createFactory(geomFactory, newPM)\n const geomEdit = new GeometryEditor(newFactory)\n return geomEdit\n }\n}\n","import StringBuffer from '../../../../../java/lang/StringBuffer.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport GeometryLocation from './GeometryLocation.js'\nimport Double from '../../../../../java/lang/Double.js'\nimport LineSegment from '../../geom/LineSegment.js'\nimport Envelope from '../../geom/Envelope.js'\nimport Distance from '../../algorithm/Distance.js'\nexport default class FacetSequence {\n constructor() {\n FacetSequence.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geom = null\n this._pts = null\n this._start = null\n this._end = null\n if (arguments.length === 2) {\n const pts = arguments[0], start = arguments[1]\n this._pts = pts\n this._start = start\n this._end = start + 1\n } else if (arguments.length === 3) {\n const pts = arguments[0], start = arguments[1], end = arguments[2]\n this._pts = pts\n this._start = start\n this._end = end\n } else if (arguments.length === 4) {\n const geom = arguments[0], pts = arguments[1], start = arguments[2], end = arguments[3]\n this._geom = geom\n this._pts = pts\n this._start = start\n this._end = end\n }\n }\n computeDistanceLineLine(facetSeq, locs) {\n let minDistance = Double.MAX_VALUE\n for (let i = this._start; i < this._end - 1; i++) {\n const p0 = this._pts.getCoordinate(i)\n const p1 = this._pts.getCoordinate(i + 1)\n for (let j = facetSeq._start; j < facetSeq._end - 1; j++) {\n const q0 = facetSeq._pts.getCoordinate(j)\n const q1 = facetSeq._pts.getCoordinate(j + 1)\n const dist = Distance.segmentToSegment(p0, p1, q0, q1)\n if (dist < minDistance) {\n minDistance = dist\n if (locs !== null) this.updateNearestLocationsLineLine(i, p0, p1, facetSeq, j, q0, q1, locs)\n if (minDistance <= 0.0) return minDistance\n }\n }\n }\n return minDistance\n }\n updateNearestLocationsPointLine(pt, facetSeq, i, q0, q1, locs) {\n locs[0] = new GeometryLocation(this._geom, this._start, new Coordinate(pt))\n const seg = new LineSegment(q0, q1)\n const segClosestPoint = seg.closestPoint(pt)\n locs[1] = new GeometryLocation(facetSeq._geom, i, new Coordinate(segClosestPoint))\n }\n size() {\n return this._end - this._start\n }\n getCoordinate(index) {\n return this._pts.getCoordinate(this._start + index)\n }\n nearestLocations(facetSeq) {\n const isPoint = this.isPoint()\n const isPointOther = facetSeq.isPoint()\n const locs = new Array(2).fill(null)\n if (isPoint && isPointOther) {\n const pt = this._pts.getCoordinate(this._start)\n const seqPt = facetSeq._pts.getCoordinate(facetSeq._start)\n locs[0] = new GeometryLocation(this._geom, this._start, new Coordinate(pt))\n locs[1] = new GeometryLocation(facetSeq._geom, facetSeq._start, new Coordinate(seqPt))\n } else if (isPoint) {\n const pt = this._pts.getCoordinate(this._start)\n this.computeDistancePointLine(pt, facetSeq, locs)\n } else if (isPointOther) {\n const seqPt = facetSeq._pts.getCoordinate(facetSeq._start)\n this.computeDistancePointLine(seqPt, this, locs)\n const tmp = locs[0]\n locs[0] = locs[1]\n locs[1] = tmp\n } else {\n this.computeDistanceLineLine(facetSeq, locs)\n }\n return locs\n }\n getEnvelope() {\n const env = new Envelope()\n for (let i = this._start; i < this._end; i++) \n env.expandToInclude(this._pts.getX(i), this._pts.getY(i))\n \n return env\n }\n updateNearestLocationsLineLine(i, p0, p1, facetSeq, j, q0, q1, locs) {\n const seg0 = new LineSegment(p0, p1)\n const seg1 = new LineSegment(q0, q1)\n const closestPt = seg0.closestPoints(seg1)\n locs[0] = new GeometryLocation(this._geom, i, new Coordinate(closestPt[0]))\n locs[1] = new GeometryLocation(facetSeq._geom, j, new Coordinate(closestPt[1]))\n }\n toString() {\n const buf = new StringBuffer()\n buf.append('LINESTRING ( ')\n const p = new Coordinate()\n for (let i = this._start; i < this._end; i++) {\n if (i > this._start) buf.append(', ')\n this._pts.getCoordinate(i, p)\n buf.append(p.x + ' ' + p.y)\n }\n buf.append(' )')\n return buf.toString()\n }\n computeDistancePointLine(pt, facetSeq, locs) {\n let minDistance = Double.MAX_VALUE\n for (let i = facetSeq._start; i < facetSeq._end - 1; i++) {\n const q0 = facetSeq._pts.getCoordinate(i)\n const q1 = facetSeq._pts.getCoordinate(i + 1)\n const dist = Distance.pointToSegment(pt, q0, q1)\n if (dist < minDistance) {\n minDistance = dist\n if (locs !== null) this.updateNearestLocationsPointLine(pt, facetSeq, i, q0, q1, locs)\n if (minDistance <= 0.0) return minDistance\n }\n }\n return minDistance\n }\n isPoint() {\n return this._end - this._start === 1\n }\n distance(facetSeq) {\n const isPoint = this.isPoint()\n const isPointOther = facetSeq.isPoint()\n let distance = null\n if (isPoint && isPointOther) {\n const pt = this._pts.getCoordinate(this._start)\n const seqPt = facetSeq._pts.getCoordinate(facetSeq._start)\n distance = pt.distance(seqPt)\n } else if (isPoint) {\n const pt = this._pts.getCoordinate(this._start)\n distance = this.computeDistancePointLine(pt, facetSeq, null)\n } else if (isPointOther) {\n const seqPt = facetSeq._pts.getCoordinate(facetSeq._start)\n distance = this.computeDistancePointLine(seqPt, this, null)\n } else {\n distance = this.computeDistanceLineLine(facetSeq, null)\n }\n return distance\n }\n}\n","import LineString from '../../geom/LineString.js'\nimport FacetSequence from './FacetSequence.js'\nimport STRtree from '../../index/strtree/STRtree.js'\nimport Point from '../../geom/Point.js'\nimport GeometryComponentFilter from '../../geom/GeometryComponentFilter.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nexport default class FacetSequenceTreeBuilder {\n static addFacetSequences(geom, pts, sections) {\n let i = 0\n const size = pts.size()\n while (i <= size - 1) {\n let end = i + FacetSequenceTreeBuilder.FACET_SEQUENCE_SIZE + 1\n if (end >= size - 1) end = size\n const sect = new FacetSequence(geom, pts, i, end)\n sections.add(sect)\n i = i + FacetSequenceTreeBuilder.FACET_SEQUENCE_SIZE\n }\n }\n static computeFacetSequences(g) {\n const sections = new ArrayList()\n g.apply(new (class {\n get interfaces_() {\n return [GeometryComponentFilter]\n }\n filter(geom) {\n let seq = null\n if (geom instanceof LineString) {\n seq = geom.getCoordinateSequence()\n FacetSequenceTreeBuilder.addFacetSequences(geom, seq, sections)\n } else if (geom instanceof Point) {\n seq = geom.getCoordinateSequence()\n FacetSequenceTreeBuilder.addFacetSequences(geom, seq, sections)\n }\n }\n })())\n return sections\n }\n static build(g) {\n const tree = new STRtree(FacetSequenceTreeBuilder.STR_TREE_NODE_CAPACITY)\n const sections = FacetSequenceTreeBuilder.computeFacetSequences(g)\n for (let i = sections.iterator(); i.hasNext(); ) {\n const section = i.next()\n tree.insert(section.getEnvelope(), section)\n }\n tree.build()\n return tree\n }\n}\nFacetSequenceTreeBuilder.FACET_SEQUENCE_SIZE = 6\nFacetSequenceTreeBuilder.STR_TREE_NODE_CAPACITY = 4\n","import ItemBoundable from '../index/strtree/ItemBoundable.js'\nimport FacetSequence from '../operation/distance/FacetSequence.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport Double from '../../../../java/lang/Double.js'\nimport LineSegment from '../geom/LineSegment.js'\nimport FacetSequenceTreeBuilder from '../operation/distance/FacetSequenceTreeBuilder.js'\nimport Distance from '../algorithm/Distance.js'\nimport ItemDistance from '../index/strtree/ItemDistance.js'\nexport default class MinimumClearance {\n constructor() {\n MinimumClearance.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputGeom = null\n this._minClearance = null\n this._minClearancePts = null\n const geom = arguments[0]\n this._inputGeom = geom\n }\n static getLine(g) {\n const rp = new MinimumClearance(g)\n return rp.getLine()\n }\n static getDistance(g) {\n const rp = new MinimumClearance(g)\n return rp.getDistance()\n }\n getLine() {\n this.compute()\n if (this._minClearancePts === null || this._minClearancePts[0] === null) return this._inputGeom.getFactory().createLineString()\n return this._inputGeom.getFactory().createLineString(this._minClearancePts)\n }\n compute() {\n if (this._minClearancePts !== null) return null\n this._minClearancePts = new Array(2).fill(null)\n this._minClearance = Double.MAX_VALUE\n if (this._inputGeom.isEmpty()) \n return null\n \n const geomTree = FacetSequenceTreeBuilder.build(this._inputGeom)\n const nearest = geomTree.nearestNeighbour(new MinClearanceDistance())\n const mcd = new MinClearanceDistance()\n this._minClearance = mcd.distance(nearest[0], nearest[1])\n this._minClearancePts = mcd.getCoordinates()\n }\n getDistance() {\n this.compute()\n return this._minClearance\n }\n}\nclass MinClearanceDistance {\n constructor() {\n MinClearanceDistance.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._minDist = Double.MAX_VALUE\n this._minPts = new Array(2).fill(null)\n }\n vertexDistance(fs1, fs2) {\n for (let i1 = 0; i1 < fs1.size(); i1++) \n for (let i2 = 0; i2 < fs2.size(); i2++) {\n const p1 = fs1.getCoordinate(i1)\n const p2 = fs2.getCoordinate(i2)\n if (!p1.equals2D(p2)) {\n const d = p1.distance(p2)\n if (d < this._minDist) {\n this._minDist = d\n this._minPts[0] = p1\n this._minPts[1] = p2\n if (d === 0.0) return d\n }\n }\n }\n \n return this._minDist\n }\n getCoordinates() {\n return this._minPts\n }\n segmentDistance(fs1, fs2) {\n for (let i1 = 0; i1 < fs1.size(); i1++) \n for (let i2 = 1; i2 < fs2.size(); i2++) {\n const p = fs1.getCoordinate(i1)\n const seg0 = fs2.getCoordinate(i2 - 1)\n const seg1 = fs2.getCoordinate(i2)\n if (!(p.equals2D(seg0) || p.equals2D(seg1))) {\n const d = Distance.pointToSegment(p, seg0, seg1)\n if (d < this._minDist) {\n this._minDist = d\n this.updatePts(p, seg0, seg1)\n if (d === 0.0) return d\n }\n }\n }\n \n return this._minDist\n }\n distance() {\n if (arguments[0] instanceof ItemBoundable && arguments[1] instanceof ItemBoundable) {\n const b1 = arguments[0], b2 = arguments[1]\n const fs1 = b1.getItem()\n const fs2 = b2.getItem()\n this._minDist = Double.MAX_VALUE\n return this.distance(fs1, fs2)\n } else if (arguments[0] instanceof FacetSequence && arguments[1] instanceof FacetSequence) {\n const fs1 = arguments[0], fs2 = arguments[1]\n this.vertexDistance(fs1, fs2)\n if (fs1.size() === 1 && fs2.size() === 1) return this._minDist\n if (this._minDist <= 0.0) return this._minDist\n this.segmentDistance(fs1, fs2)\n if (this._minDist <= 0.0) return this._minDist\n this.segmentDistance(fs2, fs1)\n return this._minDist\n }\n }\n updatePts(p, seg0, seg1) {\n this._minPts[0] = p\n const seg = new LineSegment(seg0, seg1)\n this._minPts[1] = new Coordinate(seg.closestPoint(p))\n }\n get interfaces_() {\n return [ItemDistance]\n }\n}\nMinimumClearance.MinClearanceDistance = MinClearanceDistance\n","import CoordinateFilter from '../geom/CoordinateFilter.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport Double from '../../../../java/lang/Double.js'\nimport LineSegment from '../geom/LineSegment.js'\nimport CoordinateSequenceFilter from '../geom/CoordinateSequenceFilter.js'\nimport Distance from '../algorithm/Distance.js'\nexport default class SimpleMinimumClearance {\n constructor() {\n SimpleMinimumClearance.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputGeom = null\n this._minClearance = null\n this._minClearancePts = null\n const geom = arguments[0]\n this._inputGeom = geom\n }\n static getLine(g) {\n const rp = new SimpleMinimumClearance(g)\n return rp.getLine()\n }\n static getDistance(g) {\n const rp = new SimpleMinimumClearance(g)\n return rp.getDistance()\n }\n getLine() {\n this.compute()\n return this._inputGeom.getFactory().createLineString(this._minClearancePts)\n }\n updateClearance() {\n if (arguments.length === 3) {\n const candidateValue = arguments[0], p0 = arguments[1], p1 = arguments[2]\n if (candidateValue < this._minClearance) {\n this._minClearance = candidateValue\n this._minClearancePts[0] = new Coordinate(p0)\n this._minClearancePts[1] = new Coordinate(p1)\n }\n } else if (arguments.length === 4) {\n const candidateValue = arguments[0], p = arguments[1], seg0 = arguments[2], seg1 = arguments[3]\n if (candidateValue < this._minClearance) {\n this._minClearance = candidateValue\n this._minClearancePts[0] = new Coordinate(p)\n const seg = new LineSegment(seg0, seg1)\n this._minClearancePts[1] = new Coordinate(seg.closestPoint(p))\n }\n }\n }\n compute() {\n if (this._minClearancePts !== null) return null\n this._minClearancePts = new Array(2).fill(null)\n this._minClearance = Double.MAX_VALUE\n this._inputGeom.apply(new VertexCoordinateFilter(this))\n }\n getDistance() {\n this.compute()\n return this._minClearance\n }\n}\nclass VertexCoordinateFilter {\n constructor() {\n VertexCoordinateFilter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.smc = null\n const smc = arguments[0]\n this.smc = smc\n }\n filter(coord) {\n this.smc._inputGeom.apply(new ComputeMCCoordinateSequenceFilter(this.smc, coord))\n }\n get interfaces_() {\n return [CoordinateFilter]\n }\n}\nclass ComputeMCCoordinateSequenceFilter {\n constructor() {\n ComputeMCCoordinateSequenceFilter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.smc = null\n this._queryPt = null\n const smc = arguments[0], queryPt = arguments[1]\n this.smc = smc\n this._queryPt = queryPt\n }\n isGeometryChanged() {\n return false\n }\n checkVertexDistance(vertex) {\n const vertexDist = vertex.distance(this._queryPt)\n if (vertexDist > 0) \n this.smc.updateClearance(vertexDist, this._queryPt, vertex)\n \n }\n filter(seq, i) {\n this.checkVertexDistance(seq.getCoordinate(i))\n if (i > 0) \n this.checkSegmentDistance(seq.getCoordinate(i - 1), seq.getCoordinate(i))\n \n }\n checkSegmentDistance(seg0, seg1) {\n if (this._queryPt.equals2D(seg0) || this._queryPt.equals2D(seg1)) return null\n const segDist = Distance.pointToSegment(this._queryPt, seg1, seg0)\n if (segDist > 0) this.smc.updateClearance(segDist, this._queryPt, seg1, seg0)\n }\n isDone() {\n return false\n }\n get interfaces_() {\n return [CoordinateSequenceFilter]\n }\n}\nSimpleMinimumClearance.VertexCoordinateFilter = VertexCoordinateFilter\nSimpleMinimumClearance.ComputeMCCoordinateSequenceFilter = ComputeMCCoordinateSequenceFilter\n","import CommonBitsOp from './CommonBitsOp.js'\nimport RuntimeException from '../../../../java/lang/RuntimeException.js'\nexport default class EnhancedPrecisionOp {\n static union(geom0, geom1) {\n let originalEx = null\n try {\n const result = geom0.union(geom1)\n return result\n } catch (ex) {\n if (ex instanceof RuntimeException) \n originalEx = ex\n else throw ex\n } finally {}\n try {\n const cbo = new CommonBitsOp(true)\n const resultEP = cbo.union(geom0, geom1)\n if (!resultEP.isValid()) throw originalEx\n return resultEP\n } catch (ex2) {\n if (ex2 instanceof RuntimeException) \n throw originalEx\n else throw ex2\n } finally {}\n }\n static intersection(geom0, geom1) {\n let originalEx = null\n try {\n const result = geom0.intersection(geom1)\n return result\n } catch (ex) {\n if (ex instanceof RuntimeException) \n originalEx = ex\n else throw ex\n } finally {}\n try {\n const cbo = new CommonBitsOp(true)\n const resultEP = cbo.intersection(geom0, geom1)\n if (!resultEP.isValid()) throw originalEx\n return resultEP\n } catch (ex2) {\n if (ex2 instanceof RuntimeException) \n throw originalEx\n else throw ex2\n } finally {}\n }\n static buffer(geom, distance) {\n let originalEx = null\n try {\n const result = geom.buffer(distance)\n return result\n } catch (ex) {\n if (ex instanceof RuntimeException) \n originalEx = ex\n else throw ex\n } finally {}\n try {\n const cbo = new CommonBitsOp(true)\n const resultEP = cbo.buffer(geom, distance)\n if (!resultEP.isValid()) throw originalEx\n return resultEP\n } catch (ex2) {\n if (ex2 instanceof RuntimeException) \n throw originalEx\n else throw ex2\n } finally {}\n }\n static symDifference(geom0, geom1) {\n let originalEx = null\n try {\n const result = geom0.symDifference(geom1)\n return result\n } catch (ex) {\n if (ex instanceof RuntimeException) \n originalEx = ex\n else throw ex\n } finally {}\n try {\n const cbo = new CommonBitsOp(true)\n const resultEP = cbo.symDifference(geom0, geom1)\n if (!resultEP.isValid()) throw originalEx\n return resultEP\n } catch (ex2) {\n if (ex2 instanceof RuntimeException) \n throw originalEx\n else throw ex2\n } finally {}\n }\n static difference(geom0, geom1) {\n let originalEx = null\n try {\n const result = geom0.difference(geom1)\n return result\n } catch (ex) {\n if (ex instanceof RuntimeException) \n originalEx = ex\n else throw ex\n } finally {}\n try {\n const cbo = new CommonBitsOp(true)\n const resultEP = cbo.difference(geom0, geom1)\n if (!resultEP.isValid()) throw originalEx\n return resultEP\n } catch (ex2) {\n if (ex2 instanceof RuntimeException) \n throw originalEx\n else throw ex2\n } finally {}\n }\n}\n","import CoordinateList from '../geom/CoordinateList.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport LineSegment from '../geom/LineSegment.js'\nexport default class DouglasPeuckerLineSimplifier {\n constructor() {\n DouglasPeuckerLineSimplifier.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pts = null\n this._usePt = null\n this._distanceTolerance = null\n this._seg = new LineSegment()\n const pts = arguments[0]\n this._pts = pts\n }\n static simplify(pts, distanceTolerance) {\n const simp = new DouglasPeuckerLineSimplifier(pts)\n simp.setDistanceTolerance(distanceTolerance)\n return simp.simplify()\n }\n simplifySection(i, j) {\n if (i + 1 === j) \n return null\n \n this._seg.p0 = this._pts[i]\n this._seg.p1 = this._pts[j]\n let maxDistance = -1.0\n let maxIndex = i\n for (let k = i + 1; k < j; k++) {\n const distance = this._seg.distance(this._pts[k])\n if (distance > maxDistance) {\n maxDistance = distance\n maxIndex = k\n }\n }\n if (maxDistance <= this._distanceTolerance) {\n for (let k = i + 1; k < j; k++) \n this._usePt[k] = false\n \n } else {\n this.simplifySection(i, maxIndex)\n this.simplifySection(maxIndex, j)\n }\n }\n setDistanceTolerance(distanceTolerance) {\n this._distanceTolerance = distanceTolerance\n }\n simplify() {\n this._usePt = new Array(this._pts.length).fill(null)\n for (let i = 0; i < this._pts.length; i++) \n this._usePt[i] = true\n \n this.simplifySection(0, this._pts.length - 1)\n const coordList = new CoordinateList()\n for (let i = 0; i < this._pts.length; i++) \n if (this._usePt[i]) coordList.add(new Coordinate(this._pts[i]))\n \n return coordList.toCoordinateArray()\n }\n}\n","import DouglasPeuckerLineSimplifier from './DouglasPeuckerLineSimplifier.js'\nimport GeometryTransformer from '../geom/util/GeometryTransformer.js'\nimport IllegalArgumentException from '../../../../java/lang/IllegalArgumentException.js'\nimport Polygon from '../geom/Polygon.js'\nimport LinearRing from '../geom/LinearRing.js'\nimport MultiPolygon from '../geom/MultiPolygon.js'\nexport default class DouglasPeuckerSimplifier {\n constructor() {\n DouglasPeuckerSimplifier.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputGeom = null\n this._distanceTolerance = null\n this._isEnsureValidTopology = true\n const inputGeom = arguments[0]\n this._inputGeom = inputGeom\n }\n static simplify(geom, distanceTolerance) {\n const tss = new DouglasPeuckerSimplifier(geom)\n tss.setDistanceTolerance(distanceTolerance)\n return tss.getResultGeometry()\n }\n setEnsureValid(isEnsureValidTopology) {\n this._isEnsureValidTopology = isEnsureValidTopology\n }\n getResultGeometry() {\n if (this._inputGeom.isEmpty()) return this._inputGeom.copy()\n return new DPTransformer(this._isEnsureValidTopology, this._distanceTolerance).transform(this._inputGeom)\n }\n setDistanceTolerance(distanceTolerance) {\n if (distanceTolerance < 0.0) throw new IllegalArgumentException('Tolerance must be non-negative')\n this._distanceTolerance = distanceTolerance\n }\n}\nclass DPTransformer extends GeometryTransformer {\n constructor() {\n super()\n DPTransformer.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._isEnsureValidTopology = true\n this._distanceTolerance = null\n const isEnsureValidTopology = arguments[0], distanceTolerance = arguments[1]\n this._isEnsureValidTopology = isEnsureValidTopology\n this._distanceTolerance = distanceTolerance\n }\n transformPolygon(geom, parent) {\n if (geom.isEmpty()) return null\n const rawGeom = super.transformPolygon.call(this, geom, parent)\n if (parent instanceof MultiPolygon) \n return rawGeom\n \n return this.createValidArea(rawGeom)\n }\n createValidArea(rawAreaGeom) {\n if (this._isEnsureValidTopology) return rawAreaGeom.buffer(0.0)\n return rawAreaGeom\n }\n transformCoordinates(coords, parent) {\n const inputPts = coords.toCoordinateArray()\n let newPts = null\n if (inputPts.length === 0) \n newPts = new Array(0).fill(null)\n else \n newPts = DouglasPeuckerLineSimplifier.simplify(inputPts, this._distanceTolerance)\n \n return this._factory.getCoordinateSequenceFactory().create(newPts)\n }\n transformMultiPolygon(geom, parent) {\n const rawGeom = super.transformMultiPolygon.call(this, geom, parent)\n return this.createValidArea(rawGeom)\n }\n transformLinearRing(geom, parent) {\n const removeDegenerateRings = parent instanceof Polygon\n const simpResult = super.transformLinearRing.call(this, geom, parent)\n if (removeDegenerateRings && !(simpResult instanceof LinearRing)) return null\n \n return simpResult\n }\n}\nDouglasPeuckerSimplifier.DPTransformer = DPTransformer\n","import LineSegment from '../geom/LineSegment.js'\nexport default class TaggedLineSegment extends LineSegment {\n constructor() {\n super()\n TaggedLineSegment.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._parent = null\n this._index = null\n if (arguments.length === 2) {\n const p0 = arguments[0], p1 = arguments[1]\n TaggedLineSegment.constructor_.call(this, p0, p1, null, -1)\n } else if (arguments.length === 4) {\n const p0 = arguments[0], p1 = arguments[1], parent = arguments[2], index = arguments[3]\n LineSegment.constructor_.call(this, p0, p1)\n this._parent = parent\n this._index = index\n }\n }\n getIndex() {\n return this._index\n }\n getParent() {\n return this._parent\n }\n}\n","import TaggedLineSegment from './TaggedLineSegment.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nexport default class TaggedLineString {\n constructor() {\n TaggedLineString.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._parentLine = null\n this._segs = null\n this._resultSegs = new ArrayList()\n this._minimumSize = null\n if (arguments.length === 1) {\n const parentLine = arguments[0]\n TaggedLineString.constructor_.call(this, parentLine, 2)\n } else if (arguments.length === 2) {\n const parentLine = arguments[0], minimumSize = arguments[1]\n this._parentLine = parentLine\n this._minimumSize = minimumSize\n this.init()\n }\n }\n static extractCoordinates(segs) {\n const pts = new Array(segs.size() + 1).fill(null)\n let seg = null\n for (let i = 0; i < segs.size(); i++) {\n seg = segs.get(i)\n pts[i] = seg.p0\n }\n pts[pts.length - 1] = seg.p1\n return pts\n }\n addToResult(seg) {\n this._resultSegs.add(seg)\n }\n asLineString() {\n return this._parentLine.getFactory().createLineString(TaggedLineString.extractCoordinates(this._resultSegs))\n }\n getResultSize() {\n const resultSegsSize = this._resultSegs.size()\n return resultSegsSize === 0 ? 0 : resultSegsSize + 1\n }\n getParent() {\n return this._parentLine\n }\n getSegment(i) {\n return this._segs[i]\n }\n getParentCoordinates() {\n return this._parentLine.getCoordinates()\n }\n getMinimumSize() {\n return this._minimumSize\n }\n asLinearRing() {\n return this._parentLine.getFactory().createLinearRing(TaggedLineString.extractCoordinates(this._resultSegs))\n }\n getSegments() {\n return this._segs\n }\n init() {\n const pts = this._parentLine.getCoordinates()\n this._segs = new Array(pts.length - 1).fill(null)\n for (let i = 0; i < pts.length - 1; i++) {\n const seg = new TaggedLineSegment(pts[i], pts[i + 1], this._parentLine, i)\n this._segs[i] = seg\n }\n }\n getResultCoordinates() {\n return TaggedLineString.extractCoordinates(this._resultSegs)\n }\n}\n","import Quadtree from '../index/quadtree/Quadtree.js'\nimport ItemVisitor from '../index/ItemVisitor.js'\nimport LineSegment from '../geom/LineSegment.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport Envelope from '../geom/Envelope.js'\nimport TaggedLineString from './TaggedLineString.js'\nexport default class LineSegmentIndex {\n constructor() {\n LineSegmentIndex.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._index = new Quadtree()\n }\n remove(seg) {\n this._index.remove(new Envelope(seg.p0, seg.p1), seg)\n }\n add() {\n if (arguments[0] instanceof TaggedLineString) {\n const line = arguments[0]\n const segs = line.getSegments()\n for (let i = 0; i < segs.length; i++) {\n const seg = segs[i]\n this.add(seg)\n }\n } else if (arguments[0] instanceof LineSegment) {\n const seg = arguments[0]\n this._index.insert(new Envelope(seg.p0, seg.p1), seg)\n }\n }\n query(querySeg) {\n const env = new Envelope(querySeg.p0, querySeg.p1)\n const visitor = new LineSegmentVisitor(querySeg)\n this._index.query(env, visitor)\n const itemsFound = visitor.getItems()\n return itemsFound\n }\n}\nclass LineSegmentVisitor {\n constructor() {\n LineSegmentVisitor.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._querySeg = null\n this._items = new ArrayList()\n const querySeg = arguments[0]\n this._querySeg = querySeg\n }\n visitItem(item) {\n const seg = item\n if (Envelope.intersects(seg.p0, seg.p1, this._querySeg.p0, this._querySeg.p1)) this._items.add(item)\n }\n getItems() {\n return this._items\n }\n get interfaces_() {\n return [ItemVisitor]\n }\n}\n","import LineSegment from '../geom/LineSegment.js'\nimport LineSegmentIndex from './LineSegmentIndex.js'\nimport RobustLineIntersector from '../algorithm/RobustLineIntersector.js'\nexport default class TaggedLineStringSimplifier {\n constructor() {\n TaggedLineStringSimplifier.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._li = new RobustLineIntersector()\n this._inputIndex = new LineSegmentIndex()\n this._outputIndex = new LineSegmentIndex()\n this._line = null\n this._linePts = null\n this._distanceTolerance = 0.0\n const inputIndex = arguments[0], outputIndex = arguments[1]\n this._inputIndex = inputIndex\n this._outputIndex = outputIndex\n }\n static isInLineSection(line, sectionIndex, seg) {\n if (seg.getParent() !== line.getParent()) return false\n const segIndex = seg.getIndex()\n if (segIndex >= sectionIndex[0] && segIndex < sectionIndex[1]) return true\n return false\n }\n flatten(start, end) {\n const p0 = this._linePts[start]\n const p1 = this._linePts[end]\n const newSeg = new LineSegment(p0, p1)\n this.remove(this._line, start, end)\n this._outputIndex.add(newSeg)\n return newSeg\n }\n hasBadIntersection(parentLine, sectionIndex, candidateSeg) {\n if (this.hasBadOutputIntersection(candidateSeg)) return true\n if (this.hasBadInputIntersection(parentLine, sectionIndex, candidateSeg)) return true\n return false\n }\n setDistanceTolerance(distanceTolerance) {\n this._distanceTolerance = distanceTolerance\n }\n simplifySection(i, j, depth) {\n depth += 1\n const sectionIndex = new Array(2).fill(null)\n if (i + 1 === j) {\n const newSeg = this._line.getSegment(i)\n this._line.addToResult(newSeg)\n return null\n }\n let isValidToSimplify = true\n if (this._line.getResultSize() < this._line.getMinimumSize()) {\n const worstCaseSize = depth + 1\n if (worstCaseSize < this._line.getMinimumSize()) isValidToSimplify = false\n }\n const distance = new Array(1).fill(null)\n const furthestPtIndex = this.findFurthestPoint(this._linePts, i, j, distance)\n if (distance[0] > this._distanceTolerance) isValidToSimplify = false\n const candidateSeg = new LineSegment()\n candidateSeg.p0 = this._linePts[i]\n candidateSeg.p1 = this._linePts[j]\n sectionIndex[0] = i\n sectionIndex[1] = j\n if (this.hasBadIntersection(this._line, sectionIndex, candidateSeg)) isValidToSimplify = false\n if (isValidToSimplify) {\n const newSeg = this.flatten(i, j)\n this._line.addToResult(newSeg)\n return null\n }\n this.simplifySection(i, furthestPtIndex, depth)\n this.simplifySection(furthestPtIndex, j, depth)\n }\n hasBadOutputIntersection(candidateSeg) {\n const querySegs = this._outputIndex.query(candidateSeg)\n for (let i = querySegs.iterator(); i.hasNext(); ) {\n const querySeg = i.next()\n if (this.hasInteriorIntersection(querySeg, candidateSeg)) \n return true\n \n }\n return false\n }\n findFurthestPoint(pts, i, j, maxDistance) {\n const seg = new LineSegment()\n seg.p0 = pts[i]\n seg.p1 = pts[j]\n let maxDist = -1.0\n let maxIndex = i\n for (let k = i + 1; k < j; k++) {\n const midPt = pts[k]\n const distance = seg.distance(midPt)\n if (distance > maxDist) {\n maxDist = distance\n maxIndex = k\n }\n }\n maxDistance[0] = maxDist\n return maxIndex\n }\n simplify(line) {\n this._line = line\n this._linePts = line.getParentCoordinates()\n this.simplifySection(0, this._linePts.length - 1, 0)\n }\n remove(line, start, end) {\n for (let i = start; i < end; i++) {\n const seg = line.getSegment(i)\n this._inputIndex.remove(seg)\n }\n }\n hasInteriorIntersection(seg0, seg1) {\n this._li.computeIntersection(seg0.p0, seg0.p1, seg1.p0, seg1.p1)\n return this._li.isInteriorIntersection()\n }\n hasBadInputIntersection(parentLine, sectionIndex, candidateSeg) {\n const querySegs = this._inputIndex.query(candidateSeg)\n for (let i = querySegs.iterator(); i.hasNext(); ) {\n const querySeg = i.next()\n if (this.hasInteriorIntersection(querySeg, candidateSeg)) {\n if (TaggedLineStringSimplifier.isInLineSection(parentLine, sectionIndex, querySeg)) continue\n return true\n }\n }\n return false\n }\n}\n","import TaggedLineStringSimplifier from './TaggedLineStringSimplifier.js'\nimport LineSegmentIndex from './LineSegmentIndex.js'\nexport default class TaggedLinesSimplifier {\n constructor() {\n TaggedLinesSimplifier.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputIndex = new LineSegmentIndex()\n this._outputIndex = new LineSegmentIndex()\n this._distanceTolerance = 0.0\n }\n setDistanceTolerance(distanceTolerance) {\n this._distanceTolerance = distanceTolerance\n }\n simplify(taggedLines) {\n for (let i = taggedLines.iterator(); i.hasNext(); ) \n this._inputIndex.add(i.next())\n \n for (let i = taggedLines.iterator(); i.hasNext(); ) {\n const tlss = new TaggedLineStringSimplifier(this._inputIndex, this._outputIndex)\n tlss.setDistanceTolerance(this._distanceTolerance)\n tlss.simplify(i.next())\n }\n }\n}\n","import LineString from '../geom/LineString.js'\nimport HashMap from '../../../../java/util/HashMap.js'\nimport GeometryTransformer from '../geom/util/GeometryTransformer.js'\nimport TaggedLinesSimplifier from './TaggedLinesSimplifier.js'\nimport IllegalArgumentException from '../../../../java/lang/IllegalArgumentException.js'\nimport GeometryComponentFilter from '../geom/GeometryComponentFilter.js'\nimport TaggedLineString from './TaggedLineString.js'\nexport default class TopologyPreservingSimplifier {\n constructor() {\n TopologyPreservingSimplifier.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputGeom = null\n this._lineSimplifier = new TaggedLinesSimplifier()\n this._linestringMap = null\n const inputGeom = arguments[0]\n this._inputGeom = inputGeom\n }\n static simplify(geom, distanceTolerance) {\n const tss = new TopologyPreservingSimplifier(geom)\n tss.setDistanceTolerance(distanceTolerance)\n return tss.getResultGeometry()\n }\n getResultGeometry() {\n if (this._inputGeom.isEmpty()) return this._inputGeom.copy()\n this._linestringMap = new HashMap()\n this._inputGeom.apply(new LineStringMapBuilderFilter(this))\n this._lineSimplifier.simplify(this._linestringMap.values())\n const result = new LineStringTransformer(this._linestringMap).transform(this._inputGeom)\n return result\n }\n setDistanceTolerance(distanceTolerance) {\n if (distanceTolerance < 0.0) throw new IllegalArgumentException('Tolerance must be non-negative')\n this._lineSimplifier.setDistanceTolerance(distanceTolerance)\n }\n}\nclass LineStringTransformer extends GeometryTransformer {\n constructor() {\n super()\n LineStringTransformer.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._linestringMap = null\n const linestringMap = arguments[0]\n this._linestringMap = linestringMap\n }\n transformCoordinates(coords, parent) {\n if (coords.size() === 0) return null\n if (parent instanceof LineString) {\n const taggedLine = this._linestringMap.get(parent)\n return this.createCoordinateSequence(taggedLine.getResultCoordinates())\n }\n return super.transformCoordinates.call(this, coords, parent)\n }\n}\nclass LineStringMapBuilderFilter {\n constructor() {\n LineStringMapBuilderFilter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.tps = null\n const tps = arguments[0]\n this.tps = tps\n }\n filter(geom) {\n if (geom instanceof LineString) {\n const line = geom\n if (line.isEmpty()) return null\n const minSize = line.isClosed() ? 4 : 2\n const taggedLine = new TaggedLineString(line, minSize)\n this.tps._linestringMap.put(line, taggedLine)\n }\n }\n get interfaces_() {\n return [GeometryComponentFilter]\n }\n}\nTopologyPreservingSimplifier.LineStringTransformer = LineStringTransformer\nTopologyPreservingSimplifier.LineStringMapBuilderFilter = LineStringMapBuilderFilter\n","import CoordinateList from '../geom/CoordinateList.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport Double from '../../../../java/lang/Double.js'\nimport Triangle from '../geom/Triangle.js'\nexport default class VWLineSimplifier {\n constructor() {\n VWLineSimplifier.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pts = null\n this._tolerance = null\n const pts = arguments[0], distanceTolerance = arguments[1]\n this._pts = pts\n this._tolerance = distanceTolerance * distanceTolerance\n }\n static simplify(pts, distanceTolerance) {\n const simp = new VWLineSimplifier(pts, distanceTolerance)\n return simp.simplify()\n }\n simplifyVertex(vwLine) {\n let curr = vwLine\n let minArea = curr.getArea()\n let minVertex = null\n while (curr !== null) {\n const area = curr.getArea()\n if (area < minArea) {\n minArea = area\n minVertex = curr\n }\n curr = curr._next\n }\n if (minVertex !== null && minArea < this._tolerance) \n minVertex.remove()\n \n if (!vwLine.isLive()) return -1\n return minArea\n }\n simplify() {\n const vwLine = VWVertex.buildLine(this._pts)\n let minArea = this._tolerance\n do \n minArea = this.simplifyVertex(vwLine)\n while (minArea < this._tolerance)\n const simp = vwLine.getCoordinates()\n if (simp.length < 2) \n return [simp[0], new Coordinate(simp[0])]\n \n return simp\n }\n}\nclass VWVertex {\n constructor() {\n VWVertex.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pt = null\n this._prev = null\n this._next = null\n this._area = VWVertex.MAX_AREA\n this._isLive = true\n const pt = arguments[0]\n this._pt = pt\n }\n static buildLine(pts) {\n let first = null\n let prev = null\n for (let i = 0; i < pts.length; i++) {\n const v = new VWVertex(pts[i])\n if (first === null) first = v\n v.setPrev(prev)\n if (prev !== null) {\n prev.setNext(v)\n prev.updateArea()\n }\n prev = v\n }\n return first\n }\n getCoordinates() {\n const coords = new CoordinateList()\n let curr = this\n do {\n coords.add(curr._pt, false)\n curr = curr._next\n } while (curr !== null)\n return coords.toCoordinateArray()\n }\n getArea() {\n return this._area\n }\n updateArea() {\n if (this._prev === null || this._next === null) {\n this._area = VWVertex.MAX_AREA\n return null\n }\n this._area = Math.abs(Triangle.area(this._prev._pt, this._pt, this._next._pt))\n }\n remove() {\n const tmpPrev = this._prev\n const tmpNext = this._next\n let result = null\n if (this._prev !== null) {\n this._prev.setNext(tmpNext)\n this._prev.updateArea()\n result = this._prev\n }\n if (this._next !== null) {\n this._next.setPrev(tmpPrev)\n this._next.updateArea()\n if (result === null) result = this._next\n }\n this._isLive = false\n return result\n }\n isLive() {\n return this._isLive\n }\n setPrev(prev) {\n this._prev = prev\n }\n setNext(next) {\n this._next = next\n }\n}\nVWVertex.MAX_AREA = Double.MAX_VALUE\nVWLineSimplifier.VWVertex = VWVertex\n","import GeometryTransformer from '../geom/util/GeometryTransformer.js'\nimport VWLineSimplifier from './VWLineSimplifier.js'\nimport IllegalArgumentException from '../../../../java/lang/IllegalArgumentException.js'\nimport Polygon from '../geom/Polygon.js'\nimport LinearRing from '../geom/LinearRing.js'\nimport MultiPolygon from '../geom/MultiPolygon.js'\nexport default class VWSimplifier {\n constructor() {\n VWSimplifier.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._inputGeom = null\n this._distanceTolerance = null\n this._isEnsureValidTopology = true\n const inputGeom = arguments[0]\n this._inputGeom = inputGeom\n }\n static simplify(geom, distanceTolerance) {\n const simp = new VWSimplifier(geom)\n simp.setDistanceTolerance(distanceTolerance)\n return simp.getResultGeometry()\n }\n setEnsureValid(isEnsureValidTopology) {\n this._isEnsureValidTopology = isEnsureValidTopology\n }\n getResultGeometry() {\n if (this._inputGeom.isEmpty()) return this._inputGeom.copy()\n return new VWTransformer(this._isEnsureValidTopology, this._distanceTolerance).transform(this._inputGeom)\n }\n setDistanceTolerance(distanceTolerance) {\n if (distanceTolerance < 0.0) throw new IllegalArgumentException('Tolerance must be non-negative')\n this._distanceTolerance = distanceTolerance\n }\n}\nclass VWTransformer extends GeometryTransformer {\n constructor() {\n super()\n VWTransformer.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._isEnsureValidTopology = true\n this._distanceTolerance = null\n const isEnsureValidTopology = arguments[0], distanceTolerance = arguments[1]\n this._isEnsureValidTopology = isEnsureValidTopology\n this._distanceTolerance = distanceTolerance\n }\n transformPolygon(geom, parent) {\n if (geom.isEmpty()) return null\n const rawGeom = super.transformPolygon.call(this, geom, parent)\n if (parent instanceof MultiPolygon) \n return rawGeom\n \n return this.createValidArea(rawGeom)\n }\n createValidArea(rawAreaGeom) {\n if (this._isEnsureValidTopology) return rawAreaGeom.buffer(0.0)\n return rawAreaGeom\n }\n transformCoordinates(coords, parent) {\n const inputPts = coords.toCoordinateArray()\n let newPts = null\n if (inputPts.length === 0) \n newPts = new Array(0).fill(null)\n else \n newPts = VWLineSimplifier.simplify(inputPts, this._distanceTolerance)\n \n return this._factory.getCoordinateSequenceFactory().create(newPts)\n }\n transformMultiPolygon(geom, parent) {\n const rawGeom = super.transformMultiPolygon.call(this, geom, parent)\n return this.createValidArea(rawGeom)\n }\n transformLinearRing(geom, parent) {\n const removeDegenerateRings = parent instanceof Polygon\n const simpResult = super.transformLinearRing.call(this, geom, parent)\n if (removeDegenerateRings && !(simpResult instanceof LinearRing)) return null\n \n return simpResult\n }\n}\nVWSimplifier.VWTransformer = VWTransformer\n","import Coordinate from '../geom/Coordinate.js'\nexport default class SplitSegment {\n constructor() {\n SplitSegment.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._seg = null\n this._segLen = null\n this._splitPt = null\n this._minimumLen = 0.0\n const seg = arguments[0]\n this._seg = seg\n this._segLen = seg.getLength()\n }\n static pointAlongReverse(seg, segmentLengthFraction) {\n const coord = new Coordinate()\n coord.x = seg.p1.x - segmentLengthFraction * (seg.p1.x - seg.p0.x)\n coord.y = seg.p1.y - segmentLengthFraction * (seg.p1.y - seg.p0.y)\n return coord\n }\n splitAt() {\n if (arguments.length === 1) {\n const pt = arguments[0]\n const minFrac = this._minimumLen / this._segLen\n if (pt.distance(this._seg.p0) < this._minimumLen) {\n this._splitPt = this._seg.pointAlong(minFrac)\n return null\n }\n if (pt.distance(this._seg.p1) < this._minimumLen) {\n this._splitPt = SplitSegment.pointAlongReverse(this._seg, minFrac)\n return null\n }\n this._splitPt = pt\n } else if (arguments.length === 2) {\n const length = arguments[0], endPt = arguments[1]\n const actualLen = this.getConstrainedLength(length)\n const frac = actualLen / this._segLen\n if (endPt.equals2D(this._seg.p0)) this._splitPt = this._seg.pointAlong(frac); else this._splitPt = SplitSegment.pointAlongReverse(this._seg, frac)\n }\n }\n setMinimumLength(minLen) {\n this._minimumLen = minLen\n }\n getConstrainedLength(len) {\n if (len < this._minimumLen) return this._minimumLen\n return len\n }\n getSplitPoint() {\n return this._splitPt\n }\n}\n","export default class ConstraintSplitPointFinder {\n findSplitPoint(seg, encroachPt) {}\n}\n","import SplitSegment from './SplitSegment.js'\nimport ConstraintSplitPointFinder from './ConstraintSplitPointFinder.js'\nexport default class NonEncroachingSplitPointFinder {\n static projectedSplitPoint(seg, encroachPt) {\n const lineSeg = seg.getLineSegment()\n const projPt = lineSeg.project(encroachPt)\n return projPt\n }\n findSplitPoint(seg, encroachPt) {\n const lineSeg = seg.getLineSegment()\n const segLen = lineSeg.getLength()\n const midPtLen = segLen / 2\n const splitSeg = new SplitSegment(lineSeg)\n const projPt = NonEncroachingSplitPointFinder.projectedSplitPoint(seg, encroachPt)\n const nonEncroachDiam = projPt.distance(encroachPt) * 2 * 0.8\n let maxSplitLen = nonEncroachDiam\n if (maxSplitLen > midPtLen) \n maxSplitLen = midPtLen\n \n splitSeg.setMinimumLength(maxSplitLen)\n splitSeg.splitAt(projPt)\n return splitSeg.getSplitPoint()\n }\n get interfaces_() {\n return [ConstraintSplitPointFinder]\n }\n}\n","import WKTWriter from '../../io/WKTWriter.js'\nimport CoordinateArraySequence from '../../geom/impl/CoordinateArraySequence.js'\nimport DD from '../../math/DD.js'\nimport System from '../../../../../java/lang/System.js'\nimport Triangle from '../../geom/Triangle.js'\nexport default class TrianglePredicate {\n static triArea(a, b, c) {\n return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)\n }\n static isInCircleDDNormalized(a, b, c, p) {\n const adx = DD.valueOf(a.x).selfSubtract(p.x)\n const ady = DD.valueOf(a.y).selfSubtract(p.y)\n const bdx = DD.valueOf(b.x).selfSubtract(p.x)\n const bdy = DD.valueOf(b.y).selfSubtract(p.y)\n const cdx = DD.valueOf(c.x).selfSubtract(p.x)\n const cdy = DD.valueOf(c.y).selfSubtract(p.y)\n const abdet = adx.multiply(bdy).selfSubtract(bdx.multiply(ady))\n const bcdet = bdx.multiply(cdy).selfSubtract(cdx.multiply(bdy))\n const cadet = cdx.multiply(ady).selfSubtract(adx.multiply(cdy))\n const alift = adx.multiply(adx).selfAdd(ady.multiply(ady))\n const blift = bdx.multiply(bdx).selfAdd(bdy.multiply(bdy))\n const clift = cdx.multiply(cdx).selfAdd(cdy.multiply(cdy))\n const sum = alift.selfMultiply(bcdet).selfAdd(blift.selfMultiply(cadet)).selfAdd(clift.selfMultiply(abdet))\n const isInCircle = sum.doubleValue() > 0\n return isInCircle\n }\n static checkRobustInCircle(a, b, c, p) {\n const nonRobustInCircle = TrianglePredicate.isInCircleNonRobust(a, b, c, p)\n const isInCircleDD = TrianglePredicate.isInCircleDDSlow(a, b, c, p)\n const isInCircleCC = TrianglePredicate.isInCircleCC(a, b, c, p)\n const circumCentre = Triangle.circumcentre(a, b, c)\n System.out.println('p radius diff a = ' + Math.abs(p.distance(circumCentre) - a.distance(circumCentre)) / a.distance(circumCentre))\n if (nonRobustInCircle !== isInCircleDD || nonRobustInCircle !== isInCircleCC) {\n System.out.println('inCircle robustness failure (double result = ' + nonRobustInCircle + ', DD result = ' + isInCircleDD + ', CC result = ' + isInCircleCC + ')')\n System.out.println(WKTWriter.toLineString(new CoordinateArraySequence([a, b, c, p])))\n System.out.println('Circumcentre = ' + WKTWriter.toPoint(circumCentre) + ' radius = ' + a.distance(circumCentre))\n System.out.println('p radius diff a = ' + Math.abs(p.distance(circumCentre) / a.distance(circumCentre) - 1))\n System.out.println('p radius diff b = ' + Math.abs(p.distance(circumCentre) / b.distance(circumCentre) - 1))\n System.out.println('p radius diff c = ' + Math.abs(p.distance(circumCentre) / c.distance(circumCentre) - 1))\n System.out.println()\n }\n }\n static isInCircleDDFast(a, b, c, p) {\n const aTerm = DD.sqr(a.x).selfAdd(DD.sqr(a.y)).selfMultiply(TrianglePredicate.triAreaDDFast(b, c, p))\n const bTerm = DD.sqr(b.x).selfAdd(DD.sqr(b.y)).selfMultiply(TrianglePredicate.triAreaDDFast(a, c, p))\n const cTerm = DD.sqr(c.x).selfAdd(DD.sqr(c.y)).selfMultiply(TrianglePredicate.triAreaDDFast(a, b, p))\n const pTerm = DD.sqr(p.x).selfAdd(DD.sqr(p.y)).selfMultiply(TrianglePredicate.triAreaDDFast(a, b, c))\n const sum = aTerm.selfSubtract(bTerm).selfAdd(cTerm).selfSubtract(pTerm)\n const isInCircle = sum.doubleValue() > 0\n return isInCircle\n }\n static isInCircleCC(a, b, c, p) {\n const cc = Triangle.circumcentre(a, b, c)\n const ccRadius = a.distance(cc)\n const pRadiusDiff = p.distance(cc) - ccRadius\n return pRadiusDiff <= 0\n }\n static isInCircleNormalized(a, b, c, p) {\n const adx = a.x - p.x\n const ady = a.y - p.y\n const bdx = b.x - p.x\n const bdy = b.y - p.y\n const cdx = c.x - p.x\n const cdy = c.y - p.y\n const abdet = adx * bdy - bdx * ady\n const bcdet = bdx * cdy - cdx * bdy\n const cadet = cdx * ady - adx * cdy\n const alift = adx * adx + ady * ady\n const blift = bdx * bdx + bdy * bdy\n const clift = cdx * cdx + cdy * cdy\n const disc = alift * bcdet + blift * cadet + clift * abdet\n return disc > 0\n }\n static isInCircleDDSlow(a, b, c, p) {\n const px = DD.valueOf(p.x)\n const py = DD.valueOf(p.y)\n const ax = DD.valueOf(a.x)\n const ay = DD.valueOf(a.y)\n const bx = DD.valueOf(b.x)\n const by = DD.valueOf(b.y)\n const cx = DD.valueOf(c.x)\n const cy = DD.valueOf(c.y)\n const aTerm = ax.multiply(ax).add(ay.multiply(ay)).multiply(TrianglePredicate.triAreaDDSlow(bx, by, cx, cy, px, py))\n const bTerm = bx.multiply(bx).add(by.multiply(by)).multiply(TrianglePredicate.triAreaDDSlow(ax, ay, cx, cy, px, py))\n const cTerm = cx.multiply(cx).add(cy.multiply(cy)).multiply(TrianglePredicate.triAreaDDSlow(ax, ay, bx, by, px, py))\n const pTerm = px.multiply(px).add(py.multiply(py)).multiply(TrianglePredicate.triAreaDDSlow(ax, ay, bx, by, cx, cy))\n const sum = aTerm.subtract(bTerm).add(cTerm).subtract(pTerm)\n const isInCircle = sum.doubleValue() > 0\n return isInCircle\n }\n static isInCircleNonRobust(a, b, c, p) {\n const isInCircle = (a.x * a.x + a.y * a.y) * TrianglePredicate.triArea(b, c, p) - (b.x * b.x + b.y * b.y) * TrianglePredicate.triArea(a, c, p) + (c.x * c.x + c.y * c.y) * TrianglePredicate.triArea(a, b, p) - (p.x * p.x + p.y * p.y) * TrianglePredicate.triArea(a, b, c) > 0\n return isInCircle\n }\n static isInCircleRobust(a, b, c, p) {\n return TrianglePredicate.isInCircleNormalized(a, b, c, p)\n }\n static triAreaDDSlow(ax, ay, bx, by, cx, cy) {\n return bx.subtract(ax).multiply(cy.subtract(ay)).subtract(by.subtract(ay).multiply(cx.subtract(ax)))\n }\n static triAreaDDFast(a, b, c) {\n const t1 = DD.valueOf(b.x).selfSubtract(a.x).selfMultiply(DD.valueOf(c.y).selfSubtract(a.y))\n const t2 = DD.valueOf(b.y).selfSubtract(a.y).selfMultiply(DD.valueOf(c.x).selfSubtract(a.x))\n return t1.selfSubtract(t2)\n }\n}\n","import NotRepresentableException from '../../algorithm/NotRepresentableException.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport TrianglePredicate from './TrianglePredicate.js'\nimport System from '../../../../../java/lang/System.js'\nimport HCoordinate from '../../algorithm/HCoordinate.js'\nexport default class Vertex {\n constructor() {\n Vertex.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._p = null\n if (arguments.length === 1) {\n const _p = arguments[0]\n this._p = new Coordinate(_p)\n } else if (arguments.length === 2) {\n const _x = arguments[0], _y = arguments[1]\n this._p = new Coordinate(_x, _y)\n } else if (arguments.length === 3) {\n const _x = arguments[0], _y = arguments[1], _z = arguments[2]\n this._p = new Coordinate(_x, _y, _z)\n }\n }\n static interpolateZ() {\n if (arguments.length === 3) {\n const p = arguments[0], p0 = arguments[1], p1 = arguments[2]\n const segLen = p0.distance(p1)\n const ptLen = p.distance(p0)\n const dz = p1.getZ() - p0.getZ()\n const pz = p0.getZ() + dz * (ptLen / segLen)\n return pz\n } else if (arguments.length === 4) {\n const p = arguments[0], v0 = arguments[1], v1 = arguments[2], v2 = arguments[3]\n const x0 = v0.x\n const y0 = v0.y\n const a = v1.x - x0\n const b = v2.x - x0\n const c = v1.y - y0\n const d = v2.y - y0\n const det = a * d - b * c\n const dx = p.x - x0\n const dy = p.y - y0\n const t = (d * dx - b * dy) / det\n const u = (-c * dx + a * dy) / det\n const z = v0.getZ() + t * (v1.getZ() - v0.getZ()) + u * (v2.getZ() - v0.getZ())\n return z\n }\n }\n circleCenter(b, c) {\n const a = new Vertex(this.getX(), this.getY())\n const cab = this.bisector(a, b)\n const cbc = this.bisector(b, c)\n const hcc = new HCoordinate(cab, cbc)\n let cc = null\n try {\n cc = new Vertex(hcc.getX(), hcc.getY())\n } catch (nre) {\n if (nre instanceof NotRepresentableException) {\n System.err.println('a: ' + a + ' b: ' + b + ' c: ' + c)\n System.err.println(nre)\n } else {\n throw nre\n }\n } finally {}\n return cc\n }\n dot(v) {\n return this._p.x * v.getX() + this._p.y * v.getY()\n }\n magn() {\n return Math.sqrt(this._p.x * this._p.x + this._p.y * this._p.y)\n }\n getZ() {\n return this._p.getZ()\n }\n bisector(a, b) {\n const dx = b.getX() - a.getX()\n const dy = b.getY() - a.getY()\n const l1 = new HCoordinate(a.getX() + dx / 2.0, a.getY() + dy / 2.0, 1.0)\n const l2 = new HCoordinate(a.getX() - dy + dx / 2.0, a.getY() + dx + dy / 2.0, 1.0)\n return new HCoordinate(l1, l2)\n }\n equals() {\n if (arguments.length === 1) {\n const _x = arguments[0]\n if (this._p.x === _x.getX() && this._p.y === _x.getY()) \n return true\n else \n return false\n \n } else if (arguments.length === 2) {\n const _x = arguments[0], tolerance = arguments[1]\n if (this._p.distance(_x.getCoordinate()) < tolerance) \n return true\n else \n return false\n \n }\n }\n getCoordinate() {\n return this._p\n }\n isInCircle(a, b, c) {\n return TrianglePredicate.isInCircleRobust(a._p, b._p, c._p, this._p)\n }\n interpolateZValue(v0, v1, v2) {\n const x0 = v0.getX()\n const y0 = v0.getY()\n const a = v1.getX() - x0\n const b = v2.getX() - x0\n const c = v1.getY() - y0\n const d = v2.getY() - y0\n const det = a * d - b * c\n const dx = this.getX() - x0\n const dy = this.getY() - y0\n const t = (d * dx - b * dy) / det\n const u = (-c * dx + a * dy) / det\n const z = v0.getZ() + t * (v1.getZ() - v0.getZ()) + u * (v2.getZ() - v0.getZ())\n return z\n }\n midPoint(a) {\n const xm = (this._p.x + a.getX()) / 2.0\n const ym = (this._p.y + a.getY()) / 2.0\n const zm = (this._p.getZ() + a.getZ()) / 2.0\n return new Vertex(xm, ym, zm)\n }\n rightOf(e) {\n return this.isCCW(e.dest(), e.orig())\n }\n isCCW(b, c) {\n return (b._p.x - this._p.x) * (c._p.y - this._p.y) - (b._p.y - this._p.y) * (c._p.x - this._p.x) > 0\n }\n getX() {\n return this._p.x\n }\n crossProduct(v) {\n return this._p.x * v.getY() - this._p.y * v.getX()\n }\n setZ(_z) {\n this._p.setZ(_z)\n }\n times(c) {\n return new Vertex(c * this._p.x, c * this._p.y)\n }\n cross() {\n return new Vertex(this._p.y, -this._p.x)\n }\n leftOf(e) {\n return this.isCCW(e.orig(), e.dest())\n }\n toString() {\n return 'POINT (' + this._p.x + ' ' + this._p.y + ')'\n }\n sub(v) {\n return new Vertex(this._p.x - v.getX(), this._p.y - v.getY())\n }\n getY() {\n return this._p.y\n }\n classify(p0, p1) {\n const p2 = this\n const a = p1.sub(p0)\n const b = p2.sub(p0)\n const sa = a.crossProduct(b)\n if (sa > 0.0) return Vertex.LEFT\n if (sa < 0.0) return Vertex.RIGHT\n if (a.getX() * b.getX() < 0.0 || a.getY() * b.getY() < 0.0) return Vertex.BEHIND\n if (a.magn() < b.magn()) return Vertex.BEYOND\n if (p0.equals(p2)) return Vertex.ORIGIN\n if (p1.equals(p2)) return Vertex.DESTINATION\n return Vertex.BETWEEN\n }\n sum(v) {\n return new Vertex(this._p.x + v.getX(), this._p.y + v.getY())\n }\n distance(v1, v2) {\n return Math.sqrt(Math.pow(v2.getX() - v1.getX(), 2.0) + Math.pow(v2.getY() - v1.getY(), 2.0))\n }\n circumRadiusRatio(b, c) {\n const x = this.circleCenter(b, c)\n const radius = this.distance(x, b)\n let edgeLength = this.distance(this, b)\n let el = this.distance(b, c)\n if (el < edgeLength) \n edgeLength = el\n \n el = this.distance(c, this)\n if (el < edgeLength) \n edgeLength = el\n \n return radius / edgeLength\n }\n}\nVertex.LEFT = 0\nVertex.RIGHT = 1\nVertex.BEYOND = 2\nVertex.BEHIND = 3\nVertex.BETWEEN = 4\nVertex.ORIGIN = 5\nVertex.DESTINATION = 6\n","import Vertex from './quadedge/Vertex.js'\nexport default class ConstraintVertex extends Vertex {\n constructor() {\n super()\n ConstraintVertex.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._isOnConstraint = null\n this._constraint = null\n const p = arguments[0]\n Vertex.constructor_.call(this, p)\n }\n getConstraint() {\n return this._constraint\n }\n setOnConstraint(isOnConstraint) {\n this._isOnConstraint = isOnConstraint\n }\n merge(other) {\n if (other._isOnConstraint) {\n this._isOnConstraint = true\n this._constraint = other._constraint\n }\n }\n isOnConstraint() {\n return this._isOnConstraint\n }\n setConstraint(constraint) {\n this._isOnConstraint = true\n this._constraint = constraint\n }\n}\n","import WKTWriter from '../../io/WKTWriter.js'\nimport LineSegment from '../../geom/LineSegment.js'\nexport default class QuadEdge {\n constructor() {\n QuadEdge.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._rot = null\n this._vertex = null\n this._next = null\n this._data = null\n }\n static makeEdge(o, d) {\n const q0 = new QuadEdge()\n const q1 = new QuadEdge()\n const q2 = new QuadEdge()\n const q3 = new QuadEdge()\n q0._rot = q1\n q1._rot = q2\n q2._rot = q3\n q3._rot = q0\n q0.setNext(q0)\n q1.setNext(q3)\n q2.setNext(q2)\n q3.setNext(q1)\n const base = q0\n base.setOrig(o)\n base.setDest(d)\n return base\n }\n static swap(e) {\n const a = e.oPrev()\n const b = e.sym().oPrev()\n QuadEdge.splice(e, a)\n QuadEdge.splice(e.sym(), b)\n QuadEdge.splice(e, a.lNext())\n QuadEdge.splice(e.sym(), b.lNext())\n e.setOrig(a.dest())\n e.setDest(b.dest())\n }\n static splice(a, b) {\n const alpha = a.oNext().rot()\n const beta = b.oNext().rot()\n const t1 = b.oNext()\n const t2 = a.oNext()\n const t3 = beta.oNext()\n const t4 = alpha.oNext()\n a.setNext(t1)\n b.setNext(t2)\n alpha.setNext(t3)\n beta.setNext(t4)\n }\n static connect(a, b) {\n const e = QuadEdge.makeEdge(a.dest(), b.orig())\n QuadEdge.splice(e, a.lNext())\n QuadEdge.splice(e.sym(), b)\n return e\n }\n equalsNonOriented(qe) {\n if (this.equalsOriented(qe)) return true\n if (this.equalsOriented(qe.sym())) return true\n return false\n }\n toLineSegment() {\n return new LineSegment(this._vertex.getCoordinate(), this.dest().getCoordinate())\n }\n dest() {\n return this.sym().orig()\n }\n oNext() {\n return this._next\n }\n equalsOriented(qe) {\n if (this.orig().getCoordinate().equals2D(qe.orig().getCoordinate()) && this.dest().getCoordinate().equals2D(qe.dest().getCoordinate())) return true\n return false\n }\n dNext() {\n return this.sym().oNext().sym()\n }\n lPrev() {\n return this._next.sym()\n }\n rPrev() {\n return this.sym().oNext()\n }\n rot() {\n return this._rot\n }\n oPrev() {\n return this._rot._next._rot\n }\n sym() {\n return this._rot._rot\n }\n setOrig(o) {\n this._vertex = o\n }\n lNext() {\n return this.invRot().oNext().rot()\n }\n getLength() {\n return this.orig().getCoordinate().distance(this.dest().getCoordinate())\n }\n invRot() {\n return this._rot.sym()\n }\n setDest(d) {\n this.sym().setOrig(d)\n }\n setData(data) {\n this._data = data\n }\n getData() {\n return this._data\n }\n delete() {\n this._rot = null\n }\n orig() {\n return this._vertex\n }\n rNext() {\n return this._rot._next.invRot()\n }\n toString() {\n const p0 = this._vertex.getCoordinate()\n const p1 = this.dest().getCoordinate()\n return WKTWriter.toLineString(p0, p1)\n }\n isLive() {\n return this._rot !== null\n }\n getPrimary() {\n if (this.orig().getCoordinate().compareTo(this.dest().getCoordinate()) <= 0) return this; else return this.sym()\n }\n dPrev() {\n return this.invRot().oNext().invRot()\n }\n setNext(next) {\n this._next = next\n }\n}\n","import QuadEdge from './quadedge/QuadEdge.js'\nexport default class IncrementalDelaunayTriangulator {\n constructor() {\n IncrementalDelaunayTriangulator.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._subdiv = null\n this._isUsingTolerance = false\n const subdiv = arguments[0]\n this._subdiv = subdiv\n this._isUsingTolerance = subdiv.getTolerance() > 0.0\n }\n insertSite(v) {\n let e = this._subdiv.locate(v)\n if (this._subdiv.isVertexOfEdge(e, v)) {\n return e\n } else if (this._subdiv.isOnEdge(e, v.getCoordinate())) {\n e = e.oPrev()\n this._subdiv.delete(e.oNext())\n }\n let base = this._subdiv.makeEdge(e.orig(), v)\n QuadEdge.splice(base, e)\n const startEdge = base\n do {\n base = this._subdiv.connect(e, base.sym())\n e = base.oPrev()\n } while (e.lNext() !== startEdge)\n do {\n const t = e.oPrev()\n if (t.dest().rightOf(e) && v.isInCircle(e.orig(), t.dest(), e.dest())) {\n QuadEdge.swap(e)\n e = e.oPrev()\n } else if (e.oNext() === startEdge) {\n return base\n } else {\n e = e.oNext().lPrev()\n }\n } while (true)\n }\n insertSites(vertices) {\n for (let i = vertices.iterator(); i.hasNext(); ) {\n const v = i.next()\n this.insertSite(v)\n }\n }\n}\n","export default class QuadEdgeLocator {\n locate(v) {}\n}\n","import QuadEdgeLocator from './QuadEdgeLocator.js'\nexport default class LastFoundQuadEdgeLocator {\n constructor() {\n LastFoundQuadEdgeLocator.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._subdiv = null\n this._lastEdge = null\n const subdiv = arguments[0]\n this._subdiv = subdiv\n this.init()\n }\n init() {\n this._lastEdge = this.findEdge()\n }\n locate(v) {\n if (!this._lastEdge.isLive()) \n this.init()\n \n const e = this._subdiv.locateFromEdge(v, this._lastEdge)\n this._lastEdge = e\n return e\n }\n findEdge() {\n const edges = this._subdiv.getEdges()\n return edges.iterator().next()\n }\n get interfaces_() {\n return [QuadEdgeLocator]\n }\n}\n","import LineSegment from '../../geom/LineSegment.js'\nimport RuntimeException from '../../../../../java/lang/RuntimeException.js'\nexport default class LocateFailureException extends RuntimeException {\n constructor() {\n super()\n LocateFailureException.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._seg = null\n if (arguments.length === 1) {\n if (typeof arguments[0] === 'string') {\n const msg = arguments[0]\n RuntimeException.constructor_.call(this, msg)\n } else if (arguments[0] instanceof LineSegment) {\n const seg = arguments[0]\n RuntimeException.constructor_.call(this, 'Locate failed to converge (at edge: ' + seg + '). Possible causes include invalid Subdivision topology or very close sites')\n this._seg = new LineSegment(seg)\n }\n } else if (arguments.length === 2) {\n const msg = arguments[0], seg = arguments[1]\n RuntimeException.constructor_.call(this, LocateFailureException.msgWithSpatial(msg, seg))\n this._seg = new LineSegment(seg)\n }\n }\n static msgWithSpatial(msg, seg) {\n if (seg !== null) return msg + ' [ ' + seg + ' ]'\n return msg\n }\n getSegment() {\n return this._seg\n }\n}\n","export default class TriangleVisitor {\n visit(triEdges) {}\n}\n","import QuadEdge from './QuadEdge.js'\nimport CoordinateList from '../../geom/CoordinateList.js'\nimport HashSet from '../../../../../java/util/HashSet.js'\nimport WKTWriter from '../../io/WKTWriter.js'\nimport GeometryFactory from '../../geom/GeometryFactory.js'\nimport Coordinate from '../../geom/Coordinate.js'\nimport IllegalArgumentException from '../../../../../java/lang/IllegalArgumentException.js'\nimport Stack from '../../../../../java/util/Stack.js'\nimport LastFoundQuadEdgeLocator from './LastFoundQuadEdgeLocator.js'\nimport LocateFailureException from './LocateFailureException.js'\nimport Vertex from './Vertex.js'\nimport System from '../../../../../java/lang/System.js'\nimport LineSegment from '../../geom/LineSegment.js'\nimport ArrayList from '../../../../../java/util/ArrayList.js'\nimport Envelope from '../../geom/Envelope.js'\nimport Triangle from '../../geom/Triangle.js'\nimport TriangleVisitor from './TriangleVisitor.js'\nexport default class QuadEdgeSubdivision {\n constructor() {\n QuadEdgeSubdivision.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._visitedKey = 0\n this._quadEdges = new ArrayList()\n this._startingEdge = null\n this._tolerance = null\n this._edgeCoincidenceTolerance = null\n this._frameVertex = new Array(3).fill(null)\n this._frameEnv = null\n this._locator = null\n this._seg = new LineSegment()\n this._triEdges = new Array(3).fill(null)\n const env = arguments[0], tolerance = arguments[1]\n this._tolerance = tolerance\n this._edgeCoincidenceTolerance = tolerance / QuadEdgeSubdivision.EDGE_COINCIDENCE_TOL_FACTOR\n this.createFrame(env)\n this._startingEdge = this.initSubdiv()\n this._locator = new LastFoundQuadEdgeLocator(this)\n }\n static getTriangleEdges(startQE, triEdge) {\n triEdge[0] = startQE\n triEdge[1] = triEdge[0].lNext()\n triEdge[2] = triEdge[1].lNext()\n if (triEdge[2].lNext() !== triEdge[0]) throw new IllegalArgumentException('Edges do not form a triangle')\n }\n getTriangleVertices(includeFrame) {\n const visitor = new TriangleVertexListVisitor()\n this.visitTriangles(visitor, includeFrame)\n return visitor.getTriangleVertices()\n }\n isFrameVertex(v) {\n if (v.equals(this._frameVertex[0])) return true\n if (v.equals(this._frameVertex[1])) return true\n if (v.equals(this._frameVertex[2])) return true\n return false\n }\n isVertexOfEdge(e, v) {\n if (v.equals(e.orig(), this._tolerance) || v.equals(e.dest(), this._tolerance)) \n return true\n \n return false\n }\n connect(a, b) {\n const q = QuadEdge.connect(a, b)\n this._quadEdges.add(q)\n return q\n }\n getVoronoiCellPolygon(qe, geomFact) {\n const cellPts = new ArrayList()\n const startQE = qe\n do {\n const cc = qe.rot().orig().getCoordinate()\n cellPts.add(cc)\n qe = qe.oPrev()\n } while (qe !== startQE)\n const coordList = new CoordinateList()\n coordList.addAll(cellPts, false)\n coordList.closeRing()\n if (coordList.size() < 4) {\n System.out.println(coordList)\n coordList.add(coordList.get(coordList.size() - 1), true)\n }\n const pts = coordList.toCoordinateArray()\n const cellPoly = geomFact.createPolygon(geomFact.createLinearRing(pts))\n const v = startQE.orig()\n cellPoly.setUserData(v.getCoordinate())\n return cellPoly\n }\n setLocator(locator) {\n this._locator = locator\n }\n initSubdiv() {\n const ea = this.makeEdge(this._frameVertex[0], this._frameVertex[1])\n const eb = this.makeEdge(this._frameVertex[1], this._frameVertex[2])\n QuadEdge.splice(ea.sym(), eb)\n const ec = this.makeEdge(this._frameVertex[2], this._frameVertex[0])\n QuadEdge.splice(eb.sym(), ec)\n QuadEdge.splice(ec.sym(), ea)\n return ea\n }\n isFrameBorderEdge(e) {\n const leftTri = new Array(3).fill(null)\n QuadEdgeSubdivision.getTriangleEdges(e, leftTri)\n const rightTri = new Array(3).fill(null)\n QuadEdgeSubdivision.getTriangleEdges(e.sym(), rightTri)\n const vLeftTriOther = e.lNext().dest()\n if (this.isFrameVertex(vLeftTriOther)) return true\n const vRightTriOther = e.sym().lNext().dest()\n if (this.isFrameVertex(vRightTriOther)) return true\n return false\n }\n makeEdge(o, d) {\n const q = QuadEdge.makeEdge(o, d)\n this._quadEdges.add(q)\n return q\n }\n visitTriangles(triVisitor, includeFrame) {\n this._visitedKey++\n const edgeStack = new Stack()\n edgeStack.push(this._startingEdge)\n const visitedEdges = new HashSet()\n while (!edgeStack.empty()) {\n const edge = edgeStack.pop()\n if (!visitedEdges.contains(edge)) {\n const triEdges = this.fetchTriangleToVisit(edge, edgeStack, includeFrame, visitedEdges)\n if (triEdges !== null) triVisitor.visit(triEdges)\n }\n }\n }\n isFrameEdge(e) {\n if (this.isFrameVertex(e.orig()) || this.isFrameVertex(e.dest())) return true\n return false\n }\n isOnEdge(e, p) {\n this._seg.setCoordinates(e.orig().getCoordinate(), e.dest().getCoordinate())\n const dist = this._seg.distance(p)\n return dist < this._edgeCoincidenceTolerance\n }\n getEnvelope() {\n return new Envelope(this._frameEnv)\n }\n createFrame(env) {\n const deltaX = env.getWidth()\n const deltaY = env.getHeight()\n let offset = 0.0\n if (deltaX > deltaY) \n offset = deltaX * 10.0\n else \n offset = deltaY * 10.0\n \n this._frameVertex[0] = new Vertex((env.getMaxX() + env.getMinX()) / 2.0, env.getMaxY() + offset)\n this._frameVertex[1] = new Vertex(env.getMinX() - offset, env.getMinY() - offset)\n this._frameVertex[2] = new Vertex(env.getMaxX() + offset, env.getMinY() - offset)\n this._frameEnv = new Envelope(this._frameVertex[0].getCoordinate(), this._frameVertex[1].getCoordinate())\n this._frameEnv.expandToInclude(this._frameVertex[2].getCoordinate())\n }\n getTriangleCoordinates(includeFrame) {\n const visitor = new TriangleCoordinatesVisitor()\n this.visitTriangles(visitor, includeFrame)\n return visitor.getTriangles()\n }\n getVertices(includeFrame) {\n const vertices = new HashSet()\n for (let i = this._quadEdges.iterator(); i.hasNext(); ) {\n const qe = i.next()\n const v = qe.orig()\n if (includeFrame || !this.isFrameVertex(v)) vertices.add(v)\n const vd = qe.dest()\n if (includeFrame || !this.isFrameVertex(vd)) vertices.add(vd)\n }\n return vertices\n }\n fetchTriangleToVisit(edge, edgeStack, includeFrame, visitedEdges) {\n let curr = edge\n let edgeCount = 0\n let isFrame = false\n do {\n this._triEdges[edgeCount] = curr\n if (this.isFrameEdge(curr)) isFrame = true\n const sym = curr.sym()\n if (!visitedEdges.contains(sym)) edgeStack.push(sym)\n visitedEdges.add(curr)\n edgeCount++\n curr = curr.lNext()\n } while (curr !== edge)\n if (isFrame && !includeFrame) return null\n return this._triEdges\n }\n getEdges() {\n if (arguments.length === 0) {\n return this._quadEdges\n } else if (arguments.length === 1) {\n const geomFact = arguments[0]\n const quadEdges = this.getPrimaryEdges(false)\n const edges = new Array(quadEdges.size()).fill(null)\n let i = 0\n for (let it = quadEdges.iterator(); it.hasNext(); ) {\n const qe = it.next()\n edges[i++] = geomFact.createLineString([qe.orig().getCoordinate(), qe.dest().getCoordinate()])\n }\n return geomFact.createMultiLineString(edges)\n }\n }\n getVertexUniqueEdges(includeFrame) {\n const edges = new ArrayList()\n const visitedVertices = new HashSet()\n for (let i = this._quadEdges.iterator(); i.hasNext(); ) {\n const qe = i.next()\n const v = qe.orig()\n if (!visitedVertices.contains(v)) {\n visitedVertices.add(v)\n if (includeFrame || !this.isFrameVertex(v)) \n edges.add(qe)\n \n }\n const qd = qe.sym()\n const vd = qd.orig()\n if (!visitedVertices.contains(vd)) {\n visitedVertices.add(vd)\n if (includeFrame || !this.isFrameVertex(vd)) \n edges.add(qd)\n \n }\n }\n return edges\n }\n getTriangleEdges(includeFrame) {\n const visitor = new TriangleEdgesListVisitor()\n this.visitTriangles(visitor, includeFrame)\n return visitor.getTriangleEdges()\n }\n getPrimaryEdges(includeFrame) {\n this._visitedKey++\n const edges = new ArrayList()\n const edgeStack = new Stack()\n edgeStack.push(this._startingEdge)\n const visitedEdges = new HashSet()\n while (!edgeStack.empty()) {\n const edge = edgeStack.pop()\n if (!visitedEdges.contains(edge)) {\n const priQE = edge.getPrimary()\n if (includeFrame || !this.isFrameEdge(priQE)) edges.add(priQE)\n edgeStack.push(edge.oNext())\n edgeStack.push(edge.sym().oNext())\n visitedEdges.add(edge)\n visitedEdges.add(edge.sym())\n }\n }\n return edges\n }\n delete(e) {\n QuadEdge.splice(e, e.oPrev())\n QuadEdge.splice(e.sym(), e.sym().oPrev())\n const eSym = e.sym()\n const eRot = e.rot()\n const eRotSym = e.rot().sym()\n this._quadEdges.remove(e)\n this._quadEdges.remove(eSym)\n this._quadEdges.remove(eRot)\n this._quadEdges.remove(eRotSym)\n e.delete()\n eSym.delete()\n eRot.delete()\n eRotSym.delete()\n }\n locateFromEdge(v, startEdge) {\n let iter = 0\n const maxIter = this._quadEdges.size()\n let e = startEdge\n while (true) {\n iter++\n if (iter > maxIter) \n throw new LocateFailureException(e.toLineSegment())\n \n if (v.equals(e.orig()) || v.equals(e.dest())) \n break\n else if (v.rightOf(e)) \n e = e.sym()\n else if (!v.rightOf(e.oNext())) \n e = e.oNext()\n else if (!v.rightOf(e.dPrev())) \n e = e.dPrev()\n else \n break\n \n }\n return e\n }\n getTolerance() {\n return this._tolerance\n }\n getVoronoiCellPolygons(geomFact) {\n this.visitTriangles(new TriangleCircumcentreVisitor(), true)\n const cells = new ArrayList()\n const edges = this.getVertexUniqueEdges(false)\n for (let i = edges.iterator(); i.hasNext(); ) {\n const qe = i.next()\n cells.add(this.getVoronoiCellPolygon(qe, geomFact))\n }\n return cells\n }\n getVoronoiDiagram(geomFact) {\n const vorCells = this.getVoronoiCellPolygons(geomFact)\n return geomFact.createGeometryCollection(GeometryFactory.toGeometryArray(vorCells))\n }\n getTriangles(geomFact) {\n const triPtsList = this.getTriangleCoordinates(false)\n const tris = new Array(triPtsList.size()).fill(null)\n let i = 0\n for (let it = triPtsList.iterator(); it.hasNext(); ) {\n const triPt = it.next()\n tris[i++] = geomFact.createPolygon(geomFact.createLinearRing(triPt))\n }\n return geomFact.createGeometryCollection(tris)\n }\n insertSite(v) {\n let e = this.locate(v)\n if (v.equals(e.orig(), this._tolerance) || v.equals(e.dest(), this._tolerance)) \n return e\n \n let base = this.makeEdge(e.orig(), v)\n QuadEdge.splice(base, e)\n const startEdge = base\n do {\n base = this.connect(e, base.sym())\n e = base.oPrev()\n } while (e.lNext() !== startEdge)\n return startEdge\n }\n locate() {\n if (arguments.length === 1) {\n if (arguments[0] instanceof Vertex) {\n const v = arguments[0]\n return this._locator.locate(v)\n } else if (arguments[0] instanceof Coordinate) {\n const p = arguments[0]\n return this._locator.locate(new Vertex(p))\n }\n } else if (arguments.length === 2) {\n const p0 = arguments[0], p1 = arguments[1]\n const e = this._locator.locate(new Vertex(p0))\n if (e === null) return null\n let base = e\n if (e.dest().getCoordinate().equals2D(p0)) base = e.sym()\n let locEdge = base\n do {\n if (locEdge.dest().getCoordinate().equals2D(p1)) return locEdge\n locEdge = locEdge.oNext()\n } while (locEdge !== base)\n return null\n }\n }\n}\nclass TriangleCircumcentreVisitor {\n visit(triEdges) {\n const a = triEdges[0].orig().getCoordinate()\n const b = triEdges[1].orig().getCoordinate()\n const c = triEdges[2].orig().getCoordinate()\n const cc = Triangle.circumcentreDD(a, b, c)\n const ccVertex = new Vertex(cc)\n for (let i = 0; i < 3; i++) \n triEdges[i].rot().setOrig(ccVertex)\n \n }\n get interfaces_() {\n return [TriangleVisitor]\n }\n}\nclass TriangleEdgesListVisitor {\n constructor() {\n TriangleEdgesListVisitor.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._triList = new ArrayList()\n }\n getTriangleEdges() {\n return this._triList\n }\n visit(triEdges) {\n this._triList.add(triEdges)\n }\n get interfaces_() {\n return [TriangleVisitor]\n }\n}\nclass TriangleVertexListVisitor {\n constructor() {\n TriangleVertexListVisitor.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._triList = new ArrayList()\n }\n visit(triEdges) {\n this._triList.add([triEdges[0].orig(), triEdges[1].orig(), triEdges[2].orig()])\n }\n getTriangleVertices() {\n return this._triList\n }\n get interfaces_() {\n return [TriangleVisitor]\n }\n}\nclass TriangleCoordinatesVisitor {\n constructor() {\n TriangleCoordinatesVisitor.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._coordList = new CoordinateList()\n this._triCoords = new ArrayList()\n }\n checkTriangleSize(pts) {\n let loc = ''\n if (pts.length >= 2) loc = WKTWriter.toLineString(pts[0], pts[1]); else \n if (pts.length >= 1) loc = WKTWriter.toPoint(pts[0])\n \n }\n visit(triEdges) {\n this._coordList.clear()\n for (let i = 0; i < 3; i++) {\n const v = triEdges[i].orig()\n this._coordList.add(v.getCoordinate())\n }\n if (this._coordList.size() > 0) {\n this._coordList.closeRing()\n const pts = this._coordList.toCoordinateArray()\n if (pts.length !== 4) \n return null\n \n this._triCoords.add(pts)\n }\n }\n getTriangles() {\n return this._triCoords\n }\n get interfaces_() {\n return [TriangleVisitor]\n }\n}\nQuadEdgeSubdivision.TriangleCircumcentreVisitor = TriangleCircumcentreVisitor\nQuadEdgeSubdivision.TriangleEdgesListVisitor = TriangleEdgesListVisitor\nQuadEdgeSubdivision.TriangleVertexListVisitor = TriangleVertexListVisitor\nQuadEdgeSubdivision.TriangleCoordinatesVisitor = TriangleCoordinatesVisitor\nQuadEdgeSubdivision.EDGE_COINCIDENCE_TOL_FACTOR = 1000\n","import Coordinate from '../geom/Coordinate.js'\nimport LineSegment from '../geom/LineSegment.js'\nexport default class Segment {\n constructor() {\n Segment.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._ls = null\n this._data = null\n if (arguments.length === 2) {\n const p0 = arguments[0], p1 = arguments[1]\n this._ls = new LineSegment(p0, p1)\n } else if (arguments.length === 3) {\n const p0 = arguments[0], p1 = arguments[1], data = arguments[2]\n this._ls = new LineSegment(p0, p1)\n this._data = data\n } else if (arguments.length === 6) {\n const x1 = arguments[0], y1 = arguments[1], z1 = arguments[2], x2 = arguments[3], y2 = arguments[4], z2 = arguments[5]\n Segment.constructor_.call(this, new Coordinate(x1, y1, z1), new Coordinate(x2, y2, z2))\n } else if (arguments.length === 7) {\n const x1 = arguments[0], y1 = arguments[1], z1 = arguments[2], x2 = arguments[3], y2 = arguments[4], z2 = arguments[5], data = arguments[6]\n Segment.constructor_.call(this, new Coordinate(x1, y1, z1), new Coordinate(x2, y2, z2), data)\n }\n }\n getLineSegment() {\n return this._ls\n }\n getEndZ() {\n const p = this._ls.getCoordinate(1)\n return p.getZ()\n }\n getStartZ() {\n const p = this._ls.getCoordinate(0)\n return p.getZ()\n }\n intersection(s) {\n return this._ls.intersection(s.getLineSegment())\n }\n getStart() {\n return this._ls.getCoordinate(0)\n }\n getEnd() {\n return this._ls.getCoordinate(1)\n }\n getEndY() {\n const p = this._ls.getCoordinate(1)\n return p.y\n }\n getStartX() {\n const p = this._ls.getCoordinate(0)\n return p.x\n }\n equalsTopo(s) {\n return this._ls.equalsTopo(s.getLineSegment())\n }\n getStartY() {\n const p = this._ls.getCoordinate(0)\n return p.y\n }\n setData(data) {\n this._data = data\n }\n getData() {\n return this._data\n }\n getEndX() {\n const p = this._ls.getCoordinate(1)\n return p.x\n }\n toString() {\n return this._ls.toString()\n }\n}\n","import WKTWriter from '../io/WKTWriter.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport RuntimeException from '../../../../java/lang/RuntimeException.js'\nexport default class ConstraintEnforcementException extends RuntimeException {\n constructor() {\n super()\n ConstraintEnforcementException.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._pt = null\n if (arguments.length === 1) {\n const msg = arguments[0]\n RuntimeException.constructor_.call(this, msg)\n } else if (arguments.length === 2) {\n const msg = arguments[0], pt = arguments[1]\n RuntimeException.constructor_.call(this, ConstraintEnforcementException.msgWithCoord(msg, pt))\n this._pt = new Coordinate(pt)\n }\n }\n static msgWithCoord(msg, pt) {\n if (pt !== null) return msg + ' [ ' + WKTWriter.toPoint(pt) + ' ]'\n return msg\n }\n getCoordinate() {\n return this._pt\n }\n}\n","import GeometryFactory from '../geom/GeometryFactory.js'\nimport NonEncroachingSplitPointFinder from './NonEncroachingSplitPointFinder.js'\nimport ConstraintVertex from './ConstraintVertex.js'\nimport Coordinate from '../geom/Coordinate.js'\nimport IncrementalDelaunayTriangulator from './IncrementalDelaunayTriangulator.js'\nimport QuadEdgeSubdivision from './quadedge/QuadEdgeSubdivision.js'\nimport Double from '../../../../java/lang/Double.js'\nimport LastFoundQuadEdgeLocator from './quadedge/LastFoundQuadEdgeLocator.js'\nimport Segment from './Segment.js'\nimport ConvexHull from '../algorithm/ConvexHull.js'\nimport KdTree from '../index/kdtree/KdTree.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport ConstraintEnforcementException from './ConstraintEnforcementException.js'\nimport Envelope from '../geom/Envelope.js'\nexport default class ConformingDelaunayTriangulator {\n constructor() {\n ConformingDelaunayTriangulator.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._initialVertices = null\n this._segVertices = null\n this._segments = new ArrayList()\n this._subdiv = null\n this._incDel = null\n this._convexHull = null\n this._splitFinder = new NonEncroachingSplitPointFinder()\n this._kdt = null\n this._vertexFactory = null\n this._computeAreaEnv = null\n this._splitPt = null\n this._tolerance = null\n const initialVertices = arguments[0], tolerance = arguments[1]\n this._initialVertices = new ArrayList(initialVertices)\n this._tolerance = tolerance\n this._kdt = new KdTree(tolerance)\n }\n static computeVertexEnvelope(vertices) {\n const env = new Envelope()\n for (let i = vertices.iterator(); i.hasNext(); ) {\n const v = i.next()\n env.expandToInclude(v.getCoordinate())\n }\n return env\n }\n getInitialVertices() {\n return this._initialVertices\n }\n getKDT() {\n return this._kdt\n }\n enforceConstraints() {\n this.addConstraintVertices()\n let count = 0\n let splits = 0\n do {\n splits = this.enforceGabriel(this._segments)\n count++\n } while (splits > 0 && count < ConformingDelaunayTriangulator.MAX_SPLIT_ITER)\n if (count === ConformingDelaunayTriangulator.MAX_SPLIT_ITER) \n throw new ConstraintEnforcementException('Too many splitting iterations while enforcing constraints. Last split point was at: ', this._splitPt)\n \n }\n insertSites(vertices) {\n for (let i = vertices.iterator(); i.hasNext(); ) {\n const v = i.next()\n this.insertSite(v)\n }\n }\n getVertexFactory() {\n return this._vertexFactory\n }\n getPointArray() {\n const pts = new Array(this._initialVertices.size() + this._segVertices.size()).fill(null)\n let index = 0\n for (let i = this._initialVertices.iterator(); i.hasNext(); ) {\n const v = i.next()\n pts[index++] = v.getCoordinate()\n }\n for (let i2 = this._segVertices.iterator(); i2.hasNext(); ) {\n const v = i2.next()\n pts[index++] = v.getCoordinate()\n }\n return pts\n }\n setConstraints(segments, segVertices) {\n this._segments = segments\n this._segVertices = segVertices\n }\n computeConvexHull() {\n const fact = new GeometryFactory()\n const coords = this.getPointArray()\n const hull = new ConvexHull(coords, fact)\n this._convexHull = hull.getConvexHull()\n }\n addConstraintVertices() {\n this.computeConvexHull()\n this.insertSites(this._segVertices)\n }\n findNonGabrielPoint(seg) {\n const p = seg.getStart()\n const q = seg.getEnd()\n const midPt = new Coordinate((p.x + q.x) / 2.0, (p.y + q.y) / 2.0)\n const segRadius = p.distance(midPt)\n const env = new Envelope(midPt)\n env.expandBy(segRadius)\n const result = this._kdt.query(env)\n let closestNonGabriel = null\n let minDist = Double.MAX_VALUE\n for (let i = result.iterator(); i.hasNext(); ) {\n const nextNode = i.next()\n const testPt = nextNode.getCoordinate()\n if (testPt.equals2D(p) || testPt.equals2D(q)) continue\n const testRadius = midPt.distance(testPt)\n if (testRadius < segRadius) {\n const testDist = testRadius\n if (closestNonGabriel === null || testDist < minDist) {\n closestNonGabriel = testPt\n minDist = testDist\n }\n }\n }\n return closestNonGabriel\n }\n getConstraintSegments() {\n return this._segments\n }\n setSplitPointFinder(splitFinder) {\n this._splitFinder = splitFinder\n }\n getConvexHull() {\n return this._convexHull\n }\n getTolerance() {\n return this._tolerance\n }\n enforceGabriel(segsToInsert) {\n const newSegments = new ArrayList()\n let splits = 0\n const segsToRemove = new ArrayList()\n for (let i = segsToInsert.iterator(); i.hasNext(); ) {\n const seg = i.next()\n const encroachPt = this.findNonGabrielPoint(seg)\n if (encroachPt === null) continue\n this._splitPt = this._splitFinder.findSplitPoint(seg, encroachPt)\n const splitVertex = this.createVertex(this._splitPt, seg)\n const insertedVertex = this.insertSite(splitVertex)\n if (!insertedVertex.getCoordinate().equals2D(this._splitPt)) {}\n const s1 = new Segment(seg.getStartX(), seg.getStartY(), seg.getStartZ(), splitVertex.getX(), splitVertex.getY(), splitVertex.getZ(), seg.getData())\n const s2 = new Segment(splitVertex.getX(), splitVertex.getY(), splitVertex.getZ(), seg.getEndX(), seg.getEndY(), seg.getEndZ(), seg.getData())\n newSegments.add(s1)\n newSegments.add(s2)\n segsToRemove.add(seg)\n splits = splits + 1\n }\n segsToInsert.removeAll(segsToRemove)\n segsToInsert.addAll(newSegments)\n return splits\n }\n createVertex() {\n if (arguments.length === 1) {\n const p = arguments[0]\n let v = null\n if (this._vertexFactory !== null) v = this._vertexFactory.createVertex(p, null); else v = new ConstraintVertex(p)\n return v\n } else if (arguments.length === 2) {\n const p = arguments[0], seg = arguments[1]\n let v = null\n if (this._vertexFactory !== null) v = this._vertexFactory.createVertex(p, seg); else v = new ConstraintVertex(p)\n v.setOnConstraint(true)\n return v\n }\n }\n getSubdivision() {\n return this._subdiv\n }\n computeBoundingBox() {\n const vertexEnv = ConformingDelaunayTriangulator.computeVertexEnvelope(this._initialVertices)\n const segEnv = ConformingDelaunayTriangulator.computeVertexEnvelope(this._segVertices)\n const allPointsEnv = new Envelope(vertexEnv)\n allPointsEnv.expandToInclude(segEnv)\n const deltaX = allPointsEnv.getWidth() * 0.2\n const deltaY = allPointsEnv.getHeight() * 0.2\n const delta = Math.max(deltaX, deltaY)\n this._computeAreaEnv = new Envelope(allPointsEnv)\n this._computeAreaEnv.expandBy(delta)\n }\n setVertexFactory(vertexFactory) {\n this._vertexFactory = vertexFactory\n }\n formInitialDelaunay() {\n this.computeBoundingBox()\n this._subdiv = new QuadEdgeSubdivision(this._computeAreaEnv, this._tolerance)\n this._subdiv.setLocator(new LastFoundQuadEdgeLocator(this._subdiv))\n this._incDel = new IncrementalDelaunayTriangulator(this._subdiv)\n this.insertSites(this._initialVertices)\n }\n insertSite() {\n if (arguments[0] instanceof ConstraintVertex) {\n const v = arguments[0]\n const kdnode = this._kdt.insert(v.getCoordinate(), v)\n if (!kdnode.isRepeated()) {\n this._incDel.insertSite(v)\n } else {\n const snappedV = kdnode.getData()\n snappedV.merge(v)\n return snappedV\n }\n return v\n } else if (arguments[0] instanceof Coordinate) {\n const p = arguments[0]\n this.insertSite(this.createVertex(p))\n }\n }\n}\nConformingDelaunayTriangulator.MAX_SPLIT_ITER = 99\n","import CoordinateList from '../geom/CoordinateList.js'\nimport Geometry from '../geom/Geometry.js'\nimport Arrays from '../../../../java/util/Arrays.js'\nimport hasInterface from '../../../../hasInterface.js'\nimport Collection from '../../../../java/util/Collection.js'\nimport IncrementalDelaunayTriangulator from './IncrementalDelaunayTriangulator.js'\nimport QuadEdgeSubdivision from './quadedge/QuadEdgeSubdivision.js'\nimport Vertex from './quadedge/Vertex.js'\nimport CoordinateArrays from '../geom/CoordinateArrays.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport Envelope from '../geom/Envelope.js'\nexport default class DelaunayTriangulationBuilder {\n constructor() {\n DelaunayTriangulationBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._siteCoords = null\n this._tolerance = 0.0\n this._subdiv = null\n }\n static extractUniqueCoordinates(geom) {\n if (geom === null) return new CoordinateList()\n const coords = geom.getCoordinates()\n return DelaunayTriangulationBuilder.unique(coords)\n }\n static envelope(coords) {\n const env = new Envelope()\n for (let i = coords.iterator(); i.hasNext(); ) {\n const coord = i.next()\n env.expandToInclude(coord)\n }\n return env\n }\n static unique(coords) {\n const coordsCopy = CoordinateArrays.copyDeep(coords)\n Arrays.sort(coordsCopy)\n const coordList = new CoordinateList(coordsCopy, false)\n return coordList\n }\n static toVertices(coords) {\n const verts = new ArrayList()\n for (let i = coords.iterator(); i.hasNext(); ) {\n const coord = i.next()\n verts.add(new Vertex(coord))\n }\n return verts\n }\n create() {\n if (this._subdiv !== null) return null\n const siteEnv = DelaunayTriangulationBuilder.envelope(this._siteCoords)\n const vertices = DelaunayTriangulationBuilder.toVertices(this._siteCoords)\n this._subdiv = new QuadEdgeSubdivision(siteEnv, this._tolerance)\n const triangulator = new IncrementalDelaunayTriangulator(this._subdiv)\n triangulator.insertSites(vertices)\n }\n setTolerance(tolerance) {\n this._tolerance = tolerance\n }\n setSites() {\n if (arguments[0] instanceof Geometry) {\n const geom = arguments[0]\n this._siteCoords = DelaunayTriangulationBuilder.extractUniqueCoordinates(geom)\n } else if (hasInterface(arguments[0], Collection)) {\n const coords = arguments[0]\n this._siteCoords = DelaunayTriangulationBuilder.unique(CoordinateArrays.toCoordinateArray(coords))\n }\n }\n getEdges(geomFact) {\n this.create()\n return this._subdiv.getEdges(geomFact)\n }\n getSubdivision() {\n this.create()\n return this._subdiv\n }\n getTriangles(geomFact) {\n this.create()\n return this._subdiv.getTriangles(geomFact)\n }\n}\n","import ConformingDelaunayTriangulator from './ConformingDelaunayTriangulator.js'\nimport ConstraintVertex from './ConstraintVertex.js'\nimport DelaunayTriangulationBuilder from './DelaunayTriangulationBuilder.js'\nimport Segment from './Segment.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport LinearComponentExtracter from '../geom/util/LinearComponentExtracter.js'\nimport TreeMap from '../../../../java/util/TreeMap.js'\nexport default class ConformingDelaunayTriangulationBuilder {\n constructor() {\n ConformingDelaunayTriangulationBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._siteCoords = null\n this._constraintLines = null\n this._tolerance = 0.0\n this._subdiv = null\n this._constraintVertexMap = new TreeMap()\n }\n static createConstraintSegments() {\n if (arguments.length === 1) {\n const geom = arguments[0]\n const lines = LinearComponentExtracter.getLines(geom)\n const constraintSegs = new ArrayList()\n for (let i = lines.iterator(); i.hasNext(); ) {\n const line = i.next()\n ConformingDelaunayTriangulationBuilder.createConstraintSegments(line, constraintSegs)\n }\n return constraintSegs\n } else if (arguments.length === 2) {\n const line = arguments[0], constraintSegs = arguments[1]\n const coords = line.getCoordinates()\n for (let i = 1; i < coords.length; i++) \n constraintSegs.add(new Segment(coords[i - 1], coords[i]))\n \n }\n }\n createSiteVertices(coords) {\n const verts = new ArrayList()\n for (let i = coords.iterator(); i.hasNext(); ) {\n const coord = i.next()\n if (this._constraintVertexMap.containsKey(coord)) continue\n verts.add(new ConstraintVertex(coord))\n }\n return verts\n }\n create() {\n if (this._subdiv !== null) return null\n const siteEnv = DelaunayTriangulationBuilder.envelope(this._siteCoords)\n let segments = new ArrayList()\n if (this._constraintLines !== null) {\n siteEnv.expandToInclude(this._constraintLines.getEnvelopeInternal())\n this.createVertices(this._constraintLines)\n segments = ConformingDelaunayTriangulationBuilder.createConstraintSegments(this._constraintLines)\n }\n const sites = this.createSiteVertices(this._siteCoords)\n const cdt = new ConformingDelaunayTriangulator(sites, this._tolerance)\n cdt.setConstraints(segments, new ArrayList(this._constraintVertexMap.values()))\n cdt.formInitialDelaunay()\n cdt.enforceConstraints()\n this._subdiv = cdt.getSubdivision()\n }\n setTolerance(tolerance) {\n this._tolerance = tolerance\n }\n setConstraints(constraintLines) {\n this._constraintLines = constraintLines\n }\n setSites(geom) {\n this._siteCoords = DelaunayTriangulationBuilder.extractUniqueCoordinates(geom)\n }\n getEdges(geomFact) {\n this.create()\n return this._subdiv.getEdges(geomFact)\n }\n getSubdivision() {\n this.create()\n return this._subdiv\n }\n getTriangles(geomFact) {\n this.create()\n return this._subdiv.getTriangles(geomFact)\n }\n createVertices(geom) {\n const coords = geom.getCoordinates()\n for (let i = 0; i < coords.length; i++) {\n const v = new ConstraintVertex(coords[i])\n this._constraintVertexMap.put(coords[i], v)\n }\n }\n}\n","import Geometry from '../geom/Geometry.js'\nimport hasInterface from '../../../../hasInterface.js'\nimport GeometryFactory from '../geom/GeometryFactory.js'\nimport Collection from '../../../../java/util/Collection.js'\nimport IncrementalDelaunayTriangulator from './IncrementalDelaunayTriangulator.js'\nimport QuadEdgeSubdivision from './quadedge/QuadEdgeSubdivision.js'\nimport DelaunayTriangulationBuilder from './DelaunayTriangulationBuilder.js'\nimport CoordinateArrays from '../geom/CoordinateArrays.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport OverlayOp from '../operation/overlay/OverlayOp.js'\nexport default class VoronoiDiagramBuilder {\n constructor() {\n VoronoiDiagramBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._siteCoords = null\n this._tolerance = 0.0\n this._subdiv = null\n this._clipEnv = null\n this._diagramEnv = null\n }\n static clipGeometryCollection(geom, clipEnv) {\n const clipPoly = geom.getFactory().toGeometry(clipEnv)\n const clipped = new ArrayList()\n for (let i = 0; i < geom.getNumGeometries(); i++) {\n const g = geom.getGeometryN(i)\n let result = null\n if (clipEnv.contains(g.getEnvelopeInternal())) {\n result = g\n } else if (clipEnv.intersects(g.getEnvelopeInternal())) {\n result = OverlayOp.intersection(clipPoly, g)\n result.setUserData(g.getUserData())\n }\n if (result !== null && !result.isEmpty()) \n clipped.add(result)\n \n }\n return geom.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(clipped))\n }\n create() {\n if (this._subdiv !== null) return null\n const siteEnv = DelaunayTriangulationBuilder.envelope(this._siteCoords)\n this._diagramEnv = this._clipEnv\n if (this._diagramEnv === null) {\n this._diagramEnv = siteEnv\n const expandBy = this._diagramEnv.getDiameter()\n this._diagramEnv.expandBy(expandBy)\n }\n const vertices = DelaunayTriangulationBuilder.toVertices(this._siteCoords)\n this._subdiv = new QuadEdgeSubdivision(siteEnv, this._tolerance)\n const triangulator = new IncrementalDelaunayTriangulator(this._subdiv)\n triangulator.insertSites(vertices)\n }\n getDiagram(geomFact) {\n this.create()\n const polys = this._subdiv.getVoronoiDiagram(geomFact)\n return VoronoiDiagramBuilder.clipGeometryCollection(polys, this._diagramEnv)\n }\n setTolerance(tolerance) {\n this._tolerance = tolerance\n }\n setSites() {\n if (arguments[0] instanceof Geometry) {\n const geom = arguments[0]\n this._siteCoords = DelaunayTriangulationBuilder.extractUniqueCoordinates(geom)\n } else if (hasInterface(arguments[0], Collection)) {\n const coords = arguments[0]\n this._siteCoords = DelaunayTriangulationBuilder.unique(CoordinateArrays.toCoordinateArray(coords))\n }\n }\n setClipEnvelope(clipEnv) {\n this._clipEnv = clipEnv\n }\n getSubdivision() {\n this.create()\n return this._subdiv\n }\n}\n","import hasInterface from '../../../../hasInterface.js'\nimport IllegalArgumentException from '../../../../java/lang/IllegalArgumentException.js'\nimport Lineal from '../geom/Lineal.js'\nexport default class LinearIterator {\n constructor() {\n LinearIterator.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._linearGeom = null\n this._numLines = null\n this._currentLine = null\n this._componentIndex = 0\n this._vertexIndex = 0\n if (arguments.length === 1) {\n const linear = arguments[0]\n LinearIterator.constructor_.call(this, linear, 0, 0)\n } else if (arguments.length === 2) {\n const linear = arguments[0], start = arguments[1]\n LinearIterator.constructor_.call(this, linear, start.getComponentIndex(), LinearIterator.segmentEndVertexIndex(start))\n } else if (arguments.length === 3) {\n const linearGeom = arguments[0], componentIndex = arguments[1], vertexIndex = arguments[2]\n if (!hasInterface(linearGeom, Lineal)) throw new IllegalArgumentException('Lineal geometry is required')\n this._linearGeom = linearGeom\n this._numLines = linearGeom.getNumGeometries()\n this._componentIndex = componentIndex\n this._vertexIndex = vertexIndex\n this.loadCurrentLine()\n }\n }\n static segmentEndVertexIndex(loc) {\n if (loc.getSegmentFraction() > 0.0) return loc.getSegmentIndex() + 1\n return loc.getSegmentIndex()\n }\n getComponentIndex() {\n return this._componentIndex\n }\n getLine() {\n return this._currentLine\n }\n getVertexIndex() {\n return this._vertexIndex\n }\n getSegmentEnd() {\n if (this._vertexIndex < this.getLine().getNumPoints() - 1) return this._currentLine.getCoordinateN(this._vertexIndex + 1)\n return null\n }\n next() {\n if (!this.hasNext()) return null\n this._vertexIndex++\n if (this._vertexIndex >= this._currentLine.getNumPoints()) {\n this._componentIndex++\n this.loadCurrentLine()\n this._vertexIndex = 0\n }\n }\n loadCurrentLine() {\n if (this._componentIndex >= this._numLines) {\n this._currentLine = null\n return null\n }\n this._currentLine = this._linearGeom.getGeometryN(this._componentIndex)\n }\n getSegmentStart() {\n return this._currentLine.getCoordinateN(this._vertexIndex)\n }\n isEndOfLine() {\n if (this._componentIndex >= this._numLines) return false\n if (this._vertexIndex < this._currentLine.getNumPoints() - 1) return false\n return true\n }\n hasNext() {\n if (this._componentIndex >= this._numLines) return false\n if (this._componentIndex === this._numLines - 1 && this._vertexIndex >= this._currentLine.getNumPoints()) return false\n return true\n }\n}\n","import LinearIterator from './LinearIterator.js'\nimport Double from '../../../../java/lang/Double.js'\nimport LineSegment from '../geom/LineSegment.js'\nimport Assert from '../util/Assert.js'\nexport default class LengthIndexOfPoint {\n constructor() {\n LengthIndexOfPoint.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._linearGeom = null\n const linearGeom = arguments[0]\n this._linearGeom = linearGeom\n }\n static indexOf(linearGeom, inputPt) {\n const locater = new LengthIndexOfPoint(linearGeom)\n return locater.indexOf(inputPt)\n }\n static indexOfAfter(linearGeom, inputPt, minIndex) {\n const locater = new LengthIndexOfPoint(linearGeom)\n return locater.indexOfAfter(inputPt, minIndex)\n }\n indexOf(inputPt) {\n return this.indexOfFromStart(inputPt, -1.0)\n }\n indexOfFromStart(inputPt, minIndex) {\n let minDistance = Double.MAX_VALUE\n let ptMeasure = minIndex\n let segmentStartMeasure = 0.0\n const seg = new LineSegment()\n const it = new LinearIterator(this._linearGeom)\n while (it.hasNext()) {\n if (!it.isEndOfLine()) {\n seg.p0 = it.getSegmentStart()\n seg.p1 = it.getSegmentEnd()\n const segDistance = seg.distance(inputPt)\n const segMeasureToPt = this.segmentNearestMeasure(seg, inputPt, segmentStartMeasure)\n if (segDistance < minDistance && segMeasureToPt > minIndex) {\n ptMeasure = segMeasureToPt\n minDistance = segDistance\n }\n segmentStartMeasure += seg.getLength()\n }\n it.next()\n }\n return ptMeasure\n }\n indexOfAfter(inputPt, minIndex) {\n if (minIndex < 0.0) return this.indexOf(inputPt)\n const endIndex = this._linearGeom.getLength()\n if (endIndex < minIndex) return endIndex\n const closestAfter = this.indexOfFromStart(inputPt, minIndex)\n Assert.isTrue(closestAfter >= minIndex, 'computed index is before specified minimum index')\n return closestAfter\n }\n segmentNearestMeasure(seg, inputPt, segmentStartMeasure) {\n const projFactor = seg.projectionFactor(inputPt)\n if (projFactor <= 0.0) return segmentStartMeasure\n if (projFactor <= 1.0) return segmentStartMeasure + projFactor * seg.getLength()\n return segmentStartMeasure + seg.getLength()\n }\n}\n","import Coordinate from '../geom/Coordinate.js'\nimport LineSegment from '../geom/LineSegment.js'\nimport Comparable from '../../../../java/lang/Comparable.js'\nexport default class LinearLocation {\n constructor() {\n LinearLocation.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._componentIndex = 0\n this._segmentIndex = 0\n this._segmentFraction = 0.0\n if (arguments.length === 0) {} else if (arguments.length === 1) {\n const loc = arguments[0]\n this._componentIndex = loc._componentIndex\n this._segmentIndex = loc._segmentIndex\n this._segmentFraction = loc._segmentFraction\n } else if (arguments.length === 2) {\n const segmentIndex = arguments[0], segmentFraction = arguments[1]\n LinearLocation.constructor_.call(this, 0, segmentIndex, segmentFraction)\n } else if (arguments.length === 3) {\n const componentIndex = arguments[0], segmentIndex = arguments[1], segmentFraction = arguments[2]\n this._componentIndex = componentIndex\n this._segmentIndex = segmentIndex\n this._segmentFraction = segmentFraction\n this.normalize()\n } else if (arguments.length === 4) {\n const componentIndex = arguments[0], segmentIndex = arguments[1], segmentFraction = arguments[2], doNormalize = arguments[3]\n this._componentIndex = componentIndex\n this._segmentIndex = segmentIndex\n this._segmentFraction = segmentFraction\n if (doNormalize) this.normalize()\n }\n }\n static getEndLocation(linear) {\n const loc = new LinearLocation()\n loc.setToEnd(linear)\n return loc\n }\n static pointAlongSegmentByFraction(p0, p1, frac) {\n if (frac <= 0.0) return p0\n if (frac >= 1.0) return p1\n const x = (p1.x - p0.x) * frac + p0.x\n const y = (p1.y - p0.y) * frac + p0.y\n const z = (p1.getZ() - p0.getZ()) * frac + p0.getZ()\n return new Coordinate(x, y, z)\n }\n static compareLocationValues(componentIndex0, segmentIndex0, segmentFraction0, componentIndex1, segmentIndex1, segmentFraction1) {\n if (componentIndex0 < componentIndex1) return -1\n if (componentIndex0 > componentIndex1) return 1\n if (segmentIndex0 < segmentIndex1) return -1\n if (segmentIndex0 > segmentIndex1) return 1\n if (segmentFraction0 < segmentFraction1) return -1\n if (segmentFraction0 > segmentFraction1) return 1\n return 0\n }\n static numSegments(line) {\n const npts = line.getNumPoints()\n if (npts <= 1) return 0\n return npts - 1\n }\n getSegmentIndex() {\n return this._segmentIndex\n }\n getComponentIndex() {\n return this._componentIndex\n }\n isEndpoint(linearGeom) {\n const lineComp = linearGeom.getGeometryN(this._componentIndex)\n const nseg = LinearLocation.numSegments(lineComp)\n return this._segmentIndex >= nseg || this._segmentIndex === nseg - 1 && this._segmentFraction >= 1.0\n }\n isValid(linearGeom) {\n if (this._componentIndex < 0 || this._componentIndex >= linearGeom.getNumGeometries()) return false\n const lineComp = linearGeom.getGeometryN(this._componentIndex)\n if (this._segmentIndex < 0 || this._segmentIndex > lineComp.getNumPoints()) return false\n if (this._segmentIndex === lineComp.getNumPoints() && this._segmentFraction !== 0.0) return false\n if (this._segmentFraction < 0.0 || this._segmentFraction > 1.0) return false\n return true\n }\n normalize() {\n if (this._segmentFraction < 0.0) \n this._segmentFraction = 0.0\n \n if (this._segmentFraction > 1.0) \n this._segmentFraction = 1.0\n \n if (this._componentIndex < 0) {\n this._componentIndex = 0\n this._segmentIndex = 0\n this._segmentFraction = 0.0\n }\n if (this._segmentIndex < 0) {\n this._segmentIndex = 0\n this._segmentFraction = 0.0\n }\n if (this._segmentFraction === 1.0) {\n this._segmentFraction = 0.0\n this._segmentIndex += 1\n }\n }\n toLowest(linearGeom) {\n const lineComp = linearGeom.getGeometryN(this._componentIndex)\n const nseg = LinearLocation.numSegments(lineComp)\n if (this._segmentIndex < nseg) return this\n return new LinearLocation(this._componentIndex, nseg - 1, 1.0, false)\n }\n getCoordinate(linearGeom) {\n const lineComp = linearGeom.getGeometryN(this._componentIndex)\n const p0 = lineComp.getCoordinateN(this._segmentIndex)\n if (this._segmentIndex >= LinearLocation.numSegments(lineComp)) return p0\n const p1 = lineComp.getCoordinateN(this._segmentIndex + 1)\n return LinearLocation.pointAlongSegmentByFraction(p0, p1, this._segmentFraction)\n }\n getSegmentFraction() {\n return this._segmentFraction\n }\n getSegment(linearGeom) {\n const lineComp = linearGeom.getGeometryN(this._componentIndex)\n const p0 = lineComp.getCoordinateN(this._segmentIndex)\n if (this._segmentIndex >= LinearLocation.numSegments(lineComp)) {\n const prev = lineComp.getCoordinateN(lineComp.getNumPoints() - 2)\n return new LineSegment(prev, p0)\n }\n const p1 = lineComp.getCoordinateN(this._segmentIndex + 1)\n return new LineSegment(p0, p1)\n }\n clamp(linear) {\n if (this._componentIndex >= linear.getNumGeometries()) {\n this.setToEnd(linear)\n return null\n }\n if (this._segmentIndex >= linear.getNumPoints()) {\n const line = linear.getGeometryN(this._componentIndex)\n this._segmentIndex = LinearLocation.numSegments(line)\n this._segmentFraction = 1.0\n }\n }\n setToEnd(linear) {\n this._componentIndex = linear.getNumGeometries() - 1\n const lastLine = linear.getGeometryN(this._componentIndex)\n this._segmentIndex = LinearLocation.numSegments(lastLine)\n this._segmentFraction = 0.0\n }\n compareTo(o) {\n const other = o\n if (this._componentIndex < other._componentIndex) return -1\n if (this._componentIndex > other._componentIndex) return 1\n if (this._segmentIndex < other._segmentIndex) return -1\n if (this._segmentIndex > other._segmentIndex) return 1\n if (this._segmentFraction < other._segmentFraction) return -1\n if (this._segmentFraction > other._segmentFraction) return 1\n return 0\n }\n copy() {\n return new LinearLocation(this._componentIndex, this._segmentIndex, this._segmentFraction)\n }\n toString() {\n return 'LinearLoc[' + this._componentIndex + ', ' + this._segmentIndex + ', ' + this._segmentFraction + ']'\n }\n isOnSameSegment(loc) {\n if (this._componentIndex !== loc._componentIndex) return false\n if (this._segmentIndex === loc._segmentIndex) return true\n if (loc._segmentIndex - this._segmentIndex === 1 && loc._segmentFraction === 0.0) return true\n if (this._segmentIndex - loc._segmentIndex === 1 && this._segmentFraction === 0.0) return true\n return false\n }\n snapToVertex(linearGeom, minDistance) {\n if (this._segmentFraction <= 0.0 || this._segmentFraction >= 1.0) return null\n const segLen = this.getSegmentLength(linearGeom)\n const lenToStart = this._segmentFraction * segLen\n const lenToEnd = segLen - lenToStart\n if (lenToStart <= lenToEnd && lenToStart < minDistance) \n this._segmentFraction = 0.0\n else if (lenToEnd <= lenToStart && lenToEnd < minDistance) \n this._segmentFraction = 1.0\n \n }\n compareLocationValues(componentIndex1, segmentIndex1, segmentFraction1) {\n if (this._componentIndex < componentIndex1) return -1\n if (this._componentIndex > componentIndex1) return 1\n if (this._segmentIndex < segmentIndex1) return -1\n if (this._segmentIndex > segmentIndex1) return 1\n if (this._segmentFraction < segmentFraction1) return -1\n if (this._segmentFraction > segmentFraction1) return 1\n return 0\n }\n getSegmentLength(linearGeom) {\n const lineComp = linearGeom.getGeometryN(this._componentIndex)\n let segIndex = this._segmentIndex\n if (this._segmentIndex >= LinearLocation.numSegments(lineComp)) segIndex = lineComp.getNumPoints() - 2\n const p0 = lineComp.getCoordinateN(segIndex)\n const p1 = lineComp.getCoordinateN(segIndex + 1)\n return p0.distance(p1)\n }\n isVertex() {\n return this._segmentFraction <= 0.0 || this._segmentFraction >= 1.0\n }\n get interfaces_() {\n return [Comparable]\n }\n}\n","import LinearIterator from './LinearIterator.js'\nimport LinearLocation from './LinearLocation.js'\nimport Double from '../../../../java/lang/Double.js'\nimport LineSegment from '../geom/LineSegment.js'\nimport Assert from '../util/Assert.js'\nexport default class LocationIndexOfPoint {\n constructor() {\n LocationIndexOfPoint.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._linearGeom = null\n const linearGeom = arguments[0]\n this._linearGeom = linearGeom\n }\n static indexOf(linearGeom, inputPt) {\n const locater = new LocationIndexOfPoint(linearGeom)\n return locater.indexOf(inputPt)\n }\n static indexOfAfter(linearGeom, inputPt, minIndex) {\n const locater = new LocationIndexOfPoint(linearGeom)\n return locater.indexOfAfter(inputPt, minIndex)\n }\n indexOf(inputPt) {\n return this.indexOfFromStart(inputPt, null)\n }\n indexOfFromStart(inputPt, minIndex) {\n let minDistance = Double.MAX_VALUE\n let minComponentIndex = 0\n let minSegmentIndex = 0\n let minFrac = -1.0\n const seg = new LineSegment()\n for (let it = new LinearIterator(this._linearGeom); it.hasNext(); it.next()) \n if (!it.isEndOfLine()) {\n seg.p0 = it.getSegmentStart()\n seg.p1 = it.getSegmentEnd()\n const segDistance = seg.distance(inputPt)\n const segFrac = seg.segmentFraction(inputPt)\n const candidateComponentIndex = it.getComponentIndex()\n const candidateSegmentIndex = it.getVertexIndex()\n if (segDistance < minDistance) \n if (minIndex === null || minIndex.compareLocationValues(candidateComponentIndex, candidateSegmentIndex, segFrac) < 0) {\n minComponentIndex = candidateComponentIndex\n minSegmentIndex = candidateSegmentIndex\n minFrac = segFrac\n minDistance = segDistance\n }\n \n }\n \n if (minDistance === Double.MAX_VALUE) \n return new LinearLocation(minIndex)\n \n const loc = new LinearLocation(minComponentIndex, minSegmentIndex, minFrac)\n return loc\n }\n indexOfAfter(inputPt, minIndex) {\n if (minIndex === null) return this.indexOf(inputPt)\n const endLoc = LinearLocation.getEndLocation(this._linearGeom)\n if (endLoc.compareTo(minIndex) <= 0) return endLoc\n const closestAfter = this.indexOfFromStart(inputPt, minIndex)\n Assert.isTrue(closestAfter.compareTo(minIndex) >= 0, 'computed location is before specified minimum location')\n return closestAfter\n }\n}\n","import LocationIndexOfPoint from './LocationIndexOfPoint.js'\nexport default class LocationIndexOfLine {\n constructor() {\n LocationIndexOfLine.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._linearGeom = null\n const linearGeom = arguments[0]\n this._linearGeom = linearGeom\n }\n static indicesOf(linearGeom, subLine) {\n const locater = new LocationIndexOfLine(linearGeom)\n return locater.indicesOf(subLine)\n }\n indicesOf(subLine) {\n const startPt = subLine.getGeometryN(0).getCoordinateN(0)\n const lastLine = subLine.getGeometryN(subLine.getNumGeometries() - 1)\n const endPt = lastLine.getCoordinateN(lastLine.getNumPoints() - 1)\n const locPt = new LocationIndexOfPoint(this._linearGeom)\n const subLineLoc = new Array(2).fill(null)\n subLineLoc[0] = locPt.indexOf(startPt)\n if (subLine.getLength() === 0.0) \n subLineLoc[1] = subLineLoc[0].copy()\n else \n subLineLoc[1] = locPt.indexOfAfter(endPt, subLineLoc[0])\n \n return subLineLoc\n }\n}\n","import LinearIterator from './LinearIterator.js'\nimport LinearLocation from './LinearLocation.js'\nexport default class LengthLocationMap {\n constructor() {\n LengthLocationMap.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._linearGeom = null\n const linearGeom = arguments[0]\n this._linearGeom = linearGeom\n }\n static getLength(linearGeom, loc) {\n const locater = new LengthLocationMap(linearGeom)\n return locater.getLength(loc)\n }\n static getLocation() {\n if (arguments.length === 2) {\n const linearGeom = arguments[0], length = arguments[1]\n const locater = new LengthLocationMap(linearGeom)\n return locater.getLocation(length)\n } else if (arguments.length === 3) {\n const linearGeom = arguments[0], length = arguments[1], resolveLower = arguments[2]\n const locater = new LengthLocationMap(linearGeom)\n return locater.getLocation(length, resolveLower)\n }\n }\n getLength(loc) {\n let totalLength = 0.0\n const it = new LinearIterator(this._linearGeom)\n while (it.hasNext()) {\n if (!it.isEndOfLine()) {\n const p0 = it.getSegmentStart()\n const p1 = it.getSegmentEnd()\n const segLen = p1.distance(p0)\n if (loc.getComponentIndex() === it.getComponentIndex() && loc.getSegmentIndex() === it.getVertexIndex()) \n return totalLength + segLen * loc.getSegmentFraction()\n \n totalLength += segLen\n }\n it.next()\n }\n return totalLength\n }\n resolveHigher(loc) {\n if (!loc.isEndpoint(this._linearGeom)) return loc\n let compIndex = loc.getComponentIndex()\n if (compIndex >= this._linearGeom.getNumGeometries() - 1) return loc\n do \n compIndex++\n while (compIndex < this._linearGeom.getNumGeometries() - 1 && this._linearGeom.getGeometryN(compIndex).getLength() === 0)\n return new LinearLocation(compIndex, 0, 0.0)\n }\n getLocation() {\n if (arguments.length === 1) {\n const length = arguments[0]\n return this.getLocation(length, true)\n } else if (arguments.length === 2) {\n const length = arguments[0], resolveLower = arguments[1]\n let forwardLength = length\n if (length < 0.0) {\n const lineLen = this._linearGeom.getLength()\n forwardLength = lineLen + length\n }\n const loc = this.getLocationForward(forwardLength)\n if (resolveLower) \n return loc\n \n return this.resolveHigher(loc)\n }\n }\n getLocationForward(length) {\n if (length <= 0.0) return new LinearLocation()\n let totalLength = 0.0\n const it = new LinearIterator(this._linearGeom)\n while (it.hasNext()) {\n if (it.isEndOfLine()) {\n if (totalLength === length) {\n const compIndex = it.getComponentIndex()\n const segIndex = it.getVertexIndex()\n return new LinearLocation(compIndex, segIndex, 0.0)\n }\n } else {\n const p0 = it.getSegmentStart()\n const p1 = it.getSegmentEnd()\n const segLen = p1.distance(p0)\n if (totalLength + segLen > length) {\n const frac = (length - totalLength) / segLen\n const compIndex = it.getComponentIndex()\n const segIndex = it.getVertexIndex()\n return new LinearLocation(compIndex, segIndex, frac)\n }\n totalLength += segLen\n }\n it.next()\n }\n return LinearLocation.getEndLocation(this._linearGeom)\n }\n}\n","import CoordinateList from '../geom/CoordinateList.js'\nimport IllegalArgumentException from '../../../../java/lang/IllegalArgumentException.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nexport default class LinearGeometryBuilder {\n constructor() {\n LinearGeometryBuilder.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._geomFact = null\n this._lines = new ArrayList()\n this._coordList = null\n this._ignoreInvalidLines = false\n this._fixInvalidLines = false\n this._lastPt = null\n const geomFact = arguments[0]\n this._geomFact = geomFact\n }\n getGeometry() {\n this.endLine()\n return this._geomFact.buildGeometry(this._lines)\n }\n getLastCoordinate() {\n return this._lastPt\n }\n endLine() {\n if (this._coordList === null) \n return null\n \n if (this._ignoreInvalidLines && this._coordList.size() < 2) {\n this._coordList = null\n return null\n }\n const rawPts = this._coordList.toCoordinateArray()\n let pts = rawPts\n if (this._fixInvalidLines) pts = this.validCoordinateSequence(rawPts)\n this._coordList = null\n let line = null\n try {\n line = this._geomFact.createLineString(pts)\n } catch (ex) {\n if (ex instanceof IllegalArgumentException) {\n if (!this._ignoreInvalidLines) throw ex\n } else {\n throw ex\n }\n } finally {}\n if (line !== null) this._lines.add(line)\n }\n setFixInvalidLines(fixInvalidLines) {\n this._fixInvalidLines = fixInvalidLines\n }\n add() {\n if (arguments.length === 1) {\n const pt = arguments[0]\n this.add(pt, true)\n } else if (arguments.length === 2) {\n const pt = arguments[0], allowRepeatedPoints = arguments[1]\n if (this._coordList === null) this._coordList = new CoordinateList()\n this._coordList.add(pt, allowRepeatedPoints)\n this._lastPt = pt\n }\n }\n setIgnoreInvalidLines(ignoreInvalidLines) {\n this._ignoreInvalidLines = ignoreInvalidLines\n }\n validCoordinateSequence(pts) {\n if (pts.length >= 2) return pts\n const validPts = [pts[0], pts[0]]\n return validPts\n }\n}\n","import CoordinateList from '../geom/CoordinateList.js'\nimport hasInterface from '../../../../hasInterface.js'\nimport LinearIterator from './LinearIterator.js'\nimport Lineal from '../geom/Lineal.js'\nimport Assert from '../util/Assert.js'\nimport LinearGeometryBuilder from './LinearGeometryBuilder.js'\nexport default class ExtractLineByLocation {\n constructor() {\n ExtractLineByLocation.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._line = null\n const line = arguments[0]\n this._line = line\n }\n static extract(line, start, end) {\n const ls = new ExtractLineByLocation(line)\n return ls.extract(start, end)\n }\n computeLinear(start, end) {\n const builder = new LinearGeometryBuilder(this._line.getFactory())\n builder.setFixInvalidLines(true)\n if (!start.isVertex()) builder.add(start.getCoordinate(this._line))\n for (let it = new LinearIterator(this._line, start); it.hasNext(); it.next()) {\n if (end.compareLocationValues(it.getComponentIndex(), it.getVertexIndex(), 0.0) < 0) break\n const pt = it.getSegmentStart()\n builder.add(pt)\n if (it.isEndOfLine()) builder.endLine()\n }\n if (!end.isVertex()) builder.add(end.getCoordinate(this._line))\n return builder.getGeometry()\n }\n computeLine(start, end) {\n const coordinates = this._line.getCoordinates()\n const newCoordinates = new CoordinateList()\n let startSegmentIndex = start.getSegmentIndex()\n if (start.getSegmentFraction() > 0.0) startSegmentIndex += 1\n let lastSegmentIndex = end.getSegmentIndex()\n if (end.getSegmentFraction() === 1.0) lastSegmentIndex += 1\n if (lastSegmentIndex >= coordinates.length) lastSegmentIndex = coordinates.length - 1\n if (!start.isVertex()) newCoordinates.add(start.getCoordinate(this._line))\n for (let i = startSegmentIndex; i <= lastSegmentIndex; i++) \n newCoordinates.add(coordinates[i])\n \n if (!end.isVertex()) newCoordinates.add(end.getCoordinate(this._line))\n if (newCoordinates.size() <= 0) newCoordinates.add(start.getCoordinate(this._line))\n let newCoordinateArray = newCoordinates.toCoordinateArray()\n if (newCoordinateArray.length <= 1) \n newCoordinateArray = [newCoordinateArray[0], newCoordinateArray[0]]\n \n return this._line.getFactory().createLineString(newCoordinateArray)\n }\n extract(start, end) {\n if (end.compareTo(start) < 0) \n return this.reverse(this.computeLinear(end, start))\n \n return this.computeLinear(start, end)\n }\n reverse(linear) {\n if (hasInterface(linear, Lineal)) return linear.reverse()\n Assert.shouldNeverReachHere('non-linear geometry encountered')\n return null\n }\n}\n","import LengthIndexOfPoint from './LengthIndexOfPoint.js'\nimport LocationIndexOfLine from './LocationIndexOfLine.js'\nimport LengthLocationMap from './LengthLocationMap.js'\nimport ExtractLineByLocation from './ExtractLineByLocation.js'\nexport default class LengthIndexedLine {\n constructor() {\n LengthIndexedLine.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._linearGeom = null\n const linearGeom = arguments[0]\n this._linearGeom = linearGeom\n }\n clampIndex(index) {\n const posIndex = this.positiveIndex(index)\n const startIndex = this.getStartIndex()\n if (posIndex < startIndex) return startIndex\n const endIndex = this.getEndIndex()\n if (posIndex > endIndex) return endIndex\n return posIndex\n }\n locationOf() {\n if (arguments.length === 1) {\n const index = arguments[0]\n return LengthLocationMap.getLocation(this._linearGeom, index)\n } else if (arguments.length === 2) {\n const index = arguments[0], resolveLower = arguments[1]\n return LengthLocationMap.getLocation(this._linearGeom, index, resolveLower)\n }\n }\n project(pt) {\n return LengthIndexOfPoint.indexOf(this._linearGeom, pt)\n }\n positiveIndex(index) {\n if (index >= 0.0) return index\n return this._linearGeom.getLength() + index\n }\n extractPoint() {\n if (arguments.length === 1) {\n const index = arguments[0]\n const loc = LengthLocationMap.getLocation(this._linearGeom, index)\n return loc.getCoordinate(this._linearGeom)\n } else if (arguments.length === 2) {\n const index = arguments[0], offsetDistance = arguments[1]\n const loc = LengthLocationMap.getLocation(this._linearGeom, index)\n const locLow = loc.toLowest(this._linearGeom)\n return locLow.getSegment(this._linearGeom).pointAlongOffset(locLow.getSegmentFraction(), offsetDistance)\n }\n }\n isValidIndex(index) {\n return index >= this.getStartIndex() && index <= this.getEndIndex()\n }\n getEndIndex() {\n return this._linearGeom.getLength()\n }\n getStartIndex() {\n return 0.0\n }\n indexOfAfter(pt, minIndex) {\n return LengthIndexOfPoint.indexOfAfter(this._linearGeom, pt, minIndex)\n }\n extractLine(startIndex, endIndex) {\n const startIndex2 = this.clampIndex(startIndex)\n const endIndex2 = this.clampIndex(endIndex)\n const resolveStartLower = startIndex2 === endIndex2\n const startLoc = this.locationOf(startIndex2, resolveStartLower)\n const endLoc = this.locationOf(endIndex2)\n return ExtractLineByLocation.extract(this._linearGeom, startLoc, endLoc)\n }\n indexOf(pt) {\n return LengthIndexOfPoint.indexOf(this._linearGeom, pt)\n }\n indicesOf(subLine) {\n const locIndex = LocationIndexOfLine.indicesOf(this._linearGeom, subLine)\n const index = [LengthLocationMap.getLength(this._linearGeom, locIndex[0]), LengthLocationMap.getLength(this._linearGeom, locIndex[1])]\n return index\n }\n}\n","import LineString from '../geom/LineString.js'\nimport IllegalArgumentException from '../../../../java/lang/IllegalArgumentException.js'\nimport LinearLocation from './LinearLocation.js'\nimport LocationIndexOfPoint from './LocationIndexOfPoint.js'\nimport LocationIndexOfLine from './LocationIndexOfLine.js'\nimport ExtractLineByLocation from './ExtractLineByLocation.js'\nimport MultiLineString from '../geom/MultiLineString.js'\nexport default class LocationIndexedLine {\n constructor() {\n LocationIndexedLine.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._linearGeom = null\n const linearGeom = arguments[0]\n this._linearGeom = linearGeom\n this.checkGeometryType()\n }\n clampIndex(index) {\n const loc = index.copy()\n loc.clamp(this._linearGeom)\n return loc\n }\n project(pt) {\n return LocationIndexOfPoint.indexOf(this._linearGeom, pt)\n }\n checkGeometryType() {\n if (!(this._linearGeom instanceof LineString || this._linearGeom instanceof MultiLineString)) throw new IllegalArgumentException('Input geometry must be linear')\n }\n extractPoint() {\n if (arguments.length === 1) {\n const index = arguments[0]\n return index.getCoordinate(this._linearGeom)\n } else if (arguments.length === 2) {\n const index = arguments[0], offsetDistance = arguments[1]\n const indexLow = index.toLowest(this._linearGeom)\n return indexLow.getSegment(this._linearGeom).pointAlongOffset(indexLow.getSegmentFraction(), offsetDistance)\n }\n }\n isValidIndex(index) {\n return index.isValid(this._linearGeom)\n }\n getEndIndex() {\n return LinearLocation.getEndLocation(this._linearGeom)\n }\n getStartIndex() {\n return new LinearLocation()\n }\n indexOfAfter(pt, minIndex) {\n return LocationIndexOfPoint.indexOfAfter(this._linearGeom, pt, minIndex)\n }\n extractLine(startIndex, endIndex) {\n return ExtractLineByLocation.extract(this._linearGeom, startIndex, endIndex)\n }\n indexOf(pt) {\n return LocationIndexOfPoint.indexOf(this._linearGeom, pt)\n }\n indicesOf(subLine) {\n return LocationIndexOfLine.indicesOf(this._linearGeom, subLine)\n }\n}\n","import ArrayList from '../../../../java/util/ArrayList.js'\nexport default class CollectionUtil {\n static transform(coll, func) {\n const result = new ArrayList()\n for (let i = coll.iterator(); i.hasNext(); ) \n result.add(func.execute(i.next()))\n \n return result\n }\n static select(collection, func) {\n const result = new ArrayList()\n for (let i = collection.iterator(); i.hasNext(); ) {\n const item = i.next()\n if (Boolean.TRUE.equals(func.execute(item))) \n result.add(item)\n \n }\n return result\n }\n static apply(coll, func) {\n for (let i = coll.iterator(); i.hasNext(); ) \n func.execute(i.next())\n \n }\n}\nfunction Function() {}\nCollectionUtil.Function = Function\n","import CoordinateFilter from '../geom/CoordinateFilter.js'\nexport default class CoordinateArrayFilter {\n constructor() {\n CoordinateArrayFilter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.pts = null\n this.n = 0\n const size = arguments[0]\n this.pts = new Array(size).fill(null)\n }\n filter(coord) {\n this.pts[this.n++] = coord\n }\n getCoordinates() {\n return this.pts\n }\n get interfaces_() {\n return [CoordinateFilter]\n }\n}\n","import CoordinateFilter from '../geom/CoordinateFilter.js'\nexport default class CoordinateCountFilter {\n constructor() {\n CoordinateCountFilter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._n = 0\n }\n filter(coord) {\n this._n++\n }\n getCount() {\n return this._n\n }\n get interfaces_() {\n return [CoordinateFilter]\n }\n}\n","import HashMap from '../../../../java/util/HashMap.js'\nexport default class ObjectCounter {\n constructor() {\n ObjectCounter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this._counts = new HashMap()\n }\n count(o) {\n const counter = this._counts.get(o)\n if (counter === null) return 0; else return counter.count()\n }\n add(o) {\n const counter = this._counts.get(o)\n if (counter === null) this._counts.put(o, new Counter(1)); else counter.increment()\n }\n}\nclass Counter {\n constructor() {\n Counter.constructor_.apply(this, arguments)\n }\n static constructor_() {\n this.count = 0\n if (arguments.length === 0) {} else if (arguments.length === 1) {\n const count = arguments[0]\n this.count = count\n }\n }\n count() {\n return this.count\n }\n increment() {\n this.count++\n }\n}\nObjectCounter.Counter = Counter\n","export default function PrintStream() {}\n","export default function StringReader() {}\n","export default function ByteArrayOutputStream() {}\n","import Exception from '../lang/Exception.js'\n\nexport default class IOException extends Exception { }","export default function LineNumberReader() {}\n","import PrintStream from '../../../../java/io/PrintStream.js'\nimport StringReader from '../../../../java/io/StringReader.js'\nimport System from '../../../../java/lang/System.js'\nimport ArrayList from '../../../../java/util/ArrayList.js'\nimport ByteArrayOutputStream from '../../../../java/io/ByteArrayOutputStream.js'\nimport Assert from './Assert.js'\nimport IOException from '../../../../java/io/IOException.js'\nimport LineNumberReader from '../../../../java/io/LineNumberReader.js'\nexport default class StringUtil {\n static chars(c, n) {\n const ch = new Array(n).fill(null)\n for (let i = 0; i < n; i++) \n ch[i] = c\n \n return new String(ch)\n }\n static getStackTrace() {\n if (arguments.length === 1) {\n const t = arguments[0]\n const os = new ByteArrayOutputStream()\n const ps = new PrintStream(os)\n t.printStackTrace(ps)\n return os.toString()\n } else if (arguments.length === 2) {\n const t = arguments[0], depth = arguments[1]\n let stackTrace = ''\n const stringReader = new StringReader(StringUtil.getStackTrace(t))\n const lineNumberReader = new LineNumberReader(stringReader)\n for (let i = 0; i < depth; i++) \n try {\n stackTrace += lineNumberReader.readLine() + StringUtil.NEWLINE\n } catch (e) {\n if (e instanceof IOException) \n Assert.shouldNeverReachHere()\n else throw e\n } finally {}\n \n return stackTrace\n }\n }\n static spaces(n) {\n return StringUtil.chars(' ', n)\n }\n static split(s, separator) {\n const separatorlen = separator.length\n const tokenList = new ArrayList()\n let tmpString = '' + s\n let pos = tmpString.indexOf(separator)\n while (pos >= 0) {\n const token = tmpString.substring(0, pos)\n tokenList.add(token)\n tmpString = tmpString.substring(pos + separatorlen)\n pos = tmpString.indexOf(separator)\n }\n if (tmpString.length > 0) tokenList.add(tmpString)\n const res = new Array(tokenList.size()).fill(null)\n for (let i = 0; i < res.length; i++) \n res[i] = tokenList.get(i)\n \n return res\n }\n}\nStringUtil.NEWLINE = System.getProperty('line.separator')\n","import SnapIfNeededOverlayOp from '../overlay/snap/SnapIfNeededOverlayOp.js'\nimport OverlayOp from '../overlay/OverlayOp.js'\nexport default class UnionOp {\n get interfaces_() {\n return []\n }\n\n getClass() {\n return UnionOp\n }\n\n static union(g, other) {\n if (g.isEmpty() || other.isEmpty()) {\n if (g.isEmpty() && other.isEmpty()) return OverlayOp.createEmptyResult(OverlayOp.UNION, g, other, g.getFactory())\n if (g.isEmpty()) return other.copy()\n if (other.isEmpty()) return g.copy()\n }\n g.checkNotGeometryCollection(g)\n g.checkNotGeometryCollection(other)\n return SnapIfNeededOverlayOp.overlayOp(g, other, OverlayOp.UNION)\n }\n}\n","import WKTWriter from './io/WKTWriter.js'\nimport IsValidOp from './operation/valid/IsValidOp.js'\nimport InteriorPointArea from './algorithm/InteriorPointArea.js'\nimport UnaryUnionOp from './operation/union/UnaryUnionOp.js'\nimport UnionOp from './operation/union/UnionOp.js'\nimport InteriorPointLine from './algorithm/InteriorPointLine.js'\nimport IsSimpleOp from './operation/IsSimpleOp.js'\nimport BufferOp from './operation/buffer/BufferOp.js'\nimport ConvexHull from './algorithm/ConvexHull.js'\nimport Centroid from './algorithm/Centroid.js'\nimport RelateOp from './operation/relate/RelateOp.js'\nimport InteriorPointPoint from './algorithm/InteriorPointPoint.js'\nimport DistanceOp from './operation/distance/DistanceOp.js'\nimport OverlayOp from './operation/overlay/OverlayOp.js'\nimport BoundaryOp from './operation/BoundaryOp.js'\nimport Geometry from './geom/Geometry.js'\nimport LineString from './geom/LineString.js'\nimport MultiLineString from './geom/MultiLineString.js'\n\nLineString.prototype.getBoundary = function() {\n return BoundaryOp.getBoundary(this)\n}\n\nMultiLineString.prototype.getBoundary = function() {\n return BoundaryOp.getBoundary(this)\n}\n\nGeometry.prototype.equalsTopo = function(g) {\n return RelateOp.equalsTopo(this, g)\n}\nGeometry.prototype.equals = function(g) {\n if (g === null) return false\n return RelateOp.equalsTopo(this, g)\n}\nGeometry.prototype.union = function() {\n if (arguments.length === 0) {\n return UnaryUnionOp.union(this)\n } else if (arguments.length === 1) {\n const other = arguments[0]\n return UnionOp.union(this, other)\n }\n}\nGeometry.prototype.isValid = function() {\n return IsValidOp.isValid(this)\n}\nGeometry.prototype.intersection = function(other) {\n return OverlayOp.intersection(this, other)\n}\nGeometry.prototype.covers = function(g) {\n return RelateOp.covers(this, g)\n}\nGeometry.prototype.coveredBy = function(g) {\n return RelateOp.covers(g, this)\n}\nGeometry.prototype.touches = function(g) {\n return RelateOp.touches(this, g)\n}\nGeometry.prototype.intersects = function(g) {\n return RelateOp.intersects(this, g)\n}\nGeometry.prototype.within = function(g) {\n return RelateOp.contains(g, this)\n}\nGeometry.prototype.overlaps = function(g) {\n return RelateOp.overlaps(this, g)\n}\nGeometry.prototype.disjoint = function(g) {\n return RelateOp.disjoint(this, g)\n}\nGeometry.prototype.crosses = function(g) {\n return RelateOp.crosses(this, g)\n}\nGeometry.prototype.buffer = function() {\n if (arguments.length === 1) {\n const distance = arguments[0]\n return BufferOp.bufferOp(this, distance)\n } else if (arguments.length === 2) {\n const distance = arguments[0]; const quadrantSegments = arguments[1]\n return BufferOp.bufferOp(this, distance, quadrantSegments)\n } else if (arguments.length === 3) {\n const distance = arguments[0]; const quadrantSegments = arguments[1]; const endCapStyle = arguments[2]\n return BufferOp.bufferOp(this, distance, quadrantSegments, endCapStyle)\n }\n}\nGeometry.prototype.convexHull = function() {\n return new ConvexHull(this).getConvexHull()\n}\nGeometry.prototype.relate = function() {\n if (arguments.length === 1) {\n const geometry = arguments[0]\n return RelateOp.relate(this, geometry)\n } else if (arguments.length === 2) {\n const geometry = arguments[0]; const intersectionPattern = arguments[1]\n return RelateOp.relate(this, geometry).matches(intersectionPattern)\n }\n}\nGeometry.prototype.getCentroid = function() {\n if (this.isEmpty()) return this._factory.createPoint()\n const centPt = Centroid.getCentroid(this)\n return this.createPointFromInternalCoord(centPt, this)\n}\nGeometry.prototype.getInteriorPoint = function() {\n if (this.isEmpty()) return this._factory.createPoint()\n let intPt = null\n const dim = this.getDimension()\n if (dim === 0)\n intPt = new InteriorPointPoint(this)\n else if (dim === 1)\n intPt = new InteriorPointLine(this)\n else intPt = new InteriorPointArea(this)\n\n const interiorPt = intPt.getInteriorPoint()\n return this.createPointFromInternalCoord(interiorPt, this)\n}\nGeometry.prototype.symDifference = function(other) {\n return OverlayOp.symDifference(this, other)\n}\nGeometry.prototype.createPointFromInternalCoord = function(coord, exemplar) {\n exemplar.getPrecisionModel().makePrecise(coord)\n return exemplar.getFactory().createPoint(coord)\n}\nGeometry.prototype.toText = function() {\n const writer = new WKTWriter()\n return writer.write(this)\n}\nGeometry.prototype.toString = function() {\n this.toText()\n}\nGeometry.prototype.contains = function(g) {\n return RelateOp.contains(this, g)\n}\nGeometry.prototype.difference = function(other) {\n return OverlayOp.difference(this, other)\n}\nGeometry.prototype.isSimple = function() {\n const op = new IsSimpleOp(this)\n return op.isSimple()\n}\nGeometry.prototype.isWithinDistance = function(geom, distance) {\n const envDist = this.getEnvelopeInternal().distance(geom.getEnvelopeInternal())\n if (envDist > distance) return false\n return DistanceOp.isWithinDistance(this, geom, distance)\n}\nGeometry.prototype.distance = function(g) {\n return DistanceOp.distance(this, g)\n}\n","import * as geom from './org/locationtech/jts/geom.js'\nimport * as algorithm from './org/locationtech/jts/algorithm.js'\nimport * as densify from './org/locationtech/jts/densify.js'\nimport * as dissolve from './org/locationtech/jts/dissolve.js'\nimport * as geomgraph from './org/locationtech/jts/geomgraph.js'\nimport * as index from './org/locationtech/jts/index.js'\nimport * as io from './org/locationtech/jts/io.js'\nimport * as noding from './org/locationtech/jts/noding.js'\nimport * as operation from './org/locationtech/jts/operation.js'\nimport * as precision from './org/locationtech/jts/precision.js'\nimport * as simplify from './org/locationtech/jts/simplify.js'\nimport * as triangulate from './org/locationtech/jts/triangulate.js'\nimport * as linearref from './org/locationtech/jts/linearref.js'\nimport * as util from './org/locationtech/jts/util.js'\n\nimport './org/locationtech/jts/monkey.js'\n\nconst version = 'npm_package_version (git_hash)'\nexport {\n version,\n algorithm,\n densify,\n dissolve,\n geom,\n geomgraph,\n index,\n io,\n noding,\n operation,\n precision,\n simplify,\n triangulate,\n linearref,\n util\n}\n"]}