EdgeRing.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. import Location from '../geom/Location'
  2. import Position from './Position'
  3. import PointLocation from '../algorithm/PointLocation'
  4. import TopologyException from '../geom/TopologyException'
  5. import Orientation from '../algorithm/Orientation'
  6. import Label from './Label'
  7. import ArrayList from '../../../../java/util/ArrayList'
  8. import Assert from '../util/Assert'
  9. export default class EdgeRing {
  10. constructor() {
  11. EdgeRing.constructor_.apply(this, arguments)
  12. }
  13. static constructor_() {
  14. this._startDe = null
  15. this._maxNodeDegree = -1
  16. this._edges = new ArrayList()
  17. this._pts = new ArrayList()
  18. this._label = new Label(Location.NONE)
  19. this._ring = null
  20. this._isHole = null
  21. this._shell = null
  22. this._holes = new ArrayList()
  23. this._geometryFactory = null
  24. if (arguments.length === 0) {} else if (arguments.length === 2) {
  25. const start = arguments[0], geometryFactory = arguments[1]
  26. this._geometryFactory = geometryFactory
  27. this.computePoints(start)
  28. this.computeRing()
  29. }
  30. }
  31. computeRing() {
  32. if (this._ring !== null) return null
  33. const coord = new Array(this._pts.size()).fill(null)
  34. for (let i = 0; i < this._pts.size(); i++)
  35. coord[i] = this._pts.get(i)
  36. this._ring = this._geometryFactory.createLinearRing(coord)
  37. this._isHole = Orientation.isCCW(this._ring.getCoordinates())
  38. }
  39. isIsolated() {
  40. return this._label.getGeometryCount() === 1
  41. }
  42. computePoints(start) {
  43. this._startDe = start
  44. let de = start
  45. let isFirstEdge = true
  46. do {
  47. if (de === null) throw new TopologyException('Found null DirectedEdge')
  48. if (de.getEdgeRing() === this) throw new TopologyException('Directed Edge visited twice during ring-building at ' + de.getCoordinate())
  49. this._edges.add(de)
  50. const label = de.getLabel()
  51. Assert.isTrue(label.isArea())
  52. this.mergeLabel(label)
  53. this.addPoints(de.getEdge(), de.isForward(), isFirstEdge)
  54. isFirstEdge = false
  55. this.setEdgeRing(de, this)
  56. de = this.getNext(de)
  57. } while (de !== this._startDe)
  58. }
  59. getLinearRing() {
  60. return this._ring
  61. }
  62. getCoordinate(i) {
  63. return this._pts.get(i)
  64. }
  65. computeMaxNodeDegree() {
  66. this._maxNodeDegree = 0
  67. let de = this._startDe
  68. do {
  69. const node = de.getNode()
  70. const degree = node.getEdges().getOutgoingDegree(this)
  71. if (degree > this._maxNodeDegree) this._maxNodeDegree = degree
  72. de = this.getNext(de)
  73. } while (de !== this._startDe)
  74. this._maxNodeDegree *= 2
  75. }
  76. addPoints(edge, isForward, isFirstEdge) {
  77. const edgePts = edge.getCoordinates()
  78. if (isForward) {
  79. let startIndex = 1
  80. if (isFirstEdge) startIndex = 0
  81. for (let i = startIndex; i < edgePts.length; i++)
  82. this._pts.add(edgePts[i])
  83. } else {
  84. let startIndex = edgePts.length - 2
  85. if (isFirstEdge) startIndex = edgePts.length - 1
  86. for (let i = startIndex; i >= 0; i--)
  87. this._pts.add(edgePts[i])
  88. }
  89. }
  90. isHole() {
  91. return this._isHole
  92. }
  93. setInResult() {
  94. let de = this._startDe
  95. do {
  96. de.getEdge().setInResult(true)
  97. de = de.getNext()
  98. } while (de !== this._startDe)
  99. }
  100. containsPoint(p) {
  101. const shell = this.getLinearRing()
  102. const env = shell.getEnvelopeInternal()
  103. if (!env.contains(p)) return false
  104. if (!PointLocation.isInRing(p, shell.getCoordinates())) return false
  105. for (let i = this._holes.iterator(); i.hasNext(); ) {
  106. const hole = i.next()
  107. if (hole.containsPoint(p)) return false
  108. }
  109. return true
  110. }
  111. addHole(ring) {
  112. this._holes.add(ring)
  113. }
  114. isShell() {
  115. return this._shell === null
  116. }
  117. getLabel() {
  118. return this._label
  119. }
  120. getEdges() {
  121. return this._edges
  122. }
  123. getMaxNodeDegree() {
  124. if (this._maxNodeDegree < 0) this.computeMaxNodeDegree()
  125. return this._maxNodeDegree
  126. }
  127. getShell() {
  128. return this._shell
  129. }
  130. mergeLabel() {
  131. if (arguments.length === 1) {
  132. const deLabel = arguments[0]
  133. this.mergeLabel(deLabel, 0)
  134. this.mergeLabel(deLabel, 1)
  135. } else if (arguments.length === 2) {
  136. const deLabel = arguments[0], geomIndex = arguments[1]
  137. const loc = deLabel.getLocation(geomIndex, Position.RIGHT)
  138. if (loc === Location.NONE) return null
  139. if (this._label.getLocation(geomIndex) === Location.NONE) {
  140. this._label.setLocation(geomIndex, loc)
  141. return null
  142. }
  143. }
  144. }
  145. setShell(shell) {
  146. this._shell = shell
  147. if (shell !== null) shell.addHole(this)
  148. }
  149. toPolygon(geometryFactory) {
  150. const holeLR = new Array(this._holes.size()).fill(null)
  151. for (let i = 0; i < this._holes.size(); i++)
  152. holeLR[i] = this._holes.get(i).getLinearRing()
  153. const poly = geometryFactory.createPolygon(this.getLinearRing(), holeLR)
  154. return poly
  155. }
  156. }