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
JavaScript
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)
}
}