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
276 lines (253 loc) • 8.77 kB
JavaScript
import Area from '../algorithm/Area'
import Geometry from './Geometry'
import Arrays from '../../../../java/util/Arrays'
import CoordinateFilter from './CoordinateFilter'
import hasInterface from '../../../../hasInterface'
import IllegalArgumentException from '../../../../java/lang/IllegalArgumentException'
import Orientation from '../algorithm/Orientation'
import CoordinateSequences from './CoordinateSequences'
import GeometryComponentFilter from './GeometryComponentFilter'
import Polygonal from './Polygonal'
import GeometryFilter from './GeometryFilter'
import CoordinateSequenceFilter from './CoordinateSequenceFilter'
export default class Polygon extends Geometry {
constructor() {
super()
Polygon.constructor_.apply(this, arguments)
}
static constructor_() {
this._shell = null
this._holes = null
let shell = arguments[0], holes = arguments[1], factory = arguments[2]
Geometry.constructor_.call(this, factory)
if (shell === null)
shell = this.getFactory().createLinearRing()
if (holes === null)
holes = []
if (Geometry.hasNullElements(holes))
throw new IllegalArgumentException('holes must not contain null elements')
if (shell.isEmpty() && Geometry.hasNonEmptyElements(holes))
throw new IllegalArgumentException('shell is empty but holes are not')
this._shell = shell
this._holes = holes
}
computeEnvelopeInternal() {
return this._shell.getEnvelopeInternal()
}
getCoordinates() {
if (this.isEmpty())
return []
const coordinates = new Array(this.getNumPoints()).fill(null)
let k = -1
const shellCoordinates = this._shell.getCoordinates()
for (let x = 0; x < shellCoordinates.length; x++) {
k++
coordinates[k] = shellCoordinates[x]
}
for (let i = 0; i < this._holes.length; i++) {
const childCoordinates = this._holes[i].getCoordinates()
for (let j = 0; j < childCoordinates.length; j++) {
k++
coordinates[k] = childCoordinates[j]
}
}
return coordinates
}
getArea() {
let area = 0.0
area += Area.ofRing(this._shell.getCoordinateSequence())
for (let i = 0; i < this._holes.length; i++)
area -= Area.ofRing(this._holes[i].getCoordinateSequence())
return area
}
copyInternal() {
const shellCopy = this._shell.copy()
const holeCopies = new Array(this._holes.length).fill(null)
for (let i = 0; i < this._holes.length; i++)
holeCopies[i] = this._holes[i].copy()
return new Polygon(shellCopy, holeCopies, this._factory)
}
isRectangle() {
if (this.getNumInteriorRing() !== 0) return false
if (this._shell === null) return false
if (this._shell.getNumPoints() !== 5) return false
const seq = this._shell.getCoordinateSequence()
const env = this.getEnvelopeInternal()
for (let i = 0; i < 5; i++) {
const x = seq.getX(i)
if (!(x === env.getMinX() || x === env.getMaxX())) return false
const y = seq.getY(i)
if (!(y === env.getMinY() || y === env.getMaxY())) return false
}
let prevX = seq.getX(0)
let prevY = seq.getY(0)
for (let i = 1; i <= 4; i++) {
const x = seq.getX(i)
const y = seq.getY(i)
const xChanged = x !== prevX
const yChanged = y !== prevY
if (xChanged === yChanged) return false
prevX = x
prevY = y
}
return true
}
equalsExact() {
if (arguments.length === 2 && (typeof arguments[1] === 'number' && arguments[0] instanceof Geometry)) {
const other = arguments[0], tolerance = arguments[1]
if (!this.isEquivalentClass(other))
return false
const otherPolygon = other
const thisShell = this._shell
const otherPolygonShell = otherPolygon._shell
if (!thisShell.equalsExact(otherPolygonShell, tolerance))
return false
if (this._holes.length !== otherPolygon._holes.length)
return false
for (let i = 0; i < this._holes.length; i++)
if (!this._holes[i].equalsExact(otherPolygon._holes[i], tolerance))
return false
return true
} else {
return super.equalsExact.apply(this, arguments)
}
}
normalize() {
if (arguments.length === 0) {
this._shell = this.normalized(this._shell, true)
for (let i = 0; i < this._holes.length; i++)
this._holes[i] = this.normalized(this._holes[i], false)
Arrays.sort(this._holes)
} else if (arguments.length === 2) {
const ring = arguments[0], clockwise = arguments[1]
if (ring.isEmpty())
return null
const seq = ring.getCoordinateSequence()
const minCoordinateIndex = CoordinateSequences.minCoordinateIndex(seq, 0, seq.size() - 2)
CoordinateSequences.scroll(seq, minCoordinateIndex, true)
if (Orientation.isCCW(seq) === clockwise) CoordinateSequences.reverse(seq)
}
}
getCoordinate() {
return this._shell.getCoordinate()
}
getNumInteriorRing() {
return this._holes.length
}
getBoundaryDimension() {
return 1
}
reverseInternal() {
const shell = this.getExteriorRing().reverse()
const holes = new Array(this.getNumInteriorRing()).fill(null)
for (let i = 0; i < holes.length; i++)
holes[i] = this.getInteriorRingN(i).reverse()
return this.getFactory().createPolygon(shell, holes)
}
getTypeCode() {
return Geometry.TYPECODE_POLYGON
}
getDimension() {
return 2
}
getLength() {
let len = 0.0
len += this._shell.getLength()
for (let i = 0; i < this._holes.length; i++)
len += this._holes[i].getLength()
return len
}
getNumPoints() {
let numPoints = this._shell.getNumPoints()
for (let i = 0; i < this._holes.length; i++)
numPoints += this._holes[i].getNumPoints()
return numPoints
}
convexHull() {
return this.getExteriorRing().convexHull()
}
normalized(ring, clockwise) {
const res = ring.copy()
this.normalize(res, clockwise)
return res
}
compareToSameClass() {
if (arguments.length === 1) {
const o = arguments[0]
const thisShell = this._shell
const otherShell = o._shell
return thisShell.compareToSameClass(otherShell)
} else if (arguments.length === 2) {
const o = arguments[0], comp = arguments[1]
const poly = o
const thisShell = this._shell
const otherShell = poly._shell
const shellComp = thisShell.compareToSameClass(otherShell, comp)
if (shellComp !== 0) return shellComp
const nHole1 = this.getNumInteriorRing()
const nHole2 = poly.getNumInteriorRing()
let i = 0
while (i < nHole1 && i < nHole2) {
const thisHole = this.getInteriorRingN(i)
const otherHole = poly.getInteriorRingN(i)
const holeComp = thisHole.compareToSameClass(otherHole, comp)
if (holeComp !== 0) return holeComp
i++
}
if (i < nHole1) return 1
if (i < nHole2) return -1
return 0
}
}
apply() {
if (hasInterface(arguments[0], CoordinateFilter)) {
const filter = arguments[0]
this._shell.apply(filter)
for (let i = 0; i < this._holes.length; i++)
this._holes[i].apply(filter)
} else if (hasInterface(arguments[0], CoordinateSequenceFilter)) {
const filter = arguments[0]
this._shell.apply(filter)
if (!filter.isDone())
for (let i = 0; i < this._holes.length; i++) {
this._holes[i].apply(filter)
if (filter.isDone()) break
}
if (filter.isGeometryChanged()) this.geometryChanged()
} else if (hasInterface(arguments[0], GeometryFilter)) {
const filter = arguments[0]
filter.filter(this)
} else if (hasInterface(arguments[0], GeometryComponentFilter)) {
const filter = arguments[0]
filter.filter(this)
this._shell.apply(filter)
for (let i = 0; i < this._holes.length; i++)
this._holes[i].apply(filter)
}
}
getBoundary() {
if (this.isEmpty())
return this.getFactory().createMultiLineString()
const rings = new Array(this._holes.length + 1).fill(null)
rings[0] = this._shell
for (let i = 0; i < this._holes.length; i++)
rings[i + 1] = this._holes[i]
if (rings.length <= 1) return this.getFactory().createLinearRing(rings[0].getCoordinateSequence())
return this.getFactory().createMultiLineString(rings)
}
getGeometryType() {
return Geometry.TYPENAME_POLYGON
}
getExteriorRing() {
return this._shell
}
isEmpty() {
return this._shell.isEmpty()
}
getInteriorRingN(n) {
return this._holes[n]
}
get interfaces_() {
return [Polygonal]
}
}