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

166 lines (164 loc) 6.13 kB
import Coordinate from '../geom/Coordinate' import Polygon from '../geom/Polygon' import Double from '../../../../java/lang/Double' import LineSegment from '../geom/LineSegment' import ConvexHull from './ConvexHull' export default class MinimumDiameter { constructor () { this._inputGeom = null this._isConvex = null this._convexHullPts = null this._minBaseSeg = new LineSegment() this._minWidthPt = null this._minPtIndex = null this._minWidth = 0.0 if (arguments.length === 1) { const inputGeom = arguments[0] const isConvex = false this._inputGeom = inputGeom this._isConvex = isConvex } else if (arguments.length === 2) { const inputGeom = arguments[0] const isConvex = arguments[1] this._inputGeom = inputGeom this._isConvex = isConvex } } getWidthCoordinate () { this.computeMinimumDiameter() return this._minWidthPt } getSupportingSegment () { this.computeMinimumDiameter() return this._inputGeom.getFactory().createLineString([this._minBaseSeg.p0, this._minBaseSeg.p1]) } getDiameter () { this.computeMinimumDiameter() if (this._minWidthPt === null) return this._inputGeom.getFactory().createLineString(null) const basePt = this._minBaseSeg.project(this._minWidthPt) return this._inputGeom.getFactory().createLineString([basePt, this._minWidthPt]) } computeWidthConvex (convexGeom) { if (convexGeom instanceof Polygon) this._convexHullPts = convexGeom.getExteriorRing().getCoordinates(); else this._convexHullPts = convexGeom.getCoordinates() if (this._convexHullPts.length === 0) { this._minWidth = 0.0 this._minWidthPt = null this._minBaseSeg = null } else if (this._convexHullPts.length === 1) { this._minWidth = 0.0 this._minWidthPt = this._convexHullPts[0] this._minBaseSeg.p0 = this._convexHullPts[0] this._minBaseSeg.p1 = this._convexHullPts[0] } else if (this._convexHullPts.length === 2 || this._convexHullPts.length === 3) { this._minWidth = 0.0 this._minWidthPt = this._convexHullPts[0] this._minBaseSeg.p0 = this._convexHullPts[0] this._minBaseSeg.p1 = this._convexHullPts[1] } else this.computeConvexRingMinDiameter(this._convexHullPts) } computeConvexRingMinDiameter (pts) { this._minWidth = Double.MAX_VALUE let currMaxIndex = 1 const seg = new LineSegment() for (let i = 0; i < pts.length - 1; i++) { seg.p0 = pts[i] seg.p1 = pts[i + 1] currMaxIndex = this.findMaxPerpDistance(pts, seg, currMaxIndex) } } computeMinimumDiameter () { if (this._minWidthPt !== null) return null if (this._isConvex) this.computeWidthConvex(this._inputGeom); else { const convexGeom = new ConvexHull(this._inputGeom).getConvexHull() this.computeWidthConvex(convexGeom) } } getLength () { this.computeMinimumDiameter() return this._minWidth } findMaxPerpDistance (pts, seg, startIndex) { let maxPerpDistance = seg.distancePerpendicular(pts[startIndex]) let nextPerpDistance = maxPerpDistance let maxIndex = startIndex let nextIndex = maxIndex while (nextPerpDistance >= maxPerpDistance) { maxPerpDistance = nextPerpDistance maxIndex = nextIndex nextIndex = MinimumDiameter.nextIndex(pts, maxIndex) nextPerpDistance = seg.distancePerpendicular(pts[nextIndex]) } if (maxPerpDistance < this._minWidth) { this._minPtIndex = maxIndex this._minWidth = maxPerpDistance this._minWidthPt = pts[this._minPtIndex] this._minBaseSeg = new LineSegment(seg) } return maxIndex } getMinimumRectangle () { this.computeMinimumDiameter() if (this._minWidth === 0.0) { if (this._minBaseSeg.p0.equals2D(this._minBaseSeg.p1)) { return this._inputGeom.getFactory().createPoint(this._minBaseSeg.p0) } return this._minBaseSeg.toGeometry(this._inputGeom.getFactory()) } const dx = this._minBaseSeg.p1.x - this._minBaseSeg.p0.x const dy = this._minBaseSeg.p1.y - this._minBaseSeg.p0.y let minPara = Double.MAX_VALUE let maxPara = -Double.MAX_VALUE let minPerp = Double.MAX_VALUE let maxPerp = -Double.MAX_VALUE for (let i = 0; i < this._convexHullPts.length; i++) { const paraC = MinimumDiameter.computeC(dx, dy, this._convexHullPts[i]) if (paraC > maxPara) maxPara = paraC if (paraC < minPara) minPara = paraC const perpC = MinimumDiameter.computeC(-dy, dx, this._convexHullPts[i]) if (perpC > maxPerp) maxPerp = perpC if (perpC < minPerp) minPerp = perpC } const maxPerpLine = MinimumDiameter.computeSegmentForLine(-dx, -dy, maxPerp) const minPerpLine = MinimumDiameter.computeSegmentForLine(-dx, -dy, minPerp) const maxParaLine = MinimumDiameter.computeSegmentForLine(-dy, dx, maxPara) const minParaLine = MinimumDiameter.computeSegmentForLine(-dy, dx, minPara) const p0 = maxParaLine.lineIntersection(maxPerpLine) const p1 = minParaLine.lineIntersection(maxPerpLine) const p2 = minParaLine.lineIntersection(minPerpLine) const p3 = maxParaLine.lineIntersection(minPerpLine) const shell = this._inputGeom.getFactory().createLinearRing([p0, p1, p2, p3, p0]) return this._inputGeom.getFactory().createPolygon(shell, null) } interfaces_ () { return [] } getClass () { return MinimumDiameter } static nextIndex (pts, index) { index++ if (index >= pts.length) index = 0 return index } static computeC (a, b, p) { return a * p.y - b * p.x } static getMinimumDiameter (geom) { return new MinimumDiameter(geom).getDiameter() } static getMinimumRectangle (geom) { return new MinimumDiameter(geom).getMinimumRectangle() } static computeSegmentForLine (a, b, c) { let p0 = null let p1 = null if (Math.abs(b) > Math.abs(a)) { p0 = new Coordinate(0.0, c / b) p1 = new Coordinate(1.0, c / b - a / b) } else { p0 = new Coordinate(c / a, 0.0) p1 = new Coordinate(c / a - b / a, 1.0) } return new LineSegment(p0, p1) } }