VWLineSimplifier.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import CoordinateList from '../geom/CoordinateList'
  2. import Coordinate from '../geom/Coordinate'
  3. import Double from '../../../../java/lang/Double'
  4. import Triangle from '../geom/Triangle'
  5. export default class VWLineSimplifier {
  6. constructor() {
  7. VWLineSimplifier.constructor_.apply(this, arguments)
  8. }
  9. static constructor_() {
  10. this._pts = null
  11. this._tolerance = null
  12. const pts = arguments[0], distanceTolerance = arguments[1]
  13. this._pts = pts
  14. this._tolerance = distanceTolerance * distanceTolerance
  15. }
  16. static simplify(pts, distanceTolerance) {
  17. const simp = new VWLineSimplifier(pts, distanceTolerance)
  18. return simp.simplify()
  19. }
  20. simplifyVertex(vwLine) {
  21. let curr = vwLine
  22. let minArea = curr.getArea()
  23. let minVertex = null
  24. while (curr !== null) {
  25. const area = curr.getArea()
  26. if (area < minArea) {
  27. minArea = area
  28. minVertex = curr
  29. }
  30. curr = curr._next
  31. }
  32. if (minVertex !== null && minArea < this._tolerance)
  33. minVertex.remove()
  34. if (!vwLine.isLive()) return -1
  35. return minArea
  36. }
  37. simplify() {
  38. const vwLine = VWVertex.buildLine(this._pts)
  39. let minArea = this._tolerance
  40. do
  41. minArea = this.simplifyVertex(vwLine)
  42. while (minArea < this._tolerance)
  43. const simp = vwLine.getCoordinates()
  44. if (simp.length < 2)
  45. return [simp[0], new Coordinate(simp[0])]
  46. return simp
  47. }
  48. }
  49. class VWVertex {
  50. constructor() {
  51. VWVertex.constructor_.apply(this, arguments)
  52. }
  53. static constructor_() {
  54. this._pt = null
  55. this._prev = null
  56. this._next = null
  57. this._area = VWVertex.MAX_AREA
  58. this._isLive = true
  59. const pt = arguments[0]
  60. this._pt = pt
  61. }
  62. static buildLine(pts) {
  63. let first = null
  64. let prev = null
  65. for (let i = 0; i < pts.length; i++) {
  66. const v = new VWVertex(pts[i])
  67. if (first === null) first = v
  68. v.setPrev(prev)
  69. if (prev !== null) {
  70. prev.setNext(v)
  71. prev.updateArea()
  72. }
  73. prev = v
  74. }
  75. return first
  76. }
  77. getCoordinates() {
  78. const coords = new CoordinateList()
  79. let curr = this
  80. do {
  81. coords.add(curr._pt, false)
  82. curr = curr._next
  83. } while (curr !== null)
  84. return coords.toCoordinateArray()
  85. }
  86. getArea() {
  87. return this._area
  88. }
  89. updateArea() {
  90. if (this._prev === null || this._next === null) {
  91. this._area = VWVertex.MAX_AREA
  92. return null
  93. }
  94. this._area = Math.abs(Triangle.area(this._prev._pt, this._pt, this._next._pt))
  95. }
  96. remove() {
  97. const tmpPrev = this._prev
  98. const tmpNext = this._next
  99. let result = null
  100. if (this._prev !== null) {
  101. this._prev.setNext(tmpNext)
  102. this._prev.updateArea()
  103. result = this._prev
  104. }
  105. if (this._next !== null) {
  106. this._next.setPrev(tmpPrev)
  107. this._next.updateArea()
  108. if (result === null) result = this._next
  109. }
  110. this._isLive = false
  111. return result
  112. }
  113. isLive() {
  114. return this._isLive
  115. }
  116. setPrev(prev) {
  117. this._prev = prev
  118. }
  119. setNext(next) {
  120. this._next = next
  121. }
  122. }
  123. VWVertex.MAX_AREA = Double.MAX_VALUE
  124. VWLineSimplifier.VWVertex = VWVertex