UNPKG

jsts

Version:

A JavaScript library of spatial predicates and functions for processing geometry

125 lines (123 loc) 4.3 kB
import LineSegment from '../geom/LineSegment.js' import LineSegmentIndex from './LineSegmentIndex.js' import RobustLineIntersector from '../algorithm/RobustLineIntersector.js' export default class TaggedLineStringSimplifier { constructor() { TaggedLineStringSimplifier.constructor_.apply(this, arguments) } static constructor_() { this._li = new RobustLineIntersector() this._inputIndex = new LineSegmentIndex() this._outputIndex = new LineSegmentIndex() this._line = null this._linePts = null this._distanceTolerance = 0.0 const inputIndex = arguments[0], outputIndex = arguments[1] this._inputIndex = inputIndex this._outputIndex = outputIndex } static isInLineSection(line, sectionIndex, seg) { if (seg.getParent() !== line.getParent()) return false const segIndex = seg.getIndex() if (segIndex >= sectionIndex[0] && segIndex < sectionIndex[1]) return true return false } flatten(start, end) { const p0 = this._linePts[start] const p1 = this._linePts[end] const newSeg = new LineSegment(p0, p1) this.remove(this._line, start, end) this._outputIndex.add(newSeg) return newSeg } hasBadIntersection(parentLine, sectionIndex, candidateSeg) { if (this.hasBadOutputIntersection(candidateSeg)) return true if (this.hasBadInputIntersection(parentLine, sectionIndex, candidateSeg)) return true return false } setDistanceTolerance(distanceTolerance) { this._distanceTolerance = distanceTolerance } simplifySection(i, j, depth) { depth += 1 const sectionIndex = new Array(2).fill(null) if (i + 1 === j) { const newSeg = this._line.getSegment(i) this._line.addToResult(newSeg) return null } let isValidToSimplify = true if (this._line.getResultSize() < this._line.getMinimumSize()) { const worstCaseSize = depth + 1 if (worstCaseSize < this._line.getMinimumSize()) isValidToSimplify = false } const distance = new Array(1).fill(null) const furthestPtIndex = this.findFurthestPoint(this._linePts, i, j, distance) if (distance[0] > this._distanceTolerance) isValidToSimplify = false const candidateSeg = new LineSegment() candidateSeg.p0 = this._linePts[i] candidateSeg.p1 = this._linePts[j] sectionIndex[0] = i sectionIndex[1] = j if (this.hasBadIntersection(this._line, sectionIndex, candidateSeg)) isValidToSimplify = false if (isValidToSimplify) { const newSeg = this.flatten(i, j) this._line.addToResult(newSeg) return null } this.simplifySection(i, furthestPtIndex, depth) this.simplifySection(furthestPtIndex, j, depth) } hasBadOutputIntersection(candidateSeg) { const querySegs = this._outputIndex.query(candidateSeg) for (let i = querySegs.iterator(); i.hasNext(); ) { const querySeg = i.next() if (this.hasInteriorIntersection(querySeg, candidateSeg)) return true } return false } hasInteriorIntersection(seg0, seg1) { this._li.computeIntersection(seg0.p0, seg0.p1, seg1.p0, seg1.p1) return this._li.isInteriorIntersection() } hasBadInputIntersection(parentLine, sectionIndex, candidateSeg) { const querySegs = this._inputIndex.query(candidateSeg) for (let i = querySegs.iterator(); i.hasNext(); ) { const querySeg = i.next() if (this.hasInteriorIntersection(querySeg, candidateSeg)) { if (TaggedLineStringSimplifier.isInLineSection(parentLine, sectionIndex, querySeg)) continue return true } } return false } findFurthestPoint(pts, i, j, maxDistance) { const seg = new LineSegment() seg.p0 = pts[i] seg.p1 = pts[j] let maxDist = -1.0 let maxIndex = i for (let k = i + 1; k < j; k++) { const midPt = pts[k] const distance = seg.distance(midPt) if (distance > maxDist) { maxDist = distance maxIndex = k } } maxDistance[0] = maxDist return maxIndex } simplify(line) { this._line = line this._linePts = line.getParentCoordinates() this.simplifySection(0, this._linePts.length - 1, 0) } remove(line, start, end) { for (let i = start; i < end; i++) { const seg = line.getSegment(i) this._inputIndex.remove(seg) } } }