| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- 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)
- }
- }
- }
|