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
202 lines (199 loc) • 5.88 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 () {
this._root = null
this._numberOfNodes = null
this._tolerance = null
if (arguments.length === 0) {
KdTree.call(this, 0.0)
} else if (arguments.length === 1) {
const tolerance = arguments[0]
this._tolerance = tolerance
}
}
insert () {
if (arguments.length === 1) {
const p = arguments[0]
return this.insert(p, null)
} else if (arguments.length === 2) {
const p = arguments[0]
const 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]
const result = arguments[1]
this.queryNoe(this._root, queryEnv, true, {
interfaces_: function () {
return [KdNodeVisitor]
},
visit: function (node) {
result.add(node)
}
})
} else if (arguments[0] instanceof Envelope && hasInterface(arguments[1], KdNodeVisitor)) {
const queryEnv = arguments[0]
const 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
}
interfaces_ () {
return []
}
getClass () {
return KdTree
}
static toCoordinates () {
if (arguments.length === 1) {
const kdnodes = arguments[0]
return KdTree.toCoordinates(kdnodes, false)
} else if (arguments.length === 2) {
const kdnodes = arguments[0]
const includeRepeated = arguments[1]
const coord = new CoordinateList()
for (const 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()
}
}
static get BestMatchVisitor () { return BestMatchVisitor }
}
class BestMatchVisitor {
constructor () {
this._tolerance = null
this._matchNode = null
this._matchDist = 0.0
this._p = null
const p = arguments[0]
const tolerance = arguments[1]
this._p = p
this._tolerance = tolerance
}
// visit removed since it is unstable for Rollup build
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
}
interfaces_ () {
return [KdNodeVisitor]
}
getClass () {
return BestMatchVisitor
}
}