DirectedEdgeStar.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import Location from '../geom/Location'
  2. import Position from './Position'
  3. import TopologyException from '../geom/TopologyException'
  4. import EdgeEndStar from './EdgeEndStar'
  5. import System from '../../../../java/lang/System'
  6. import Label from './Label'
  7. import ArrayList from '../../../../java/util/ArrayList'
  8. import Quadrant from './Quadrant'
  9. import Assert from '../util/Assert'
  10. export default class DirectedEdgeStar extends EdgeEndStar {
  11. constructor() {
  12. super()
  13. DirectedEdgeStar.constructor_.apply(this, arguments)
  14. }
  15. static constructor_() {
  16. this._resultAreaEdgeList = null
  17. this._label = null
  18. this._SCANNING_FOR_INCOMING = 1
  19. this._LINKING_TO_OUTGOING = 2
  20. }
  21. linkResultDirectedEdges() {
  22. this.getResultAreaEdges()
  23. let firstOut = null
  24. let incoming = null
  25. let state = this._SCANNING_FOR_INCOMING
  26. for (let i = 0; i < this._resultAreaEdgeList.size(); i++) {
  27. const nextOut = this._resultAreaEdgeList.get(i)
  28. const nextIn = nextOut.getSym()
  29. if (!nextOut.getLabel().isArea()) continue
  30. if (firstOut === null && nextOut.isInResult()) firstOut = nextOut
  31. switch (state) {
  32. case this._SCANNING_FOR_INCOMING:
  33. if (!nextIn.isInResult()) continue
  34. incoming = nextIn
  35. state = this._LINKING_TO_OUTGOING
  36. break
  37. case this._LINKING_TO_OUTGOING:
  38. if (!nextOut.isInResult()) continue
  39. incoming.setNext(nextOut)
  40. state = this._SCANNING_FOR_INCOMING
  41. break
  42. }
  43. }
  44. if (state === this._LINKING_TO_OUTGOING) {
  45. if (firstOut === null) throw new TopologyException('no outgoing dirEdge found', this.getCoordinate())
  46. Assert.isTrue(firstOut.isInResult(), 'unable to link last incoming dirEdge')
  47. incoming.setNext(firstOut)
  48. }
  49. }
  50. insert(ee) {
  51. const de = ee
  52. this.insertEdgeEnd(de, de)
  53. }
  54. getRightmostEdge() {
  55. const edges = this.getEdges()
  56. const size = edges.size()
  57. if (size < 1) return null
  58. const de0 = edges.get(0)
  59. if (size === 1) return de0
  60. const deLast = edges.get(size - 1)
  61. const quad0 = de0.getQuadrant()
  62. const quad1 = deLast.getQuadrant()
  63. if (Quadrant.isNorthern(quad0) && Quadrant.isNorthern(quad1)) {
  64. return de0
  65. } else if (!Quadrant.isNorthern(quad0) && !Quadrant.isNorthern(quad1)) {
  66. return deLast
  67. } else {
  68. const nonHorizontalEdge = null
  69. if (de0.getDy() !== 0) return de0; else if (deLast.getDy() !== 0) return deLast
  70. }
  71. Assert.shouldNeverReachHere('found two horizontal edges incident on node')
  72. return null
  73. }
  74. print(out) {
  75. System.out.println('DirectedEdgeStar: ' + this.getCoordinate())
  76. for (let it = this.iterator(); it.hasNext(); ) {
  77. const de = it.next()
  78. out.print('out ')
  79. de.print(out)
  80. out.println()
  81. out.print('in ')
  82. de.getSym().print(out)
  83. out.println()
  84. }
  85. }
  86. getResultAreaEdges() {
  87. if (this._resultAreaEdgeList !== null) return this._resultAreaEdgeList
  88. this._resultAreaEdgeList = new ArrayList()
  89. for (let it = this.iterator(); it.hasNext(); ) {
  90. const de = it.next()
  91. if (de.isInResult() || de.getSym().isInResult()) this._resultAreaEdgeList.add(de)
  92. }
  93. return this._resultAreaEdgeList
  94. }
  95. updateLabelling(nodeLabel) {
  96. for (let it = this.iterator(); it.hasNext(); ) {
  97. const de = it.next()
  98. const label = de.getLabel()
  99. label.setAllLocationsIfNull(0, nodeLabel.getLocation(0))
  100. label.setAllLocationsIfNull(1, nodeLabel.getLocation(1))
  101. }
  102. }
  103. linkAllDirectedEdges() {
  104. this.getEdges()
  105. let prevOut = null
  106. let firstIn = null
  107. for (let i = this._edgeList.size() - 1; i >= 0; i--) {
  108. const nextOut = this._edgeList.get(i)
  109. const nextIn = nextOut.getSym()
  110. if (firstIn === null) firstIn = nextIn
  111. if (prevOut !== null) nextIn.setNext(prevOut)
  112. prevOut = nextOut
  113. }
  114. firstIn.setNext(prevOut)
  115. }
  116. computeDepths() {
  117. if (arguments.length === 1) {
  118. const de = arguments[0]
  119. const edgeIndex = this.findIndex(de)
  120. const startDepth = de.getDepth(Position.LEFT)
  121. const targetLastDepth = de.getDepth(Position.RIGHT)
  122. const nextDepth = this.computeDepths(edgeIndex + 1, this._edgeList.size(), startDepth)
  123. const lastDepth = this.computeDepths(0, edgeIndex, nextDepth)
  124. if (lastDepth !== targetLastDepth) throw new TopologyException('depth mismatch at ' + de.getCoordinate())
  125. } else if (arguments.length === 3) {
  126. const startIndex = arguments[0], endIndex = arguments[1], startDepth = arguments[2]
  127. let currDepth = startDepth
  128. for (let i = startIndex; i < endIndex; i++) {
  129. const nextDe = this._edgeList.get(i)
  130. nextDe.setEdgeDepths(Position.RIGHT, currDepth)
  131. currDepth = nextDe.getDepth(Position.LEFT)
  132. }
  133. return currDepth
  134. }
  135. }
  136. mergeSymLabels() {
  137. for (let it = this.iterator(); it.hasNext(); ) {
  138. const de = it.next()
  139. const label = de.getLabel()
  140. label.merge(de.getSym().getLabel())
  141. }
  142. }
  143. linkMinimalDirectedEdges(er) {
  144. let firstOut = null
  145. let incoming = null
  146. let state = this._SCANNING_FOR_INCOMING
  147. for (let i = this._resultAreaEdgeList.size() - 1; i >= 0; i--) {
  148. const nextOut = this._resultAreaEdgeList.get(i)
  149. const nextIn = nextOut.getSym()
  150. if (firstOut === null && nextOut.getEdgeRing() === er) firstOut = nextOut
  151. switch (state) {
  152. case this._SCANNING_FOR_INCOMING:
  153. if (nextIn.getEdgeRing() !== er) continue
  154. incoming = nextIn
  155. state = this._LINKING_TO_OUTGOING
  156. break
  157. case this._LINKING_TO_OUTGOING:
  158. if (nextOut.getEdgeRing() !== er) continue
  159. incoming.setNextMin(nextOut)
  160. state = this._SCANNING_FOR_INCOMING
  161. break
  162. }
  163. }
  164. if (state === this._LINKING_TO_OUTGOING) {
  165. Assert.isTrue(firstOut !== null, 'found null for first outgoing dirEdge')
  166. Assert.isTrue(firstOut.getEdgeRing() === er, 'unable to link last incoming dirEdge')
  167. incoming.setNextMin(firstOut)
  168. }
  169. }
  170. getOutgoingDegree() {
  171. if (arguments.length === 0) {
  172. let degree = 0
  173. for (let it = this.iterator(); it.hasNext(); ) {
  174. const de = it.next()
  175. if (de.isInResult()) degree++
  176. }
  177. return degree
  178. } else if (arguments.length === 1) {
  179. const er = arguments[0]
  180. let degree = 0
  181. for (let it = this.iterator(); it.hasNext(); ) {
  182. const de = it.next()
  183. if (de.getEdgeRing() === er) degree++
  184. }
  185. return degree
  186. }
  187. }
  188. getLabel() {
  189. return this._label
  190. }
  191. findCoveredLineEdges() {
  192. let startLoc = Location.NONE
  193. for (let it = this.iterator(); it.hasNext(); ) {
  194. const nextOut = it.next()
  195. const nextIn = nextOut.getSym()
  196. if (!nextOut.isLineEdge()) {
  197. if (nextOut.isInResult()) {
  198. startLoc = Location.INTERIOR
  199. break
  200. }
  201. if (nextIn.isInResult()) {
  202. startLoc = Location.EXTERIOR
  203. break
  204. }
  205. }
  206. }
  207. if (startLoc === Location.NONE) return null
  208. let currLoc = startLoc
  209. for (let it = this.iterator(); it.hasNext(); ) {
  210. const nextOut = it.next()
  211. const nextIn = nextOut.getSym()
  212. if (nextOut.isLineEdge()) {
  213. nextOut.getEdge().setCovered(currLoc === Location.INTERIOR)
  214. } else {
  215. if (nextOut.isInResult()) currLoc = Location.EXTERIOR
  216. if (nextIn.isInResult()) currLoc = Location.INTERIOR
  217. }
  218. }
  219. }
  220. computeLabelling(geom) {
  221. super.computeLabelling.call(this, geom)
  222. this._label = new Label(Location.NONE)
  223. for (let it = this.iterator(); it.hasNext(); ) {
  224. const ee = it.next()
  225. const e = ee.getEdge()
  226. const eLabel = e.getLabel()
  227. for (let i = 0; i < 2; i++) {
  228. const eLoc = eLabel.getLocation(i)
  229. if (eLoc === Location.INTERIOR || eLoc === Location.BOUNDARY) this._label.setLocation(i, Location.INTERIOR)
  230. }
  231. }
  232. }
  233. }