EdgeRing.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import Location from '../../geom/Location'
  2. import CoordinateList from '../../geom/CoordinateList'
  3. import WKTWriter from '../../io/WKTWriter'
  4. import CoordinateArraySequence from '../../geom/impl/CoordinateArraySequence'
  5. import IsValidOp from '../valid/IsValidOp'
  6. import LinearRing from '../../geom/LinearRing'
  7. import Exception from '../../../../../java/lang/Exception'
  8. import Orientation from '../../algorithm/Orientation'
  9. import System from '../../../../../java/lang/System'
  10. import CoordinateArrays from '../../geom/CoordinateArrays'
  11. import ArrayList from '../../../../../java/util/ArrayList'
  12. import Comparator from '../../../../../java/util/Comparator'
  13. import IndexedPointInAreaLocator from '../../algorithm/locate/IndexedPointInAreaLocator'
  14. import Assert from '../../util/Assert'
  15. export default class EdgeRing {
  16. constructor() {
  17. EdgeRing.constructor_.apply(this, arguments)
  18. }
  19. static constructor_() {
  20. this._factory = null
  21. this._deList = new ArrayList()
  22. this._lowestEdge = null
  23. this._ring = null
  24. this._locator = null
  25. this._ringPts = null
  26. this._holes = null
  27. this._shell = null
  28. this._isHole = null
  29. this._isProcessed = false
  30. this._isIncludedSet = false
  31. this._isIncluded = false
  32. const factory = arguments[0]
  33. this._factory = factory
  34. }
  35. static findDirEdgesInRing(startDE) {
  36. let de = startDE
  37. const edges = new ArrayList()
  38. do {
  39. edges.add(de)
  40. de = de.getNext()
  41. Assert.isTrue(de !== null, 'found null DE in ring')
  42. Assert.isTrue(de === startDE || !de.isInRing(), 'found DE already in ring')
  43. } while (de !== startDE)
  44. return edges
  45. }
  46. static addEdge(coords, isForward, coordList) {
  47. if (isForward)
  48. for (let i = 0; i < coords.length; i++)
  49. coordList.add(coords[i], false)
  50. else
  51. for (let i = coords.length - 1; i >= 0; i--)
  52. coordList.add(coords[i], false)
  53. }
  54. static findEdgeRingContaining(testEr, erList) {
  55. const testRing = testEr.getRing()
  56. const testEnv = testRing.getEnvelopeInternal()
  57. let testPt = testRing.getCoordinateN(0)
  58. let minRing = null
  59. let minRingEnv = null
  60. for (let it = erList.iterator(); it.hasNext(); ) {
  61. const tryEdgeRing = it.next()
  62. const tryRing = tryEdgeRing.getRing()
  63. const tryShellEnv = tryRing.getEnvelopeInternal()
  64. if (tryShellEnv.equals(testEnv)) continue
  65. if (!tryShellEnv.contains(testEnv)) continue
  66. testPt = CoordinateArrays.ptNotInList(testRing.getCoordinates(), tryEdgeRing.getCoordinates())
  67. const isContained = tryEdgeRing.isInRing(testPt)
  68. if (isContained)
  69. if (minRing === null || minRingEnv.contains(tryShellEnv)) {
  70. minRing = tryEdgeRing
  71. minRingEnv = minRing.getRing().getEnvelopeInternal()
  72. }
  73. }
  74. return minRing
  75. }
  76. isIncluded() {
  77. return this._isIncluded
  78. }
  79. getCoordinates() {
  80. if (this._ringPts === null) {
  81. const coordList = new CoordinateList()
  82. for (let i = this._deList.iterator(); i.hasNext(); ) {
  83. const de = i.next()
  84. const edge = de.getEdge()
  85. EdgeRing.addEdge(edge.getLine().getCoordinates(), de.getEdgeDirection(), coordList)
  86. }
  87. this._ringPts = coordList.toCoordinateArray()
  88. }
  89. return this._ringPts
  90. }
  91. isIncludedSet() {
  92. return this._isIncludedSet
  93. }
  94. isValid() {
  95. this.getCoordinates()
  96. if (this._ringPts.length <= 3) return false
  97. this.getRing()
  98. return IsValidOp.isValid(this._ring)
  99. }
  100. build(startDE) {
  101. let de = startDE
  102. do {
  103. this.add(de)
  104. de.setRing(this)
  105. de = de.getNext()
  106. Assert.isTrue(de !== null, 'found null DE in ring')
  107. Assert.isTrue(de === startDE || !de.isInRing(), 'found DE already in ring')
  108. } while (de !== startDE)
  109. }
  110. isInRing(pt) {
  111. return Location.EXTERIOR !== this.getLocator().locate(pt)
  112. }
  113. isOuterHole() {
  114. if (!this._isHole) return false
  115. return !this.hasShell()
  116. }
  117. getPolygon() {
  118. let holeLR = null
  119. if (this._holes !== null) {
  120. holeLR = new Array(this._holes.size()).fill(null)
  121. for (let i = 0; i < this._holes.size(); i++)
  122. holeLR[i] = this._holes.get(i)
  123. }
  124. const poly = this._factory.createPolygon(this._ring, holeLR)
  125. return poly
  126. }
  127. isHole() {
  128. return this._isHole
  129. }
  130. isProcessed() {
  131. return this._isProcessed
  132. }
  133. addHole() {
  134. if (arguments[0] instanceof LinearRing) {
  135. const hole = arguments[0]
  136. if (this._holes === null) this._holes = new ArrayList()
  137. this._holes.add(hole)
  138. } else if (arguments[0] instanceof EdgeRing) {
  139. const holeER = arguments[0]
  140. holeER.setShell(this)
  141. const hole = holeER.getRing()
  142. if (this._holes === null) this._holes = new ArrayList()
  143. this._holes.add(hole)
  144. }
  145. }
  146. setIncluded(isIncluded) {
  147. this._isIncluded = isIncluded
  148. this._isIncludedSet = true
  149. }
  150. getOuterHole() {
  151. if (this.isHole()) return null
  152. for (let i = 0; i < this._deList.size(); i++) {
  153. const de = this._deList.get(i)
  154. const adjRing = de.getSym().getRing()
  155. if (adjRing.isOuterHole()) return adjRing
  156. }
  157. return null
  158. }
  159. computeHole() {
  160. const ring = this.getRing()
  161. this._isHole = Orientation.isCCW(ring.getCoordinates())
  162. }
  163. hasShell() {
  164. return this._shell !== null
  165. }
  166. isOuterShell() {
  167. return this.getOuterHole() !== null
  168. }
  169. getLineString() {
  170. this.getCoordinates()
  171. return this._factory.createLineString(this._ringPts)
  172. }
  173. toString() {
  174. return WKTWriter.toLineString(new CoordinateArraySequence(this.getCoordinates()))
  175. }
  176. getLocator() {
  177. if (this._locator === null)
  178. this._locator = new IndexedPointInAreaLocator(this.getRing())
  179. return this._locator
  180. }
  181. getShell() {
  182. if (this.isHole()) return this._shell
  183. return this
  184. }
  185. add(de) {
  186. this._deList.add(de)
  187. }
  188. getRing() {
  189. if (this._ring !== null) return this._ring
  190. this.getCoordinates()
  191. if (this._ringPts.length < 3) System.out.println(this._ringPts)
  192. try {
  193. this._ring = this._factory.createLinearRing(this._ringPts)
  194. } catch (ex) {
  195. if (ex instanceof Exception)
  196. System.out.println(this._ringPts)
  197. else throw ex
  198. } finally {}
  199. return this._ring
  200. }
  201. updateIncluded() {
  202. if (this.isHole()) return null
  203. for (let i = 0; i < this._deList.size(); i++) {
  204. const de = this._deList.get(i)
  205. const adjShell = de.getSym().getRing().getShell()
  206. if (adjShell !== null && adjShell.isIncludedSet()) {
  207. this.setIncluded(!adjShell.isIncluded())
  208. return null
  209. }
  210. }
  211. }
  212. setShell(shell) {
  213. this._shell = shell
  214. }
  215. setProcessed(isProcessed) {
  216. this._isProcessed = isProcessed
  217. }
  218. }
  219. class EnvelopeComparator {
  220. compare(obj0, obj1) {
  221. const r0 = obj0
  222. const r1 = obj1
  223. return r0.getRing().getEnvelope().compareTo(r1.getRing().getEnvelope())
  224. }
  225. get interfaces_() {
  226. return [Comparator]
  227. }
  228. }
  229. EdgeRing.EnvelopeComparator = EnvelopeComparator