UNPKG

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

325 lines (323 loc) 12.4 kB
import TreeSet from '../../../../../java/util/TreeSet' import LineString from '../../geom/LineString' import CGAlgorithms from '../../algorithm/CGAlgorithms' import Geometry from '../../geom/Geometry' import ConnectedInteriorTester from './ConnectedInteriorTester' import Coordinate from '../../geom/Coordinate' import Point from '../../geom/Point' import Polygon from '../../geom/Polygon' import MultiPoint from '../../geom/MultiPoint' import LinearRing from '../../geom/LinearRing' import Double from '../../../../../java/lang/Double' import MCPointInRing from '../../algorithm/MCPointInRing' import GeometryGraph from '../../geomgraph/GeometryGraph' import MultiPolygon from '../../geom/MultiPolygon' import ConsistentAreaTester from './ConsistentAreaTester' import GeometryCollection from '../../geom/GeometryCollection' import IndexedNestedRingTester from './IndexedNestedRingTester' import RobustLineIntersector from '../../algorithm/RobustLineIntersector' import TopologyValidationError from './TopologyValidationError' import Assert from '../../util/Assert' export default class IsValidOp { constructor () { this._parentGeometry = null this._isSelfTouchingRingFormingHoleValid = false this._validErr = null let parentGeometry = arguments[0] this._parentGeometry = parentGeometry } checkInvalidCoordinates () { if (arguments[0] instanceof Array) { let coords = arguments[0] for (let i = 0; i < coords.length; i++) { if (!IsValidOp.isValid(coords[i])) { this._validErr = new TopologyValidationError(TopologyValidationError.INVALID_COORDINATE, coords[i]) return null } } } else if (arguments[0] instanceof Polygon) { let poly = arguments[0] this.checkInvalidCoordinates(poly.getExteriorRing().getCoordinates()) if (this._validErr !== null) return null for (let i = 0; i < poly.getNumInteriorRing(); i++) { this.checkInvalidCoordinates(poly.getInteriorRingN(i).getCoordinates()) if (this._validErr !== null) return null } } } checkHolesNotNested (p, graph) { const nestedTester = new IndexedNestedRingTester(graph) for (let i = 0; i < p.getNumInteriorRing(); i++) { const innerHole = p.getInteriorRingN(i) nestedTester.add(innerHole) } const isNonNested = nestedTester.isNonNested() if (!isNonNested) { this._validErr = new TopologyValidationError(TopologyValidationError.NESTED_HOLES, nestedTester.getNestedPoint()) } } checkConsistentArea (graph) { const cat = new ConsistentAreaTester(graph) const isValidArea = cat.isNodeConsistentArea() if (!isValidArea) { this._validErr = new TopologyValidationError(TopologyValidationError.SELF_INTERSECTION, cat.getInvalidPoint()) return null } if (cat.hasDuplicateRings()) { this._validErr = new TopologyValidationError(TopologyValidationError.DUPLICATE_RINGS, cat.getInvalidPoint()) } } isValid () { this.checkValid(this._parentGeometry) return this._validErr === null } checkShellInsideHole (shell, hole, graph) { const shellPts = shell.getCoordinates() const holePts = hole.getCoordinates() const shellPt = IsValidOp.findPtNotNode(shellPts, hole, graph) if (shellPt !== null) { const insideHole = CGAlgorithms.isPointInRing(shellPt, holePts) if (!insideHole) { return shellPt } } const holePt = IsValidOp.findPtNotNode(holePts, shell, graph) if (holePt !== null) { const insideShell = CGAlgorithms.isPointInRing(holePt, shellPts) if (insideShell) { return holePt } return null } Assert.shouldNeverReachHere('points in shell and hole appear to be equal') return null } checkNoSelfIntersectingRings (graph) { for (let i = graph.getEdgeIterator(); i.hasNext();) { const e = i.next() this.checkNoSelfIntersectingRing(e.getEdgeIntersectionList()) if (this._validErr !== null) return null } } checkConnectedInteriors (graph) { const cit = new ConnectedInteriorTester(graph) if (!cit.isInteriorsConnected()) this._validErr = new TopologyValidationError(TopologyValidationError.DISCONNECTED_INTERIOR, cit.getCoordinate()) } checkNoSelfIntersectingRing (eiList) { const nodeSet = new TreeSet() let isFirst = true for (let i = eiList.iterator(); i.hasNext();) { const ei = i.next() if (isFirst) { isFirst = false continue } if (nodeSet.contains(ei.coord)) { this._validErr = new TopologyValidationError(TopologyValidationError.RING_SELF_INTERSECTION, ei.coord) return null } else { nodeSet.add(ei.coord) } } } checkHolesInShell (p, graph) { const shell = p.getExteriorRing() const pir = new MCPointInRing(shell) for (let i = 0; i < p.getNumInteriorRing(); i++) { const hole = p.getInteriorRingN(i) const holePt = IsValidOp.findPtNotNode(hole.getCoordinates(), shell, graph) if (holePt === null) return null const outside = !pir.isInside(holePt) if (outside) { this._validErr = new TopologyValidationError(TopologyValidationError.HOLE_OUTSIDE_SHELL, holePt) return null } } } checkTooFewPoints (graph) { if (graph.hasTooFewPoints()) { this._validErr = new TopologyValidationError(TopologyValidationError.TOO_FEW_POINTS, graph.getInvalidPoint()) return null } } getValidationError () { this.checkValid(this._parentGeometry) return this._validErr } checkValid () { if (arguments[0] instanceof Point) { let g = arguments[0] this.checkInvalidCoordinates(g.getCoordinates()) } else if (arguments[0] instanceof MultiPoint) { let g = arguments[0] this.checkInvalidCoordinates(g.getCoordinates()) } else if (arguments[0] instanceof LinearRing) { let g = arguments[0] this.checkInvalidCoordinates(g.getCoordinates()) if (this._validErr !== null) return null this.checkClosedRing(g) if (this._validErr !== null) return null const graph = new GeometryGraph(0, g) this.checkTooFewPoints(graph) if (this._validErr !== null) return null const li = new RobustLineIntersector() graph.computeSelfNodes(li, true, true) this.checkNoSelfIntersectingRings(graph) } else if (arguments[0] instanceof LineString) { let g = arguments[0] this.checkInvalidCoordinates(g.getCoordinates()) if (this._validErr !== null) return null const graph = new GeometryGraph(0, g) this.checkTooFewPoints(graph) } else if (arguments[0] instanceof Polygon) { let g = arguments[0] this.checkInvalidCoordinates(g) if (this._validErr !== null) return null this.checkClosedRings(g) if (this._validErr !== null) return null const graph = new GeometryGraph(0, g) this.checkTooFewPoints(graph) if (this._validErr !== null) return null this.checkConsistentArea(graph) if (this._validErr !== null) return null if (!this._isSelfTouchingRingFormingHoleValid) { this.checkNoSelfIntersectingRings(graph) if (this._validErr !== null) return null } this.checkHolesInShell(g, graph) if (this._validErr !== null) return null this.checkHolesNotNested(g, graph) if (this._validErr !== null) return null this.checkConnectedInteriors(graph) } else if (arguments[0] instanceof MultiPolygon) { let g = arguments[0] for (let i = 0; i < g.getNumGeometries(); i++) { const p = g.getGeometryN(i) this.checkInvalidCoordinates(p) if (this._validErr !== null) return null this.checkClosedRings(p) if (this._validErr !== null) return null } const graph = new GeometryGraph(0, g) this.checkTooFewPoints(graph) if (this._validErr !== null) return null this.checkConsistentArea(graph) if (this._validErr !== null) return null if (!this._isSelfTouchingRingFormingHoleValid) { this.checkNoSelfIntersectingRings(graph) if (this._validErr !== null) return null } for (let i = 0; i < g.getNumGeometries(); i++) { const p = g.getGeometryN(i) this.checkHolesInShell(p, graph) if (this._validErr !== null) return null } for (let i = 0; i < g.getNumGeometries(); i++) { const p = g.getGeometryN(i) this.checkHolesNotNested(p, graph) if (this._validErr !== null) return null } this.checkShellsNotNested(g, graph) if (this._validErr !== null) return null this.checkConnectedInteriors(graph) } else if (arguments[0] instanceof GeometryCollection) { let gc = arguments[0] for (let i = 0; i < gc.getNumGeometries(); i++) { const g = gc.getGeometryN(i) this.checkValid(g) if (this._validErr !== null) return null } } else if (arguments[0] instanceof Geometry) { let g = arguments[0] this._validErr = null if (g.isEmpty()) return null if (g instanceof Point) this.checkValid(g) else if (g instanceof MultiPoint) this.checkValid(g) else if (g instanceof LinearRing) this.checkValid(g) else if (g instanceof LineString) this.checkValid(g) else if (g instanceof Polygon) this.checkValid(g) else if (g instanceof MultiPolygon) this.checkValid(g) else if (g instanceof GeometryCollection) this.checkValid(g) else throw new Error(g.getClass().getName()) } } setSelfTouchingRingFormingHoleValid (isValid) { this._isSelfTouchingRingFormingHoleValid = isValid } checkShellNotNested (shell, p, graph) { const shellPts = shell.getCoordinates() const polyShell = p.getExteriorRing() const polyPts = polyShell.getCoordinates() const shellPt = IsValidOp.findPtNotNode(shellPts, polyShell, graph) if (shellPt === null) return null const insidePolyShell = CGAlgorithms.isPointInRing(shellPt, polyPts) if (!insidePolyShell) return null if (p.getNumInteriorRing() <= 0) { this._validErr = new TopologyValidationError(TopologyValidationError.NESTED_SHELLS, shellPt) return null } let badNestedPt = null for (let i = 0; i < p.getNumInteriorRing(); i++) { const hole = p.getInteriorRingN(i) badNestedPt = this.checkShellInsideHole(shell, hole, graph) if (badNestedPt === null) return null } this._validErr = new TopologyValidationError(TopologyValidationError.NESTED_SHELLS, badNestedPt) } checkClosedRings (poly) { this.checkClosedRing(poly.getExteriorRing()) if (this._validErr !== null) return null for (let i = 0; i < poly.getNumInteriorRing(); i++) { this.checkClosedRing(poly.getInteriorRingN(i)) if (this._validErr !== null) return null } } checkClosedRing (ring) { if (!ring.isClosed()) { let pt = null if (ring.getNumPoints() >= 1) pt = ring.getCoordinateN(0) this._validErr = new TopologyValidationError(TopologyValidationError.RING_NOT_CLOSED, pt) } } checkShellsNotNested (mp, graph) { for (let i = 0; i < mp.getNumGeometries(); i++) { const p = mp.getGeometryN(i) const shell = p.getExteriorRing() for (let j = 0; j < mp.getNumGeometries(); j++) { if (i === j) continue const p2 = mp.getGeometryN(j) this.checkShellNotNested(shell, p2, graph) if (this._validErr !== null) return null } } } interfaces_ () { return [] } getClass () { return IsValidOp } static findPtNotNode (testCoords, searchRing, graph) { const searchEdge = graph.findEdge(searchRing) const eiList = searchEdge.getEdgeIntersectionList() for (let i = 0; i < testCoords.length; i++) { const pt = testCoords[i] if (!eiList.isIntersection(pt)) return pt } return null } static isValid () { if (arguments[0] instanceof Geometry) { let geom = arguments[0] const isValidOp = new IsValidOp(geom) return isValidOp.isValid() } else if (arguments[0] instanceof Coordinate) { let coord = arguments[0] if (Double.isNaN(coord.x)) return false if (Double.isInfinite(coord.x)) return false if (Double.isNaN(coord.y)) return false if (Double.isInfinite(coord.y)) return false return true } } }