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
239 lines (236 loc) • 9.39 kB
JavaScript
import PointLocator from '../algorithm/PointLocator'
import Location from '../geom/Location'
import LineString from '../geom/LineString'
import HashMap from '../../../../java/util/HashMap'
import Geometry from '../geom/Geometry'
import hasInterface from '../../../../hasInterface'
import Position from './Position'
import Coordinate from '../geom/Coordinate'
import Point from '../geom/Point'
import Polygon from '../geom/Polygon'
import MultiPoint from '../geom/MultiPoint'
import SimpleMCSweepLineIntersector from './index/SimpleMCSweepLineIntersector'
import LinearRing from '../geom/LinearRing'
import BoundaryNodeRule from '../algorithm/BoundaryNodeRule'
import Orientation from '../algorithm/Orientation'
import SegmentIntersector from './index/SegmentIntersector'
import MultiPolygon from '../geom/MultiPolygon'
import Label from './Label'
import GeometryCollection from '../geom/GeometryCollection'
import UnsupportedOperationException from '../../../../java/lang/UnsupportedOperationException'
import CoordinateArrays from '../geom/CoordinateArrays'
import Polygonal from '../geom/Polygonal'
import IndexedPointInAreaLocator from '../algorithm/locate/IndexedPointInAreaLocator'
import Assert from '../util/Assert'
import Edge from './Edge'
import MultiLineString from '../geom/MultiLineString'
import PlanarGraph from './PlanarGraph'
export default class GeometryGraph extends PlanarGraph {
constructor() {
super()
GeometryGraph.constructor_.apply(this, arguments)
}
static constructor_() {
this._parentGeom = null
this._lineEdgeMap = new HashMap()
this._boundaryNodeRule = null
this._useBoundaryDeterminationRule = true
this._argIndex = null
this._boundaryNodes = null
this._hasTooFewPoints = false
this._invalidPoint = null
this._areaPtLocator = null
this._ptLocator = new PointLocator()
if (arguments.length === 2) {
const argIndex = arguments[0], parentGeom = arguments[1]
GeometryGraph.constructor_.call(this, argIndex, parentGeom, BoundaryNodeRule.OGC_SFS_BOUNDARY_RULE)
} else if (arguments.length === 3) {
const argIndex = arguments[0], parentGeom = arguments[1], boundaryNodeRule = arguments[2]
this._argIndex = argIndex
this._parentGeom = parentGeom
this._boundaryNodeRule = boundaryNodeRule
if (parentGeom !== null)
this.add(parentGeom)
}
}
static determineBoundary(boundaryNodeRule, boundaryCount) {
return boundaryNodeRule.isInBoundary(boundaryCount) ? Location.BOUNDARY : Location.INTERIOR
}
insertBoundaryPoint(argIndex, coord) {
const n = this._nodes.addNode(coord)
const lbl = n.getLabel()
let boundaryCount = 1
let loc = Location.NONE
loc = lbl.getLocation(argIndex, Position.ON)
if (loc === Location.BOUNDARY) boundaryCount++
const newLoc = GeometryGraph.determineBoundary(this._boundaryNodeRule, boundaryCount)
lbl.setLocation(argIndex, newLoc)
}
computeSelfNodes() {
if (arguments.length === 2) {
const li = arguments[0], computeRingSelfNodes = arguments[1]
return this.computeSelfNodes(li, computeRingSelfNodes, false)
} else if (arguments.length === 3) {
const li = arguments[0], computeRingSelfNodes = arguments[1], isDoneIfProperInt = arguments[2]
const si = new SegmentIntersector(li, true, false)
si.setIsDoneIfProperInt(isDoneIfProperInt)
const esi = this.createEdgeSetIntersector()
const isRings = this._parentGeom instanceof LinearRing || this._parentGeom instanceof Polygon || this._parentGeom instanceof MultiPolygon
const computeAllSegments = computeRingSelfNodes || !isRings
esi.computeIntersections(this._edges, si, computeAllSegments)
this.addSelfIntersectionNodes(this._argIndex)
return si
}
}
computeSplitEdges(edgelist) {
for (let i = this._edges.iterator(); i.hasNext(); ) {
const e = i.next()
e.eiList.addSplitEdges(edgelist)
}
}
computeEdgeIntersections(g, li, includeProper) {
const si = new SegmentIntersector(li, includeProper, true)
si.setBoundaryNodes(this.getBoundaryNodes(), g.getBoundaryNodes())
const esi = this.createEdgeSetIntersector()
esi.computeIntersections(this._edges, g._edges, si)
return si
}
getGeometry() {
return this._parentGeom
}
getBoundaryNodeRule() {
return this._boundaryNodeRule
}
hasTooFewPoints() {
return this._hasTooFewPoints
}
addPoint() {
if (arguments[0] instanceof Point) {
const p = arguments[0]
const coord = p.getCoordinate()
this.insertPoint(this._argIndex, coord, Location.INTERIOR)
} else if (arguments[0] instanceof Coordinate) {
const pt = arguments[0]
this.insertPoint(this._argIndex, pt, Location.INTERIOR)
}
}
addPolygon(p) {
this.addPolygonRing(p.getExteriorRing(), Location.EXTERIOR, Location.INTERIOR)
for (let i = 0; i < p.getNumInteriorRing(); i++) {
const hole = p.getInteriorRingN(i)
this.addPolygonRing(hole, Location.INTERIOR, Location.EXTERIOR)
}
}
addEdge(e) {
this.insertEdge(e)
const coord = e.getCoordinates()
this.insertPoint(this._argIndex, coord[0], Location.BOUNDARY)
this.insertPoint(this._argIndex, coord[coord.length - 1], Location.BOUNDARY)
}
addLineString(line) {
const coord = CoordinateArrays.removeRepeatedPoints(line.getCoordinates())
if (coord.length < 2) {
this._hasTooFewPoints = true
this._invalidPoint = coord[0]
return null
}
const e = new Edge(coord, new Label(this._argIndex, Location.INTERIOR))
this._lineEdgeMap.put(line, e)
this.insertEdge(e)
Assert.isTrue(coord.length >= 2, 'found LineString with single point')
this.insertBoundaryPoint(this._argIndex, coord[0])
this.insertBoundaryPoint(this._argIndex, coord[coord.length - 1])
}
getInvalidPoint() {
return this._invalidPoint
}
getBoundaryPoints() {
const coll = this.getBoundaryNodes()
const pts = new Array(coll.size()).fill(null)
let i = 0
for (let it = coll.iterator(); it.hasNext(); ) {
const node = it.next()
pts[i++] = node.getCoordinate().copy()
}
return pts
}
getBoundaryNodes() {
if (this._boundaryNodes === null) this._boundaryNodes = this._nodes.getBoundaryNodes(this._argIndex)
return this._boundaryNodes
}
addSelfIntersectionNode(argIndex, coord, loc) {
if (this.isBoundaryNode(argIndex, coord)) return null
if (loc === Location.BOUNDARY && this._useBoundaryDeterminationRule) this.insertBoundaryPoint(argIndex, coord); else this.insertPoint(argIndex, coord, loc)
}
addPolygonRing(lr, cwLeft, cwRight) {
if (lr.isEmpty()) return null
const coord = CoordinateArrays.removeRepeatedPoints(lr.getCoordinates())
if (coord.length < 4) {
this._hasTooFewPoints = true
this._invalidPoint = coord[0]
return null
}
let left = cwLeft
let right = cwRight
if (Orientation.isCCW(coord)) {
left = cwRight
right = cwLeft
}
const e = new Edge(coord, new Label(this._argIndex, Location.BOUNDARY, left, right))
this._lineEdgeMap.put(lr, e)
this.insertEdge(e)
this.insertPoint(this._argIndex, coord[0], Location.BOUNDARY)
}
insertPoint(argIndex, coord, onLocation) {
const n = this._nodes.addNode(coord)
const lbl = n.getLabel()
if (lbl === null)
n._label = new Label(argIndex, onLocation)
else lbl.setLocation(argIndex, onLocation)
}
createEdgeSetIntersector() {
return new SimpleMCSweepLineIntersector()
}
addSelfIntersectionNodes(argIndex) {
for (let i = this._edges.iterator(); i.hasNext(); ) {
const e = i.next()
const eLoc = e.getLabel().getLocation(argIndex)
for (let eiIt = e.eiList.iterator(); eiIt.hasNext(); ) {
const ei = eiIt.next()
this.addSelfIntersectionNode(argIndex, ei.coord, eLoc)
}
}
}
add() {
if (arguments.length === 1 && arguments[0] instanceof Geometry) {
const g = arguments[0]
if (g.isEmpty()) return null
if (g instanceof MultiPolygon) this._useBoundaryDeterminationRule = false
if (g instanceof Polygon) this.addPolygon(g); else if (g instanceof LineString) this.addLineString(g); else if (g instanceof Point) this.addPoint(g); else if (g instanceof MultiPoint) this.addCollection(g); else if (g instanceof MultiLineString) this.addCollection(g); else if (g instanceof MultiPolygon) this.addCollection(g); else if (g instanceof GeometryCollection) this.addCollection(g); else throw new UnsupportedOperationException(g.getGeometryType())
} else {
return super.add.apply(this, arguments)
}
}
addCollection(gc) {
for (let i = 0; i < gc.getNumGeometries(); i++) {
const g = gc.getGeometryN(i)
this.add(g)
}
}
locate(pt) {
if (hasInterface(this._parentGeom, Polygonal) && this._parentGeom.getNumGeometries() > 50) {
if (this._areaPtLocator === null)
this._areaPtLocator = new IndexedPointInAreaLocator(this._parentGeom)
return this._areaPtLocator.locate(pt)
}
return this._ptLocator.locate(pt, this._parentGeom)
}
findEdge() {
if (arguments.length === 1 && arguments[0] instanceof LineString) {
const line = arguments[0]
return this._lineEdgeMap.get(line)
} else {
return super.findEdge.apply(this, arguments)
}
}
}