HotPixel.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import Coordinate from '../../geom/Coordinate'
  2. import IllegalArgumentException from '../../../../../java/lang/IllegalArgumentException'
  3. import Envelope from '../../geom/Envelope'
  4. import Assert from '../../util/Assert'
  5. export default class HotPixel {
  6. constructor() {
  7. HotPixel.constructor_.apply(this, arguments)
  8. }
  9. static constructor_() {
  10. this._li = null
  11. this._pt = null
  12. this._originalPt = null
  13. this._ptScaled = null
  14. this._p0Scaled = null
  15. this._p1Scaled = null
  16. this._scaleFactor = null
  17. this._minx = null
  18. this._maxx = null
  19. this._miny = null
  20. this._maxy = null
  21. this._corner = new Array(4).fill(null)
  22. this._safeEnv = null
  23. const pt = arguments[0], scaleFactor = arguments[1], li = arguments[2]
  24. this._originalPt = pt
  25. this._pt = pt
  26. this._scaleFactor = scaleFactor
  27. this._li = li
  28. if (scaleFactor <= 0) throw new IllegalArgumentException('Scale factor must be non-zero')
  29. if (scaleFactor !== 1.0) {
  30. this._pt = new Coordinate(this.scale(pt.x), this.scale(pt.y))
  31. this._p0Scaled = new Coordinate()
  32. this._p1Scaled = new Coordinate()
  33. }
  34. this.initCorners(this._pt)
  35. }
  36. intersectsScaled(p0, p1) {
  37. const segMinx = Math.min(p0.x, p1.x)
  38. const segMaxx = Math.max(p0.x, p1.x)
  39. const segMiny = Math.min(p0.y, p1.y)
  40. const segMaxy = Math.max(p0.y, p1.y)
  41. const isOutsidePixelEnv = this._maxx < segMinx || this._minx > segMaxx || this._maxy < segMiny || this._miny > segMaxy
  42. if (isOutsidePixelEnv) return false
  43. const intersects = this.intersectsToleranceSquare(p0, p1)
  44. Assert.isTrue(!(isOutsidePixelEnv && intersects), 'Found bad envelope test')
  45. return intersects
  46. }
  47. initCorners(pt) {
  48. const tolerance = 0.5
  49. this._minx = pt.x - tolerance
  50. this._maxx = pt.x + tolerance
  51. this._miny = pt.y - tolerance
  52. this._maxy = pt.y + tolerance
  53. this._corner[0] = new Coordinate(this._maxx, this._maxy)
  54. this._corner[1] = new Coordinate(this._minx, this._maxy)
  55. this._corner[2] = new Coordinate(this._minx, this._miny)
  56. this._corner[3] = new Coordinate(this._maxx, this._miny)
  57. }
  58. intersects(p0, p1) {
  59. if (this._scaleFactor === 1.0) return this.intersectsScaled(p0, p1)
  60. this.copyScaled(p0, this._p0Scaled)
  61. this.copyScaled(p1, this._p1Scaled)
  62. return this.intersectsScaled(this._p0Scaled, this._p1Scaled)
  63. }
  64. scale(val) {
  65. return Math.round(val * this._scaleFactor)
  66. }
  67. getCoordinate() {
  68. return this._originalPt
  69. }
  70. copyScaled(p, pScaled) {
  71. pScaled.x = this.scale(p.x)
  72. pScaled.y = this.scale(p.y)
  73. }
  74. getSafeEnvelope() {
  75. if (this._safeEnv === null) {
  76. const safeTolerance = HotPixel.SAFE_ENV_EXPANSION_FACTOR / this._scaleFactor
  77. this._safeEnv = new Envelope(this._originalPt.x - safeTolerance, this._originalPt.x + safeTolerance, this._originalPt.y - safeTolerance, this._originalPt.y + safeTolerance)
  78. }
  79. return this._safeEnv
  80. }
  81. intersectsPixelClosure(p0, p1) {
  82. this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1])
  83. if (this._li.hasIntersection()) return true
  84. this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2])
  85. if (this._li.hasIntersection()) return true
  86. this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3])
  87. if (this._li.hasIntersection()) return true
  88. this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0])
  89. if (this._li.hasIntersection()) return true
  90. return false
  91. }
  92. intersectsToleranceSquare(p0, p1) {
  93. let intersectsLeft = false
  94. let intersectsBottom = false
  95. this._li.computeIntersection(p0, p1, this._corner[0], this._corner[1])
  96. if (this._li.isProper()) return true
  97. this._li.computeIntersection(p0, p1, this._corner[1], this._corner[2])
  98. if (this._li.isProper()) return true
  99. if (this._li.hasIntersection()) intersectsLeft = true
  100. this._li.computeIntersection(p0, p1, this._corner[2], this._corner[3])
  101. if (this._li.isProper()) return true
  102. if (this._li.hasIntersection()) intersectsBottom = true
  103. this._li.computeIntersection(p0, p1, this._corner[3], this._corner[0])
  104. if (this._li.isProper()) return true
  105. if (intersectsLeft && intersectsBottom) return true
  106. if (p0.equals(this._pt)) return true
  107. if (p1.equals(this._pt)) return true
  108. return false
  109. }
  110. addSnappedNode(segStr, segIndex) {
  111. const p0 = segStr.getCoordinate(segIndex)
  112. const p1 = segStr.getCoordinate(segIndex + 1)
  113. if (this.intersects(p0, p1)) {
  114. segStr.addIntersection(this.getCoordinate(), segIndex)
  115. return true
  116. }
  117. return false
  118. }
  119. }
  120. HotPixel.SAFE_ENV_EXPANSION_FACTOR = 0.75