BufferBuilder.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import Location from '../../geom/Location'
  2. import BufferSubgraph from './BufferSubgraph'
  3. import PolygonBuilder from '../overlay/PolygonBuilder'
  4. import GeometryFactory from '../../geom/GeometryFactory'
  5. import Position from '../../geomgraph/Position'
  6. import MCIndexNoder from '../../noding/MCIndexNoder'
  7. import OffsetCurveBuilder from './OffsetCurveBuilder'
  8. import Collections from '../../../../../java/util/Collections'
  9. import SubgraphDepthLocater from './SubgraphDepthLocater'
  10. import OffsetCurveSetBuilder from './OffsetCurveSetBuilder'
  11. import Label from '../../geomgraph/Label'
  12. import OverlayNodeFactory from '../overlay/OverlayNodeFactory'
  13. import EdgeList from '../../geomgraph/EdgeList'
  14. import ArrayList from '../../../../../java/util/ArrayList'
  15. import RobustLineIntersector from '../../algorithm/RobustLineIntersector'
  16. import IntersectionAdder from '../../noding/IntersectionAdder'
  17. import Edge from '../../geomgraph/Edge'
  18. import PlanarGraph from '../../geomgraph/PlanarGraph'
  19. export default class BufferBuilder {
  20. constructor() {
  21. BufferBuilder.constructor_.apply(this, arguments)
  22. }
  23. static constructor_() {
  24. this._bufParams = null
  25. this._workingPrecisionModel = null
  26. this._workingNoder = null
  27. this._geomFact = null
  28. this._graph = null
  29. this._edgeList = new EdgeList()
  30. const bufParams = arguments[0]
  31. this._bufParams = bufParams
  32. }
  33. static depthDelta(label) {
  34. const lLoc = label.getLocation(0, Position.LEFT)
  35. const rLoc = label.getLocation(0, Position.RIGHT)
  36. if (lLoc === Location.INTERIOR && rLoc === Location.EXTERIOR) return 1; else if (lLoc === Location.EXTERIOR && rLoc === Location.INTERIOR) return -1
  37. return 0
  38. }
  39. static convertSegStrings(it) {
  40. const fact = new GeometryFactory()
  41. const lines = new ArrayList()
  42. while (it.hasNext()) {
  43. const ss = it.next()
  44. const line = fact.createLineString(ss.getCoordinates())
  45. lines.add(line)
  46. }
  47. return fact.buildGeometry(lines)
  48. }
  49. setWorkingPrecisionModel(pm) {
  50. this._workingPrecisionModel = pm
  51. }
  52. insertUniqueEdge(e) {
  53. const existingEdge = this._edgeList.findEqualEdge(e)
  54. if (existingEdge !== null) {
  55. const existingLabel = existingEdge.getLabel()
  56. let labelToMerge = e.getLabel()
  57. if (!existingEdge.isPointwiseEqual(e)) {
  58. labelToMerge = new Label(e.getLabel())
  59. labelToMerge.flip()
  60. }
  61. existingLabel.merge(labelToMerge)
  62. const mergeDelta = BufferBuilder.depthDelta(labelToMerge)
  63. const existingDelta = existingEdge.getDepthDelta()
  64. const newDelta = existingDelta + mergeDelta
  65. existingEdge.setDepthDelta(newDelta)
  66. } else {
  67. this._edgeList.add(e)
  68. e.setDepthDelta(BufferBuilder.depthDelta(e.getLabel()))
  69. }
  70. }
  71. buildSubgraphs(subgraphList, polyBuilder) {
  72. const processedGraphs = new ArrayList()
  73. for (let i = subgraphList.iterator(); i.hasNext(); ) {
  74. const subgraph = i.next()
  75. const p = subgraph.getRightmostCoordinate()
  76. const locater = new SubgraphDepthLocater(processedGraphs)
  77. const outsideDepth = locater.getDepth(p)
  78. subgraph.computeDepth(outsideDepth)
  79. subgraph.findResultEdges()
  80. processedGraphs.add(subgraph)
  81. polyBuilder.add(subgraph.getDirectedEdges(), subgraph.getNodes())
  82. }
  83. }
  84. createSubgraphs(graph) {
  85. const subgraphList = new ArrayList()
  86. for (let i = graph.getNodes().iterator(); i.hasNext(); ) {
  87. const node = i.next()
  88. if (!node.isVisited()) {
  89. const subgraph = new BufferSubgraph()
  90. subgraph.create(node)
  91. subgraphList.add(subgraph)
  92. }
  93. }
  94. Collections.sort(subgraphList, Collections.reverseOrder())
  95. return subgraphList
  96. }
  97. createEmptyResultGeometry() {
  98. const emptyGeom = this._geomFact.createPolygon()
  99. return emptyGeom
  100. }
  101. getNoder(precisionModel) {
  102. if (this._workingNoder !== null) return this._workingNoder
  103. const noder = new MCIndexNoder()
  104. const li = new RobustLineIntersector()
  105. li.setPrecisionModel(precisionModel)
  106. noder.setSegmentIntersector(new IntersectionAdder(li))
  107. return noder
  108. }
  109. buffer(g, distance) {
  110. let precisionModel = this._workingPrecisionModel
  111. if (precisionModel === null) precisionModel = g.getPrecisionModel()
  112. this._geomFact = g.getFactory()
  113. const curveBuilder = new OffsetCurveBuilder(precisionModel, this._bufParams)
  114. const curveSetBuilder = new OffsetCurveSetBuilder(g, distance, curveBuilder)
  115. const bufferSegStrList = curveSetBuilder.getCurves()
  116. if (bufferSegStrList.size() <= 0)
  117. return this.createEmptyResultGeometry()
  118. this.computeNodedEdges(bufferSegStrList, precisionModel)
  119. this._graph = new PlanarGraph(new OverlayNodeFactory())
  120. this._graph.addEdges(this._edgeList.getEdges())
  121. const subgraphList = this.createSubgraphs(this._graph)
  122. const polyBuilder = new PolygonBuilder(this._geomFact)
  123. this.buildSubgraphs(subgraphList, polyBuilder)
  124. const resultPolyList = polyBuilder.getPolygons()
  125. if (resultPolyList.size() <= 0)
  126. return this.createEmptyResultGeometry()
  127. const resultGeom = this._geomFact.buildGeometry(resultPolyList)
  128. return resultGeom
  129. }
  130. computeNodedEdges(bufferSegStrList, precisionModel) {
  131. const noder = this.getNoder(precisionModel)
  132. noder.computeNodes(bufferSegStrList)
  133. const nodedSegStrings = noder.getNodedSubstrings()
  134. for (let i = nodedSegStrings.iterator(); i.hasNext(); ) {
  135. const segStr = i.next()
  136. const pts = segStr.getCoordinates()
  137. if (pts.length === 2 && pts[0].equals2D(pts[1])) continue
  138. const oldLabel = segStr.getData()
  139. const edge = new Edge(segStr.getCoordinates(), new Label(oldLabel))
  140. this.insertUniqueEdge(edge)
  141. }
  142. }
  143. setNoder(noder) {
  144. this._workingNoder = noder
  145. }
  146. }