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
313 lines (311 loc) • 11.8 kB
JavaScript
import LineString from '../../geom/LineString'
import Geometry from '../../geom/Geometry'
import Coordinate from '../../geom/Coordinate'
import IllegalArgumentException from '../../../../../java/lang/IllegalArgumentException'
import Point from '../../geom/Point'
import PlanarPolygon3D from './PlanarPolygon3D'
import Polygon from '../../geom/Polygon'
import GeometryLocation from '../distance/GeometryLocation'
import Double from '../../../../../java/lang/Double'
import LineSegment from '../../geom/LineSegment'
import GeometryCollection from '../../geom/GeometryCollection'
import CGAlgorithms3D from '../../algorithm/CGAlgorithms3D'
export default class Distance3DOp {
constructor () {
this._geom = null
this._terminateDistance = 0.0
this._minDistanceLocation = null
this._minDistance = Double.MAX_VALUE
this._isDone = false
if (arguments.length === 2) {
const g0 = arguments[0]
const g1 = arguments[1]
Distance3DOp.call(this, g0, g1, 0.0)
} else if (arguments.length === 3) {
const g0 = arguments[0]
const g1 = arguments[1]
const terminateDistance = arguments[2]
this._geom = new Array(2).fill(null)
this._geom[0] = g0
this._geom[1] = g1
this._terminateDistance = terminateDistance
}
}
computeMinDistancePolygonPoint (polyPlane, point, flip) {
const pt = point.getCoordinate()
const shell = polyPlane.getPolygon().getExteriorRing()
if (polyPlane.intersects(pt, shell)) {
const nHole = polyPlane.getPolygon().getNumInteriorRing()
for (let i = 0; i < nHole; i++) {
const hole = polyPlane.getPolygon().getInteriorRingN(i)
if (polyPlane.intersects(pt, hole)) {
this.computeMinDistanceLinePoint(hole, point, flip)
return null
}
}
const dist = Math.abs(polyPlane.getPlane().orientedDistance(pt))
this.updateDistance(dist, new GeometryLocation(polyPlane.getPolygon(), 0, pt), new GeometryLocation(point, 0, pt), flip)
}
this.computeMinDistanceLinePoint(shell, point, flip)
}
intersection (poly, line) {
const seq = line.getCoordinateSequence()
if (seq.size() === 0) return null
const p0 = new Coordinate()
seq.getCoordinate(0, p0)
let d0 = poly.getPlane().orientedDistance(p0)
const p1 = new Coordinate()
for (let i = 0; i < seq.size() - 1; i++) {
seq.getCoordinate(i, p0)
seq.getCoordinate(i + 1, p1)
const d1 = poly.getPlane().orientedDistance(p1)
if (d0 * d1 > 0) continue
const intPt = Distance3DOp.segmentPoint(p0, p1, d0, d1)
if (poly.intersects(intPt)) {
return intPt
}
d0 = d1
}
return null
}
computeMinDistancePolygonPolygon (poly0, poly1, flip) {
this.computeMinDistancePolygonRings(poly0, poly1, flip)
if (this._isDone) return null
const polyPlane1 = new PlanarPolygon3D(poly1)
this.computeMinDistancePolygonRings(polyPlane1, poly0.getPolygon(), flip)
}
computeMinDistancePointPoint (point0, point1, flip) {
const dist = CGAlgorithms3D.distance(point0.getCoordinate(), point1.getCoordinate())
if (dist < this._minDistance) {
this.updateDistance(dist, new GeometryLocation(point0, 0, point0.getCoordinate()), new GeometryLocation(point1, 0, point1.getCoordinate()), flip)
}
}
computeMinDistanceMultiMulti (g0, g1, flip) {
if (g0 instanceof GeometryCollection) {
const n = g0.getNumGeometries()
for (let i = 0; i < n; i++) {
const g = g0.getGeometryN(i)
this.computeMinDistanceMultiMulti(g, g1, flip)
if (this._isDone) return null
}
} else {
if (g0.isEmpty()) return null
if (g0 instanceof Polygon) {
this.computeMinDistanceOneMulti(Distance3DOp.polyPlane(g0), g1, flip)
} else this.computeMinDistanceOneMulti(g0, g1, flip)
}
}
computeMinDistanceOneMulti () {
if (typeof arguments[2] === 'boolean' && (arguments[0] instanceof Geometry && arguments[1] instanceof Geometry)) {
const g0 = arguments[0]
const g1 = arguments[1]
const flip = arguments[2]
if (g1 instanceof GeometryCollection) {
const n = g1.getNumGeometries()
for (let i = 0; i < n; i++) {
const g = g1.getGeometryN(i)
this.computeMinDistanceOneMulti(g0, g, flip)
if (this._isDone) return null
}
} else {
this.computeMinDistance(g0, g1, flip)
}
} else if (typeof arguments[2] === 'boolean' && (arguments[0] instanceof PlanarPolygon3D && arguments[1] instanceof Geometry)) {
const poly = arguments[0]
const geom = arguments[1]
const flip = arguments[2]
if (geom instanceof GeometryCollection) {
const n = geom.getNumGeometries()
for (let i = 0; i < n; i++) {
const g = geom.getGeometryN(i)
this.computeMinDistanceOneMulti(poly, g, flip)
if (this._isDone) return null
}
} else {
if (geom instanceof Point) {
this.computeMinDistancePolygonPoint(poly, geom, flip)
return null
}
if (geom instanceof LineString) {
this.computeMinDistancePolygonLine(poly, geom, flip)
return null
}
if (geom instanceof Polygon) {
this.computeMinDistancePolygonPolygon(poly, geom, flip)
return null
}
}
}
}
computeMinDistanceLinePoint (line, point, flip) {
const lineCoord = line.getCoordinates()
const coord = point.getCoordinate()
for (let i = 0; i < lineCoord.length - 1; i++) {
const dist = CGAlgorithms3D.distancePointSegment(coord, lineCoord[i], lineCoord[i + 1])
if (dist < this._minDistance) {
const seg = new LineSegment(lineCoord[i], lineCoord[i + 1])
const segClosestPoint = seg.closestPoint(coord)
this.updateDistance(dist, new GeometryLocation(line, i, segClosestPoint), new GeometryLocation(point, 0, coord), flip)
}
if (this._isDone) return null
}
}
nearestLocations () {
this.computeMinDistance()
return this._minDistanceLocation
}
nearestPoints () {
this.computeMinDistance()
const nearestPts = [this._minDistanceLocation[0].getCoordinate(), this._minDistanceLocation[1].getCoordinate()]
return nearestPts
}
computeMinDistance () {
if (arguments.length === 0) {
if (this._minDistanceLocation !== null) return null
this._minDistanceLocation = new Array(2).fill(null)
const geomIndex = this.mostPolygonalIndex()
const flip = geomIndex === 0
this.computeMinDistanceMultiMulti(this._geom[geomIndex], this._geom[1 - geomIndex], flip)
} else if (arguments.length === 3) {
const g0 = arguments[0]
const g1 = arguments[1]
const flip = arguments[2]
if (g0 instanceof Point) {
if (g1 instanceof Point) {
this.computeMinDistancePointPoint(g0, g1, flip)
return null
}
if (g1 instanceof LineString) {
this.computeMinDistanceLinePoint(g1, g0, !flip)
return null
}
if (g1 instanceof Polygon) {
this.computeMinDistancePolygonPoint(Distance3DOp.polyPlane(g1), g0, !flip)
return null
}
}
if (g0 instanceof LineString) {
if (g1 instanceof Point) {
this.computeMinDistanceLinePoint(g0, g1, flip)
return null
}
if (g1 instanceof LineString) {
this.computeMinDistanceLineLine(g0, g1, flip)
return null
}
if (g1 instanceof Polygon) {
this.computeMinDistancePolygonLine(Distance3DOp.polyPlane(g1), g0, !flip)
return null
}
}
if (g0 instanceof Polygon) {
if (g1 instanceof Point) {
this.computeMinDistancePolygonPoint(Distance3DOp.polyPlane(g0), g1, flip)
return null
}
if (g1 instanceof LineString) {
this.computeMinDistancePolygonLine(Distance3DOp.polyPlane(g0), g1, flip)
return null
}
if (g1 instanceof Polygon) {
this.computeMinDistancePolygonPolygon(Distance3DOp.polyPlane(g0), g1, flip)
return null
}
}
}
}
computeMinDistanceLineLine (line0, line1, flip) {
const coord0 = line0.getCoordinates()
const coord1 = line1.getCoordinates()
for (let i = 0; i < coord0.length - 1; i++) {
for (let j = 0; j < coord1.length - 1; j++) {
const dist = CGAlgorithms3D.distanceSegmentSegment(coord0[i], coord0[i + 1], coord1[j], coord1[j + 1])
if (dist < this._minDistance) {
this._minDistance = dist
const seg0 = new LineSegment(coord0[i], coord0[i + 1])
const seg1 = new LineSegment(coord1[j], coord1[j + 1])
const closestPt = seg0.closestPoints(seg1)
this.updateDistance(dist, new GeometryLocation(line0, i, closestPt[0]), new GeometryLocation(line1, j, closestPt[1]), flip)
}
if (this._isDone) return null
}
}
}
computeMinDistancePolygonLine (poly, line, flip) {
const intPt = this.intersection(poly, line)
if (intPt !== null) {
this.updateDistance(0, new GeometryLocation(poly.getPolygon(), 0, intPt), new GeometryLocation(line, 0, intPt), flip)
return null
}
this.computeMinDistanceLineLine(poly.getPolygon().getExteriorRing(), line, flip)
if (this._isDone) return null
const nHole = poly.getPolygon().getNumInteriorRing()
for (let i = 0; i < nHole; i++) {
this.computeMinDistanceLineLine(poly.getPolygon().getInteriorRingN(i), line, flip)
if (this._isDone) return null
}
}
distance () {
if (this._geom[0] === null || this._geom[1] === null) throw new IllegalArgumentException('null geometries are not supported')
if (this._geom[0].isEmpty() || this._geom[1].isEmpty()) return 0.0
this.computeMinDistance()
return this._minDistance
}
mostPolygonalIndex () {
const dim0 = this._geom[0].getDimension()
const dim1 = this._geom[1].getDimension()
if (dim0 >= 2 && dim1 >= 2) {
if (this._geom[0].getNumPoints() > this._geom[1].getNumPoints()) return 0
return 1
}
if (dim0 >= 2) return 0
if (dim1 >= 2) return 1
return 0
}
computeMinDistancePolygonRings (poly, ringPoly, flip) {
this.computeMinDistancePolygonLine(poly, ringPoly.getExteriorRing(), flip)
if (this._isDone) return null
const nHole = ringPoly.getNumInteriorRing()
for (let i = 0; i < nHole; i++) {
this.computeMinDistancePolygonLine(poly, ringPoly.getInteriorRingN(i), flip)
if (this._isDone) return null
}
}
updateDistance (dist, loc0, loc1, flip) {
this._minDistance = dist
const index = flip ? 1 : 0
this._minDistanceLocation[index] = loc0
this._minDistanceLocation[1 - index] = loc1
if (this._minDistance < this._terminateDistance) this._isDone = true
}
interfaces_ () {
return []
}
getClass () {
return Distance3DOp
}
static segmentPoint (p0, p1, d0, d1) {
if (d0 <= 0) return new Coordinate(p0)
if (d1 <= 0) return new Coordinate(p1)
const f = Math.abs(d0) / (Math.abs(d0) + Math.abs(d1))
const intx = p0.x + f * (p1.x - p0.x)
const inty = p0.y + f * (p1.y - p0.y)
const intz = p0.z + f * (p1.z - p0.z)
return new Coordinate(intx, inty, intz)
}
static nearestPoints (g0, g1) {
const distOp = new Distance3DOp(g0, g1)
return distOp.nearestPoints()
}
static polyPlane (poly) {
return new PlanarPolygon3D(poly)
}
static isWithinDistance (g0, g1, distance) {
const distOp = new Distance3DOp(g0, g1, distance)
return distOp.distance() <= distance
}
static distance (g0, g1) {
const distOp = new Distance3DOp(g0, g1)
return distOp.distance()
}
}