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
118 lines (116 loc) • 3.9 kB
JavaScript
import Location from '../../geom/Location'
import hasInterface from '../../../../../hasInterface'
import Coordinate from '../../geom/Coordinate'
import AxisPlaneCoordinateSequence from './AxisPlaneCoordinateSequence'
import Vector3D from '../../math/Vector3D'
import CoordinateSequence from '../../geom/CoordinateSequence'
import Plane3D from '../../math/Plane3D'
import RayCrossingCounter from '../../algorithm/RayCrossingCounter'
export default class PlanarPolygon3D {
constructor () {
this._plane = null
this._poly = null
this._facingPlane = -1
const poly = arguments[0]
this._poly = poly
this._plane = this.findBestFitPlane(poly)
this._facingPlane = this._plane.closestAxisPlane()
}
intersects () {
if (arguments.length === 1) {
const intPt = arguments[0]
if (Location.EXTERIOR === this.locate(intPt, this._poly.getExteriorRing())) return false
for (let i = 0; i < this._poly.getNumInteriorRing(); i++) {
if (Location.INTERIOR === this.locate(intPt, this._poly.getInteriorRingN(i))) return false
}
return true
} else if (arguments.length === 2) {
const pt = arguments[0]
const ring = arguments[1]
const seq = ring.getCoordinateSequence()
const seqProj = PlanarPolygon3D.project(seq, this._facingPlane)
const ptProj = PlanarPolygon3D.project(pt, this._facingPlane)
return Location.EXTERIOR !== RayCrossingCounter.locatePointInRing(ptProj, seqProj)
}
}
averagePoint (seq) {
const a = new Coordinate(0, 0, 0)
const n = seq.size()
for (let i = 0; i < n; i++) {
a.x += seq.getOrdinate(i, CoordinateSequence.X)
a.y += seq.getOrdinate(i, CoordinateSequence.Y)
a.z += seq.getOrdinate(i, CoordinateSequence.Z)
}
a.x /= n
a.y /= n
a.z /= n
return a
}
getPolygon () {
return this._poly
}
getPlane () {
return this._plane
}
findBestFitPlane (poly) {
const seq = poly.getExteriorRing().getCoordinateSequence()
const basePt = this.averagePoint(seq)
const normal = this.averageNormal(seq)
return new Plane3D(normal, basePt)
}
averageNormal (seq) {
const n = seq.size()
const sum = new Coordinate(0, 0, 0)
const p1 = new Coordinate(0, 0, 0)
const p2 = new Coordinate(0, 0, 0)
for (let i = 0; i < n - 1; i++) {
seq.getCoordinate(i, p1)
seq.getCoordinate(i + 1, p2)
sum.x += (p1.y - p2.y) * (p1.z + p2.z)
sum.y += (p1.z - p2.z) * (p1.x + p2.x)
sum.z += (p1.x - p2.x) * (p1.y + p2.y)
}
sum.x /= n
sum.y /= n
sum.z /= n
const norm = Vector3D.create(sum).normalize()
return norm
}
locate (pt, ring) {
const seq = ring.getCoordinateSequence()
const seqProj = PlanarPolygon3D.project(seq, this._facingPlane)
const ptProj = PlanarPolygon3D.project(pt, this._facingPlane)
return RayCrossingCounter.locatePointInRing(ptProj, seqProj)
}
interfaces_ () {
return []
}
getClass () {
return PlanarPolygon3D
}
static project () {
if (hasInterface(arguments[0], CoordinateSequence) && Number.isInteger(arguments[1])) {
const seq = arguments[0]
const facingPlane = arguments[1]
switch (facingPlane) {
case Plane3D.XY_PLANE:
return AxisPlaneCoordinateSequence.projectToXY(seq)
case Plane3D.XZ_PLANE:
return AxisPlaneCoordinateSequence.projectToXZ(seq)
default:
return AxisPlaneCoordinateSequence.projectToYZ(seq)
}
} else if (arguments[0] instanceof Coordinate && Number.isInteger(arguments[1])) {
const p = arguments[0]
const facingPlane = arguments[1]
switch (facingPlane) {
case Plane3D.XY_PLANE:
return new Coordinate(p.x, p.y)
case Plane3D.XZ_PLANE:
return new Coordinate(p.x, p.z)
default:
return new Coordinate(p.y, p.z)
}
}
}
}