Polygonizer.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import LineString from '../../geom/LineString'
  2. import Geometry from '../../geom/Geometry'
  3. import PolygonizeGraph from './PolygonizeGraph'
  4. import hasInterface from '../../../../../hasInterface'
  5. import GeometryFactory from '../../geom/GeometryFactory'
  6. import Collection from '../../../../../java/util/Collection'
  7. import Collections from '../../../../../java/util/Collections'
  8. import EdgeRing from './EdgeRing'
  9. import GeometryComponentFilter from '../../geom/GeometryComponentFilter'
  10. import ArrayList from '../../../../../java/util/ArrayList'
  11. import HoleAssigner from './HoleAssigner'
  12. export default class Polygonizer {
  13. constructor() {
  14. Polygonizer.constructor_.apply(this, arguments)
  15. }
  16. static constructor_() {
  17. this._lineStringAdder = new LineStringAdder(this)
  18. this._graph = null
  19. this._dangles = new ArrayList()
  20. this._cutEdges = new ArrayList()
  21. this._invalidRingLines = new ArrayList()
  22. this._holeList = null
  23. this._shellList = null
  24. this._polyList = null
  25. this._isCheckingRingsValid = true
  26. this._extractOnlyPolygonal = null
  27. this._geomFactory = null
  28. if (arguments.length === 0) {
  29. Polygonizer.constructor_.call(this, false)
  30. } else if (arguments.length === 1) {
  31. const extractOnlyPolygonal = arguments[0]
  32. this._extractOnlyPolygonal = extractOnlyPolygonal
  33. }
  34. }
  35. static extractPolygons(shellList, includeAll) {
  36. const polyList = new ArrayList()
  37. for (let i = shellList.iterator(); i.hasNext(); ) {
  38. const er = i.next()
  39. if (includeAll || er.isIncluded())
  40. polyList.add(er.getPolygon())
  41. }
  42. return polyList
  43. }
  44. static findOuterShells(shellList) {
  45. for (let i = shellList.iterator(); i.hasNext(); ) {
  46. const er = i.next()
  47. const outerHoleER = er.getOuterHole()
  48. if (outerHoleER !== null && !outerHoleER.isProcessed()) {
  49. er.setIncluded(true)
  50. outerHoleER.setProcessed(true)
  51. }
  52. }
  53. }
  54. static findDisjointShells(shellList) {
  55. Polygonizer.findOuterShells(shellList)
  56. let isMoreToScan = null
  57. do {
  58. isMoreToScan = false
  59. for (let i = shellList.iterator(); i.hasNext(); ) {
  60. const er = i.next()
  61. if (er.isIncludedSet()) continue
  62. er.updateIncluded()
  63. if (!er.isIncludedSet())
  64. isMoreToScan = true
  65. }
  66. } while (isMoreToScan)
  67. }
  68. getGeometry() {
  69. if (this._geomFactory === null) this._geomFactory = new GeometryFactory()
  70. this.polygonize()
  71. if (this._extractOnlyPolygonal)
  72. return this._geomFactory.buildGeometry(this._polyList)
  73. return this._geomFactory.createGeometryCollection(GeometryFactory.toGeometryArray(this._polyList))
  74. }
  75. getInvalidRingLines() {
  76. this.polygonize()
  77. return this._invalidRingLines
  78. }
  79. findValidRings(edgeRingList, validEdgeRingList, invalidRingList) {
  80. for (let i = edgeRingList.iterator(); i.hasNext(); ) {
  81. const er = i.next()
  82. if (er.isValid()) validEdgeRingList.add(er); else invalidRingList.add(er.getLineString())
  83. }
  84. }
  85. polygonize() {
  86. if (this._polyList !== null) return null
  87. this._polyList = new ArrayList()
  88. if (this._graph === null) return null
  89. this._dangles = this._graph.deleteDangles()
  90. this._cutEdges = this._graph.deleteCutEdges()
  91. const edgeRingList = this._graph.getEdgeRings()
  92. let validEdgeRingList = new ArrayList()
  93. this._invalidRingLines = new ArrayList()
  94. if (this._isCheckingRingsValid)
  95. this.findValidRings(edgeRingList, validEdgeRingList, this._invalidRingLines)
  96. else
  97. validEdgeRingList = edgeRingList
  98. this.findShellsAndHoles(validEdgeRingList)
  99. HoleAssigner.assignHolesToShells(this._holeList, this._shellList)
  100. Collections.sort(this._shellList, new EdgeRing.EnvelopeComparator())
  101. let includeAll = true
  102. if (this._extractOnlyPolygonal) {
  103. Polygonizer.findDisjointShells(this._shellList)
  104. includeAll = false
  105. }
  106. this._polyList = Polygonizer.extractPolygons(this._shellList, includeAll)
  107. }
  108. getDangles() {
  109. this.polygonize()
  110. return this._dangles
  111. }
  112. getCutEdges() {
  113. this.polygonize()
  114. return this._cutEdges
  115. }
  116. getPolygons() {
  117. this.polygonize()
  118. return this._polyList
  119. }
  120. add() {
  121. if (hasInterface(arguments[0], Collection)) {
  122. const geomList = arguments[0]
  123. for (let i = geomList.iterator(); i.hasNext(); ) {
  124. const geometry = i.next()
  125. this.add(geometry)
  126. }
  127. } else if (arguments[0] instanceof LineString) {
  128. const line = arguments[0]
  129. this._geomFactory = line.getFactory()
  130. if (this._graph === null) this._graph = new PolygonizeGraph(this._geomFactory)
  131. this._graph.addEdge(line)
  132. } else if (arguments[0] instanceof Geometry) {
  133. const g = arguments[0]
  134. g.apply(this._lineStringAdder)
  135. }
  136. }
  137. setCheckRingsValid(isCheckingRingsValid) {
  138. this._isCheckingRingsValid = isCheckingRingsValid
  139. }
  140. findShellsAndHoles(edgeRingList) {
  141. this._holeList = new ArrayList()
  142. this._shellList = new ArrayList()
  143. for (let i = edgeRingList.iterator(); i.hasNext(); ) {
  144. const er = i.next()
  145. er.computeHole()
  146. if (er.isHole()) this._holeList.add(er); else this._shellList.add(er)
  147. }
  148. }
  149. }
  150. class LineStringAdder {
  151. constructor() {
  152. LineStringAdder.constructor_.apply(this, arguments)
  153. }
  154. static constructor_() {
  155. this.p = null
  156. const p = arguments[0]
  157. this.p = p
  158. }
  159. filter(g) {
  160. if (g instanceof LineString) this.p.add(g)
  161. }
  162. get interfaces_() {
  163. return [GeometryComponentFilter]
  164. }
  165. }
  166. Polygonizer.LineStringAdder = LineStringAdder