VoronoiDiagramBuilder.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import Geometry from '../geom/Geometry'
  2. import hasInterface from '../../../../hasInterface'
  3. import GeometryFactory from '../geom/GeometryFactory'
  4. import Collection from '../../../../java/util/Collection'
  5. import IncrementalDelaunayTriangulator from './IncrementalDelaunayTriangulator'
  6. import QuadEdgeSubdivision from './quadedge/QuadEdgeSubdivision'
  7. import DelaunayTriangulationBuilder from './DelaunayTriangulationBuilder'
  8. import CoordinateArrays from '../geom/CoordinateArrays'
  9. import ArrayList from '../../../../java/util/ArrayList'
  10. import OverlayOp from '../operation/overlay/OverlayOp'
  11. export default class VoronoiDiagramBuilder {
  12. constructor() {
  13. VoronoiDiagramBuilder.constructor_.apply(this, arguments)
  14. }
  15. static constructor_() {
  16. this._siteCoords = null
  17. this._tolerance = 0.0
  18. this._subdiv = null
  19. this._clipEnv = null
  20. this._diagramEnv = null
  21. }
  22. static clipGeometryCollection(geom, clipEnv) {
  23. const clipPoly = geom.getFactory().toGeometry(clipEnv)
  24. const clipped = new ArrayList()
  25. for (let i = 0; i < geom.getNumGeometries(); i++) {
  26. const g = geom.getGeometryN(i)
  27. let result = null
  28. if (clipEnv.contains(g.getEnvelopeInternal())) {
  29. result = g
  30. } else if (clipEnv.intersects(g.getEnvelopeInternal())) {
  31. result = OverlayOp.intersection(clipPoly, g)
  32. result.setUserData(g.getUserData())
  33. }
  34. if (result !== null && !result.isEmpty())
  35. clipped.add(result)
  36. }
  37. return geom.getFactory().createGeometryCollection(GeometryFactory.toGeometryArray(clipped))
  38. }
  39. create() {
  40. if (this._subdiv !== null) return null
  41. const siteEnv = DelaunayTriangulationBuilder.envelope(this._siteCoords)
  42. this._diagramEnv = this._clipEnv
  43. if (this._diagramEnv === null) {
  44. this._diagramEnv = siteEnv
  45. const expandBy = this._diagramEnv.getDiameter()
  46. this._diagramEnv.expandBy(expandBy)
  47. }
  48. const vertices = DelaunayTriangulationBuilder.toVertices(this._siteCoords)
  49. this._subdiv = new QuadEdgeSubdivision(siteEnv, this._tolerance)
  50. const triangulator = new IncrementalDelaunayTriangulator(this._subdiv)
  51. triangulator.insertSites(vertices)
  52. }
  53. getDiagram(geomFact) {
  54. this.create()
  55. const polys = this._subdiv.getVoronoiDiagram(geomFact)
  56. return VoronoiDiagramBuilder.clipGeometryCollection(polys, this._diagramEnv)
  57. }
  58. setTolerance(tolerance) {
  59. this._tolerance = tolerance
  60. }
  61. setSites() {
  62. if (arguments[0] instanceof Geometry) {
  63. const geom = arguments[0]
  64. this._siteCoords = DelaunayTriangulationBuilder.extractUniqueCoordinates(geom)
  65. } else if (hasInterface(arguments[0], Collection)) {
  66. const coords = arguments[0]
  67. this._siteCoords = DelaunayTriangulationBuilder.unique(CoordinateArrays.toCoordinateArray(coords))
  68. }
  69. }
  70. setClipEnvelope(clipEnv) {
  71. this._clipEnv = clipEnv
  72. }
  73. getSubdivision() {
  74. this.create()
  75. return this._subdiv
  76. }
  77. }