import LineString from '../geom/LineString' import CoordinateList from '../geom/CoordinateList' import Geometry from '../geom/Geometry' import hasInterface from '../../../../hasInterface' import Collection from '../../../../java/util/Collection' import Stack from '../../../../java/util/Stack' import MarkHalfEdge from '../edgegraph/MarkHalfEdge' import DissolveEdgeGraph from './DissolveEdgeGraph' import GeometryComponentFilter from '../geom/GeometryComponentFilter' import ArrayList from '../../../../java/util/ArrayList' export default class LineDissolver { constructor() { LineDissolver.constructor_.apply(this, arguments) } static constructor_() { this._result = null this._factory = null this._graph = null this._lines = new ArrayList() this._nodeEdgeStack = new Stack() this._ringStartEdge = null this._graph = new DissolveEdgeGraph() } static dissolve(g) { const d = new LineDissolver() d.add(g) return d.getResult() } addLine(line) { this._lines.add(this._factory.createLineString(line.toCoordinateArray())) } updateRingStartEdge(e) { if (!e.isStart()) { e = e.sym() if (!e.isStart()) return null } if (this._ringStartEdge === null) { this._ringStartEdge = e return null } if (e.orig().compareTo(this._ringStartEdge.orig()) < 0) this._ringStartEdge = e } getResult() { if (this._result === null) this.computeResult() return this._result } process(e) { let eNode = e.prevNode() if (eNode === null) eNode = e this.stackEdges(eNode) this.buildLines() } buildRing(eStartRing) { const line = new CoordinateList() let e = eStartRing line.add(e.orig().copy(), false) while (e.sym().degree() === 2) { const eNext = e.next() if (eNext === eStartRing) break line.add(eNext.orig().copy(), false) e = eNext } line.add(e.dest().copy(), false) this.addLine(line) } buildLine(eStart) { const line = new CoordinateList() let e = eStart this._ringStartEdge = null MarkHalfEdge.markBoth(e) line.add(e.orig().copy(), false) while (e.sym().degree() === 2) { this.updateRingStartEdge(e) const eNext = e.next() if (eNext === eStart) { this.buildRing(this._ringStartEdge) return null } line.add(eNext.orig().copy(), false) e = eNext MarkHalfEdge.markBoth(e) } line.add(e.dest().clone(), false) this.stackEdges(e.sym()) this.addLine(line) } stackEdges(node) { let e = node do { if (!MarkHalfEdge.isMarked(e)) this._nodeEdgeStack.add(e) e = e.oNext() } while (e !== node) } computeResult() { const edges = this._graph.getVertexEdges() for (let i = edges.iterator(); i.hasNext(); ) { const e = i.next() if (MarkHalfEdge.isMarked(e)) continue this.process(e) } this._result = this._factory.buildGeometry(this._lines) } buildLines() { while (!this._nodeEdgeStack.empty()) { const e = this._nodeEdgeStack.pop() if (MarkHalfEdge.isMarked(e)) continue this.buildLine(e) } } add() { if (arguments[0] instanceof Geometry) { const geometry = arguments[0] geometry.apply(new (class { get interfaces_() { return [GeometryComponentFilter] } filter(component) { if (component instanceof LineString) this.add(component) } })()) } else if (hasInterface(arguments[0], Collection)) { const geometries = arguments[0] for (let i = geometries.iterator(); i.hasNext(); ) { const geometry = i.next() this.add(geometry) } } else if (arguments[0] instanceof LineString) { const lineString = arguments[0] if (this._factory === null) this._factory = lineString.getFactory() const seq = lineString.getCoordinateSequence() let doneStart = false for (let i = 1; i < seq.size(); i++) { const e = this._graph.addEdge(seq.getCoordinate(i - 1), seq.getCoordinate(i)) if (e === null) continue if (!doneStart) { e.setStart() doneStart = true } } } } }