MinimumClearance.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import ItemBoundable from '../index/strtree/ItemBoundable'
  2. import FacetSequence from '../operation/distance/FacetSequence'
  3. import Coordinate from '../geom/Coordinate'
  4. import Double from '../../../../java/lang/Double'
  5. import LineSegment from '../geom/LineSegment'
  6. import FacetSequenceTreeBuilder from '../operation/distance/FacetSequenceTreeBuilder'
  7. import Distance from '../algorithm/Distance'
  8. import ItemDistance from '../index/strtree/ItemDistance'
  9. export default class MinimumClearance {
  10. constructor() {
  11. MinimumClearance.constructor_.apply(this, arguments)
  12. }
  13. static constructor_() {
  14. this._inputGeom = null
  15. this._minClearance = null
  16. this._minClearancePts = null
  17. const geom = arguments[0]
  18. this._inputGeom = geom
  19. }
  20. static getLine(g) {
  21. const rp = new MinimumClearance(g)
  22. return rp.getLine()
  23. }
  24. static getDistance(g) {
  25. const rp = new MinimumClearance(g)
  26. return rp.getDistance()
  27. }
  28. getLine() {
  29. this.compute()
  30. if (this._minClearancePts === null || this._minClearancePts[0] === null) return this._inputGeom.getFactory().createLineString()
  31. return this._inputGeom.getFactory().createLineString(this._minClearancePts)
  32. }
  33. compute() {
  34. if (this._minClearancePts !== null) return null
  35. this._minClearancePts = new Array(2).fill(null)
  36. this._minClearance = Double.MAX_VALUE
  37. if (this._inputGeom.isEmpty())
  38. return null
  39. const geomTree = FacetSequenceTreeBuilder.build(this._inputGeom)
  40. const nearest = geomTree.nearestNeighbour(new MinClearanceDistance())
  41. const mcd = new MinClearanceDistance()
  42. this._minClearance = mcd.distance(nearest[0], nearest[1])
  43. this._minClearancePts = mcd.getCoordinates()
  44. }
  45. getDistance() {
  46. this.compute()
  47. return this._minClearance
  48. }
  49. }
  50. class MinClearanceDistance {
  51. constructor() {
  52. MinClearanceDistance.constructor_.apply(this, arguments)
  53. }
  54. static constructor_() {
  55. this._minDist = Double.MAX_VALUE
  56. this._minPts = new Array(2).fill(null)
  57. }
  58. vertexDistance(fs1, fs2) {
  59. for (let i1 = 0; i1 < fs1.size(); i1++)
  60. for (let i2 = 0; i2 < fs2.size(); i2++) {
  61. const p1 = fs1.getCoordinate(i1)
  62. const p2 = fs2.getCoordinate(i2)
  63. if (!p1.equals2D(p2)) {
  64. const d = p1.distance(p2)
  65. if (d < this._minDist) {
  66. this._minDist = d
  67. this._minPts[0] = p1
  68. this._minPts[1] = p2
  69. if (d === 0.0) return d
  70. }
  71. }
  72. }
  73. return this._minDist
  74. }
  75. getCoordinates() {
  76. return this._minPts
  77. }
  78. segmentDistance(fs1, fs2) {
  79. for (let i1 = 0; i1 < fs1.size(); i1++)
  80. for (let i2 = 1; i2 < fs2.size(); i2++) {
  81. const p = fs1.getCoordinate(i1)
  82. const seg0 = fs2.getCoordinate(i2 - 1)
  83. const seg1 = fs2.getCoordinate(i2)
  84. if (!(p.equals2D(seg0) || p.equals2D(seg1))) {
  85. const d = Distance.pointToSegment(p, seg0, seg1)
  86. if (d < this._minDist) {
  87. this._minDist = d
  88. this.updatePts(p, seg0, seg1)
  89. if (d === 0.0) return d
  90. }
  91. }
  92. }
  93. return this._minDist
  94. }
  95. distance() {
  96. if (arguments[0] instanceof ItemBoundable && arguments[1] instanceof ItemBoundable) {
  97. const b1 = arguments[0], b2 = arguments[1]
  98. const fs1 = b1.getItem()
  99. const fs2 = b2.getItem()
  100. this._minDist = Double.MAX_VALUE
  101. return this.distance(fs1, fs2)
  102. } else if (arguments[0] instanceof FacetSequence && arguments[1] instanceof FacetSequence) {
  103. const fs1 = arguments[0], fs2 = arguments[1]
  104. this.vertexDistance(fs1, fs2)
  105. if (fs1.size() === 1 && fs2.size() === 1) return this._minDist
  106. if (this._minDist <= 0.0) return this._minDist
  107. this.segmentDistance(fs1, fs2)
  108. if (this._minDist <= 0.0) return this._minDist
  109. this.segmentDistance(fs2, fs1)
  110. return this._minDist
  111. }
  112. }
  113. updatePts(p, seg0, seg1) {
  114. this._minPts[0] = p
  115. const seg = new LineSegment(seg0, seg1)
  116. this._minPts[1] = new Coordinate(seg.closestPoint(p))
  117. }
  118. get interfaces_() {
  119. return [ItemDistance]
  120. }
  121. }
  122. MinimumClearance.MinClearanceDistance = MinClearanceDistance