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
191 lines (183 loc) • 5.74 kB
JavaScript
import CoordinateList from '../../geom/CoordinateList'
import hasInterface from '../../../../../hasInterface'
import ArrayList from '../../../../../java/util/ArrayList'
import KdNodeVisitor from './KdNodeVisitor'
import Envelope from '../../geom/Envelope'
import List from '../../../../../java/util/List'
import KdNode from './KdNode'
export default class KdTree {
constructor() {
KdTree.constructor_.apply(this, arguments)
}
static constructor_() {
this._root = null
this._numberOfNodes = null
this._tolerance = null
if (arguments.length === 0) {
KdTree.constructor_.call(this, 0.0)
} else if (arguments.length === 1) {
const tolerance = arguments[0]
this._tolerance = tolerance
}
}
static toCoordinates() {
if (arguments.length === 1) {
const kdnodes = arguments[0]
return KdTree.toCoordinates(kdnodes, false)
} else if (arguments.length === 2) {
const kdnodes = arguments[0], includeRepeated = arguments[1]
const coord = new CoordinateList()
for (let it = kdnodes.iterator(); it.hasNext(); ) {
const node = it.next()
const count = includeRepeated ? node.getCount() : 1
for (let i = 0; i < count; i++)
coord.add(node.getCoordinate(), true)
}
return coord.toCoordinateArray()
}
}
insert() {
if (arguments.length === 1) {
const p = arguments[0]
return this.insert(p, null)
} else if (arguments.length === 2) {
const p = arguments[0], data = arguments[1]
if (this._root === null) {
this._root = new KdNode(p, data)
return this._root
}
if (this._tolerance > 0) {
const matchNode = this.findBestMatchNode(p)
if (matchNode !== null) {
matchNode.increment()
return matchNode
}
}
return this.insertExact(p, data)
}
}
query() {
if (arguments.length === 1) {
const queryEnv = arguments[0]
const result = new ArrayList()
this.query(queryEnv, result)
return result
} else if (arguments.length === 2) {
if (arguments[0] instanceof Envelope && hasInterface(arguments[1], List)) {
const queryEnv = arguments[0], result = arguments[1]
this.queryNode(this._root, queryEnv, true, new (class {
get interfaces_() {
return [KdNodeVisitor]
}
visit(node) {
result.add(node)
}
})())
} else if (arguments[0] instanceof Envelope && hasInterface(arguments[1], KdNodeVisitor)) {
const queryEnv = arguments[0], visitor = arguments[1]
this.queryNode(this._root, queryEnv, true, visitor)
}
}
}
queryNode(currentNode, queryEnv, odd, visitor) {
if (currentNode === null) return null
let min = null
let max = null
let discriminant = null
if (odd) {
min = queryEnv.getMinX()
max = queryEnv.getMaxX()
discriminant = currentNode.getX()
} else {
min = queryEnv.getMinY()
max = queryEnv.getMaxY()
discriminant = currentNode.getY()
}
const searchLeft = min < discriminant
const searchRight = discriminant <= max
if (searchLeft)
this.queryNode(currentNode.getLeft(), queryEnv, !odd, visitor)
if (queryEnv.contains(currentNode.getCoordinate()))
visitor.visit(currentNode)
if (searchRight)
this.queryNode(currentNode.getRight(), queryEnv, !odd, visitor)
}
findBestMatchNode(p) {
const visitor = new BestMatchVisitor(p, this._tolerance)
this.query(visitor.queryEnvelope(), visitor)
return visitor.getNode()
}
isEmpty() {
if (this._root === null) return true
return false
}
insertExact(p, data) {
let currentNode = this._root
let leafNode = this._root
let isOddLevel = true
let isLessThan = true
while (currentNode !== null) {
if (currentNode !== null) {
const isInTolerance = p.distance(currentNode.getCoordinate()) <= this._tolerance
if (isInTolerance) {
currentNode.increment()
return currentNode
}
}
if (isOddLevel)
isLessThan = p.x < currentNode.getX()
else
isLessThan = p.y < currentNode.getY()
leafNode = currentNode
if (isLessThan)
currentNode = currentNode.getLeft()
else
currentNode = currentNode.getRight()
isOddLevel = !isOddLevel
}
this._numberOfNodes = this._numberOfNodes + 1
const node = new KdNode(p, data)
if (isLessThan)
leafNode.setLeft(node)
else
leafNode.setRight(node)
return node
}
}
class BestMatchVisitor {
constructor() {
BestMatchVisitor.constructor_.apply(this, arguments)
}
static constructor_() {
this._tolerance = null
this._matchNode = null
this._matchDist = 0.0
this._p = null
const p = arguments[0], tolerance = arguments[1]
this._p = p
this._tolerance = tolerance
}
visit(node) {
const dist = this._p.distance(node.getCoordinate())
const isInTolerance = dist <= this._tolerance
if (!isInTolerance) return null
let update = false
if (this._matchNode === null || dist < this._matchDist || this._matchNode !== null && dist === this._matchDist && node.getCoordinate().compareTo(this._matchNode.getCoordinate()) < 1) update = true
if (update) {
this._matchNode = node
this._matchDist = dist
}
}
queryEnvelope() {
const queryEnv = new Envelope(this._p)
queryEnv.expandBy(this._tolerance)
return queryEnv
}
getNode() {
return this._matchNode
}
get interfaces_() {
return [KdNodeVisitor]
}
}
KdTree.BestMatchVisitor = BestMatchVisitor