UNPKG

node-red-contrib-tak-registration

Version:

A Node-RED node to register to TAK and to help wrap files as datapackages to send to TAK

217 lines (215 loc) 7.32 kB
import GeometryFactory from '../geom/GeometryFactory' import NonEncroachingSplitPointFinder from './NonEncroachingSplitPointFinder' import ConstraintVertex from './ConstraintVertex' import Coordinate from '../geom/Coordinate' import IncrementalDelaunayTriangulator from './IncrementalDelaunayTriangulator' import QuadEdgeSubdivision from './quadedge/QuadEdgeSubdivision' import Double from '../../../../java/lang/Double' import LastFoundQuadEdgeLocator from './quadedge/LastFoundQuadEdgeLocator' import Segment from './Segment' import ConvexHull from '../algorithm/ConvexHull' import KdTree from '../index/kdtree/KdTree' import ArrayList from '../../../../java/util/ArrayList' import Envelope from '../geom/Envelope' export default class ConformingDelaunayTriangulator { constructor () { this._initialVertices = null this._segVertices = null this._segments = new ArrayList() this._subdiv = null this._incDel = null this._convexHull = null this._splitFinder = new NonEncroachingSplitPointFinder() this._kdt = null this._vertexFactory = null this._computeAreaEnv = null this._splitPt = null this._tolerance = null const initialVertices = arguments[0] const tolerance = arguments[1] this._initialVertices = new ArrayList(initialVertices) this._tolerance = tolerance this._kdt = new KdTree(tolerance) } getInitialVertices () { return this._initialVertices } getKDT () { return this._kdt } enforceConstraints () { this.addConstraintVertices() let count = 0 let splits = 0 do { splits = this.enforceGabriel(this._segments) count++ } while (splits > 0 && count < ConformingDelaunayTriangulator.MAX_SPLIT_ITER) } insertSites (vertices) { for (const i = vertices.iterator(); i.hasNext();) { const v = i.next() this.insertSite(v) } } getVertexFactory () { return this._vertexFactory } getPointArray () { const pts = new Array(this._initialVertices.size() + this._segVertices.size()).fill(null) let index = 0 for (const i = this._initialVertices.iterator(); i.hasNext();) { const v = i.next() pts[index++] = v.getCoordinate() } for (const i2 = this._segVertices.iterator(); i2.hasNext();) { const v = i2.next() pts[index++] = v.getCoordinate() } return pts } setConstraints (segments, segVertices) { this._segments = segments this._segVertices = segVertices } computeConvexHull () { const fact = new GeometryFactory() const coords = this.getPointArray() const hull = new ConvexHull(coords, fact) this._convexHull = hull.getConvexHull() } addConstraintVertices () { this.computeConvexHull() this.insertSites(this._segVertices) } findNonGabrielPoint (seg) { const p = seg.getStart() const q = seg.getEnd() const midPt = new Coordinate((p.x + q.x) / 2.0, (p.y + q.y) / 2.0) const segRadius = p.distance(midPt) const env = new Envelope(midPt) env.expandBy(segRadius) const result = this._kdt.query(env) let closestNonGabriel = null let minDist = Double.MAX_VALUE for (const i = result.iterator(); i.hasNext();) { const nextNode = i.next() const testPt = nextNode.getCoordinate() if (testPt.equals2D(p) || testPt.equals2D(q)) continue const testRadius = midPt.distance(testPt) if (testRadius < segRadius) { const testDist = testRadius if (closestNonGabriel === null || testDist < minDist) { closestNonGabriel = testPt minDist = testDist } } } return closestNonGabriel } getConstraintSegments () { return this._segments } setSplitPointFinder (splitFinder) { this._splitFinder = splitFinder } getConvexHull () { return this._convexHull } getTolerance () { return this._tolerance } enforceGabriel (segsToInsert) { const newSegments = new ArrayList() let splits = 0 const segsToRemove = new ArrayList() for (const i = segsToInsert.iterator(); i.hasNext();) { const seg = i.next() const encroachPt = this.findNonGabrielPoint(seg) if (encroachPt === null) continue this._splitPt = this._splitFinder.findSplitPoint(seg, encroachPt) const splitVertex = this.createVertex(this._splitPt, seg) // const insertedVertex = this.insertSite(splitVertex) const s1 = new Segment(seg.getStartX(), seg.getStartY(), seg.getStartZ(), splitVertex.getX(), splitVertex.getY(), splitVertex.getZ(), seg.getData()) const s2 = new Segment(splitVertex.getX(), splitVertex.getY(), splitVertex.getZ(), seg.getEndX(), seg.getEndY(), seg.getEndZ(), seg.getData()) newSegments.add(s1) newSegments.add(s2) segsToRemove.add(seg) splits = splits + 1 } segsToInsert.removeAll(segsToRemove) segsToInsert.addAll(newSegments) return splits } createVertex () { if (arguments.length === 1) { const p = arguments[0] let v = null if (this._vertexFactory !== null) v = this._vertexFactory.createVertex(p, null); else v = new ConstraintVertex(p) return v } else if (arguments.length === 2) { const p = arguments[0] const seg = arguments[1] let v = null if (this._vertexFactory !== null) v = this._vertexFactory.createVertex(p, seg); else v = new ConstraintVertex(p) v.setOnConstraint(true) return v } } getSubdivision () { return this._subdiv } computeBoundingBox () { const vertexEnv = ConformingDelaunayTriangulator.computeVertexEnvelope(this._initialVertices) const segEnv = ConformingDelaunayTriangulator.computeVertexEnvelope(this._segVertices) const allPointsEnv = new Envelope(vertexEnv) allPointsEnv.expandToInclude(segEnv) const deltaX = allPointsEnv.getWidth() * 0.2 const deltaY = allPointsEnv.getHeight() * 0.2 const delta = Math.max(deltaX, deltaY) this._computeAreaEnv = new Envelope(allPointsEnv) this._computeAreaEnv.expandBy(delta) } setVertexFactory (vertexFactory) { this._vertexFactory = vertexFactory } formInitialDelaunay () { this.computeBoundingBox() this._subdiv = new QuadEdgeSubdivision(this._computeAreaEnv, this._tolerance) this._subdiv.setLocator(new LastFoundQuadEdgeLocator(this._subdiv)) this._incDel = new IncrementalDelaunayTriangulator(this._subdiv) this.insertSites(this._initialVertices) } insertSite () { if (arguments[0] instanceof ConstraintVertex) { const v = arguments[0] const kdnode = this._kdt.insert(v.getCoordinate(), v) if (!kdnode.isRepeated()) { this._incDel.insertSite(v) } else { const snappedV = kdnode.getData() snappedV.merge(v) return snappedV } return v } else if (arguments[0] instanceof Coordinate) { const p = arguments[0] this.insertSite(this.createVertex(p)) } } interfaces_ () { return [] } getClass () { return ConformingDelaunayTriangulator } static computeVertexEnvelope (vertices) { const env = new Envelope() for (const i = vertices.iterator(); i.hasNext();) { const v = i.next() env.expandToInclude(v.getCoordinate()) } return env } static get MAX_SPLIT_ITER () { return 99 } }