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
267 lines (264 loc) • 8.14 kB
JavaScript
import GeometryFactory from '../geom/GeometryFactory'
import Coordinate from '../geom/Coordinate'
import AffineTransformation from '../geom/util/AffineTransformation'
import Envelope from '../geom/Envelope'
export default class GeometricShapeFactory {
constructor () {
this._geomFact = null
this._precModel = null
this._dim = new Dimensions()
this._nPts = 100
this._rotationAngle = 0.0
if (arguments.length === 0) {
GeometricShapeFactory.call(this, new GeometryFactory())
} else if (arguments.length === 1) {
const geomFact = arguments[0]
this._geomFact = geomFact
this._precModel = geomFact.getPrecisionModel()
}
}
createSupercircle (power) {
const recipPow = 1.0 / power
const radius = this._dim.getMinSize() / 2
const centre = this._dim.getCentre()
const r4 = Math.pow(radius, power)
const y0 = radius
const xyInt = Math.pow(r4 / 2, recipPow)
const nSegsInOct = Math.trunc(this._nPts / 8)
const totPts = nSegsInOct * 8 + 1
const pts = new Array(totPts).fill(null)
const xInc = xyInt / nSegsInOct
for (let i = 0; i <= nSegsInOct; i++) {
let x = 0.0
let y = y0
if (i !== 0) {
x = xInc * i
const x4 = Math.pow(x, power)
y = Math.pow(r4 - x4, recipPow)
}
pts[i] = this.coordTrans(x, y, centre)
pts[2 * nSegsInOct - i] = this.coordTrans(y, x, centre)
pts[2 * nSegsInOct + i] = this.coordTrans(y, -x, centre)
pts[4 * nSegsInOct - i] = this.coordTrans(x, -y, centre)
pts[4 * nSegsInOct + i] = this.coordTrans(-x, -y, centre)
pts[6 * nSegsInOct - i] = this.coordTrans(-y, -x, centre)
pts[6 * nSegsInOct + i] = this.coordTrans(-y, x, centre)
pts[8 * nSegsInOct - i] = this.coordTrans(-x, y, centre)
}
pts[pts.length - 1] = new Coordinate(pts[0])
const ring = this._geomFact.createLinearRing(pts)
const poly = this._geomFact.createPolygon(ring, null)
return this.rotate(poly)
}
setNumPoints (nPts) {
this._nPts = nPts
}
setBase (base) {
this._dim.setBase(base)
}
setRotation (radians) {
this._rotationAngle = radians
}
setWidth (width) {
this._dim.setWidth(width)
}
createEllipse () {
const env = this._dim.getEnvelope()
const xRadius = env.getWidth() / 2.0
const yRadius = env.getHeight() / 2.0
const centreX = env.getMinX() + xRadius
const centreY = env.getMinY() + yRadius
const pts = new Array(this._nPts + 1).fill(null)
let iPt = 0
for (let i = 0; i < this._nPts; i++) {
const ang = i * (2 * Math.PI / this._nPts)
const x = xRadius * Math.cos(ang) + centreX
const y = yRadius * Math.sin(ang) + centreY
pts[iPt++] = this.coord(x, y)
}
pts[iPt] = new Coordinate(pts[0])
const ring = this._geomFact.createLinearRing(pts)
const poly = this._geomFact.createPolygon(ring, null)
return this.rotate(poly)
}
coordTrans (x, y, trans) {
return this.coord(x + trans.x, y + trans.y)
}
createSquircle () {
return this.createSupercircle(4)
}
setEnvelope (env) {
this._dim.setEnvelope(env)
}
setCentre (centre) {
this._dim.setCentre(centre)
}
createArc (startAng, angExtent) {
const env = this._dim.getEnvelope()
const xRadius = env.getWidth() / 2.0
const yRadius = env.getHeight() / 2.0
const centreX = env.getMinX() + xRadius
const centreY = env.getMinY() + yRadius
let angSize = angExtent
if (angSize <= 0.0 || angSize > 2 * Math.PI) angSize = 2 * Math.PI
const angInc = angSize / (this._nPts - 1)
const pts = new Array(this._nPts).fill(null)
let iPt = 0
for (let i = 0; i < this._nPts; i++) {
const ang = startAng + i * angInc
const x = xRadius * Math.cos(ang) + centreX
const y = yRadius * Math.sin(ang) + centreY
pts[iPt++] = this.coord(x, y)
}
const line = this._geomFact.createLineString(pts)
return this.rotate(line)
}
rotate (geom) {
if (this._rotationAngle !== 0.0) {
const trans = AffineTransformation.rotationInstance(this._rotationAngle, this._dim.getCentre().x, this._dim.getCentre().y)
geom.apply(trans)
}
return geom
}
coord (x, y) {
const pt = new Coordinate(x, y)
this._precModel.makePrecise(pt)
return pt
}
createArcPolygon (startAng, angExtent) {
const env = this._dim.getEnvelope()
const xRadius = env.getWidth() / 2.0
const yRadius = env.getHeight() / 2.0
const centreX = env.getMinX() + xRadius
const centreY = env.getMinY() + yRadius
let angSize = angExtent
if (angSize <= 0.0 || angSize > 2 * Math.PI) angSize = 2 * Math.PI
const angInc = angSize / (this._nPts - 1)
const pts = new Array(this._nPts + 2).fill(null)
let iPt = 0
pts[iPt++] = this.coord(centreX, centreY)
for (let i = 0; i < this._nPts; i++) {
const ang = startAng + angInc * i
const x = xRadius * Math.cos(ang) + centreX
const y = yRadius * Math.sin(ang) + centreY
pts[iPt++] = this.coord(x, y)
}
pts[iPt++] = this.coord(centreX, centreY)
const ring = this._geomFact.createLinearRing(pts)
const poly = this._geomFact.createPolygon(ring, null)
return this.rotate(poly)
}
createRectangle () {
let i = null
let ipt = 0
let nSide = Math.trunc(this._nPts / 4)
if (nSide < 1) nSide = 1
const XsegLen = this._dim.getEnvelope().getWidth() / nSide
const YsegLen = this._dim.getEnvelope().getHeight() / nSide
const pts = new Array(4 * nSide + 1).fill(null)
const env = this._dim.getEnvelope()
for ((i = 0); i < nSide; i++) {
const x = env.getMinX() + i * XsegLen
const y = env.getMinY()
pts[ipt++] = this.coord(x, y)
}
for ((i = 0); i < nSide; i++) {
const x = env.getMaxX()
const y = env.getMinY() + i * YsegLen
pts[ipt++] = this.coord(x, y)
}
for ((i = 0); i < nSide; i++) {
const x = env.getMaxX() - i * XsegLen
const y = env.getMaxY()
pts[ipt++] = this.coord(x, y)
}
for ((i = 0); i < nSide; i++) {
const x = env.getMinX()
const y = env.getMaxY() - i * YsegLen
pts[ipt++] = this.coord(x, y)
}
pts[ipt++] = new Coordinate(pts[0])
const ring = this._geomFact.createLinearRing(pts)
const poly = this._geomFact.createPolygon(ring, null)
return this.rotate(poly)
}
createCircle () {
return this.createEllipse()
}
setHeight (height) {
this._dim.setHeight(height)
}
setSize (size) {
this._dim.setSize(size)
}
interfaces_ () {
return []
}
getClass () {
return GeometricShapeFactory
}
static get Dimensions () { return Dimensions }
}
class Dimensions {
constructor () {
this.base = null
this.centre = null
this.width = null
this.height = null
}
setBase (base) {
this.base = base
}
setWidth (width) {
this.width = width
}
getBase () {
return this.base
}
getWidth () {
return this.width
}
setEnvelope (env) {
this.width = env.getWidth()
this.height = env.getHeight()
this.base = new Coordinate(env.getMinX(), env.getMinY())
this.centre = new Coordinate(env.centre())
}
setCentre (centre) {
this.centre = centre
}
getMinSize () {
return Math.min(this.width, this.height)
}
getEnvelope () {
if (this.base !== null) {
return new Envelope(this.base.x, this.base.x + this.width, this.base.y, this.base.y + this.height)
}
if (this.centre !== null) {
return new Envelope(this.centre.x - this.width / 2, this.centre.x + this.width / 2, this.centre.y - this.height / 2, this.centre.y + this.height / 2)
}
return new Envelope(0, this.width, 0, this.height)
}
getCentre () {
if (this.centre === null) {
this.centre = new Coordinate(this.base.x + this.width / 2, this.base.y + this.height / 2)
}
return this.centre
}
getHeight () {
return this.height
}
setHeight (height) {
this.height = height
}
setSize (size) {
this.height = size
this.width = size
}
interfaces_ () {
return []
}
getClass () {
return Dimensions
}
}