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
128 lines (126 loc) • 4.07 kB
JavaScript
import LineString from '../geom/LineString'
import CGAlgorithms from './CGAlgorithms'
import Geometry from '../geom/Geometry'
import Coordinate from '../geom/Coordinate'
import Point from '../geom/Point'
import Polygon from '../geom/Polygon'
import GeometryCollection from '../geom/GeometryCollection'
export default class Centroid {
constructor () {
this._areaBasePt = null
this._triangleCent3 = new Coordinate()
this._areasum2 = 0
this._cg3 = new Coordinate()
this._lineCentSum = new Coordinate()
this._totalLength = 0.0
this._ptCount = 0
this._ptCentSum = new Coordinate()
const geom = arguments[0]
this._areaBasePt = null
this.add(geom)
}
addPoint (pt) {
this._ptCount += 1
this._ptCentSum.x += pt.x
this._ptCentSum.y += pt.y
}
setBasePoint (basePt) {
if (this._areaBasePt === null) this._areaBasePt = basePt
}
addLineSegments (pts) {
let lineLen = 0.0
for (let i = 0; i < pts.length - 1; i++) {
const segmentLen = pts[i].distance(pts[i + 1])
if (segmentLen === 0.0) continue
lineLen += segmentLen
const midx = (pts[i].x + pts[i + 1].x) / 2
this._lineCentSum.x += segmentLen * midx
const midy = (pts[i].y + pts[i + 1].y) / 2
this._lineCentSum.y += segmentLen * midy
}
this._totalLength += lineLen
if (lineLen === 0.0 && pts.length > 0) this.addPoint(pts[0])
}
addHole (pts) {
const isPositiveArea = CGAlgorithms.isCCW(pts)
for (let i = 0; i < pts.length - 1; i++) {
this.addTriangle(this._areaBasePt, pts[i], pts[i + 1], isPositiveArea)
}
this.addLineSegments(pts)
}
getCentroid () {
const cent = new Coordinate()
if (Math.abs(this._areasum2) > 0.0) {
cent.x = this._cg3.x / 3 / this._areasum2
cent.y = this._cg3.y / 3 / this._areasum2
} else if (this._totalLength > 0.0) {
cent.x = this._lineCentSum.x / this._totalLength
cent.y = this._lineCentSum.y / this._totalLength
} else if (this._ptCount > 0) {
cent.x = this._ptCentSum.x / this._ptCount
cent.y = this._ptCentSum.y / this._ptCount
} else {
return null
}
return cent
}
addShell (pts) {
if (pts.length > 0) this.setBasePoint(pts[0])
const isPositiveArea = !CGAlgorithms.isCCW(pts)
for (let i = 0; i < pts.length - 1; i++) {
this.addTriangle(this._areaBasePt, pts[i], pts[i + 1], isPositiveArea)
}
this.addLineSegments(pts)
}
addTriangle (p0, p1, p2, isPositiveArea) {
const sign = isPositiveArea ? 1.0 : -1.0
Centroid.centroid3(p0, p1, p2, this._triangleCent3)
const area2 = Centroid.area2(p0, p1, p2)
this._cg3.x += sign * area2 * this._triangleCent3.x
this._cg3.y += sign * area2 * this._triangleCent3.y
this._areasum2 += sign * area2
}
add () {
if (arguments[0] instanceof Polygon) {
let poly = arguments[0]
this.addShell(poly.getExteriorRing().getCoordinates())
for (let i = 0; i < poly.getNumInteriorRing(); i++) {
this.addHole(poly.getInteriorRingN(i).getCoordinates())
}
} else if (arguments[0] instanceof Geometry) {
let geom = arguments[0]
if (geom.isEmpty()) return null
if (geom instanceof Point) {
this.addPoint(geom.getCoordinate())
} else if (geom instanceof LineString) {
this.addLineSegments(geom.getCoordinates())
} else if (geom instanceof Polygon) {
const poly = geom
this.add(poly)
} else if (geom instanceof GeometryCollection) {
const gc = geom
for (let i = 0; i < gc.getNumGeometries(); i++) {
this.add(gc.getGeometryN(i))
}
}
}
}
interfaces_ () {
return []
}
getClass () {
return Centroid
}
static area2 (p1, p2, p3) {
return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y)
}
static centroid3 (p1, p2, p3, c) {
c.x = p1.x + p2.x + p3.x
c.y = p1.y + p2.y + p3.y
return null
}
static getCentroid (geom) {
const cent = new Centroid(geom)
return cent.getCentroid()
}
}