MonotoneChain.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import Envelope from '../../geom/Envelope'
  2. export default class MonotoneChain {
  3. constructor() {
  4. MonotoneChain.constructor_.apply(this, arguments)
  5. }
  6. static constructor_() {
  7. this._pts = null
  8. this._start = null
  9. this._end = null
  10. this._env = null
  11. this._context = null
  12. this._id = null
  13. const pts = arguments[0], start = arguments[1], end = arguments[2], context = arguments[3]
  14. this._pts = pts
  15. this._start = start
  16. this._end = end
  17. this._context = context
  18. }
  19. getLineSegment(index, ls) {
  20. ls.p0 = this._pts[index]
  21. ls.p1 = this._pts[index + 1]
  22. }
  23. computeSelect(searchEnv, start0, end0, mcs) {
  24. const p0 = this._pts[start0]
  25. const p1 = this._pts[end0]
  26. if (end0 - start0 === 1) {
  27. mcs.select(this, start0)
  28. return null
  29. }
  30. if (!searchEnv.intersects(p0, p1)) return null
  31. const mid = Math.trunc((start0 + end0) / 2)
  32. if (start0 < mid)
  33. this.computeSelect(searchEnv, start0, mid, mcs)
  34. if (mid < end0)
  35. this.computeSelect(searchEnv, mid, end0, mcs)
  36. }
  37. getCoordinates() {
  38. const coord = new Array(this._end - this._start + 1).fill(null)
  39. let index = 0
  40. for (let i = this._start; i <= this._end; i++)
  41. coord[index++] = this._pts[i]
  42. return coord
  43. }
  44. computeOverlaps() {
  45. if (arguments.length === 2) {
  46. const mc = arguments[0], mco = arguments[1]
  47. this.computeOverlaps(this._start, this._end, mc, mc._start, mc._end, mco)
  48. } else if (arguments.length === 6) {
  49. const start0 = arguments[0], end0 = arguments[1], mc = arguments[2], start1 = arguments[3], end1 = arguments[4], mco = arguments[5]
  50. if (end0 - start0 === 1 && end1 - start1 === 1) {
  51. mco.overlap(this, start0, mc, start1)
  52. return null
  53. }
  54. if (!this.overlaps(start0, end0, mc, start1, end1)) return null
  55. const mid0 = Math.trunc((start0 + end0) / 2)
  56. const mid1 = Math.trunc((start1 + end1) / 2)
  57. if (start0 < mid0) {
  58. if (start1 < mid1) this.computeOverlaps(start0, mid0, mc, start1, mid1, mco)
  59. if (mid1 < end1) this.computeOverlaps(start0, mid0, mc, mid1, end1, mco)
  60. }
  61. if (mid0 < end0) {
  62. if (start1 < mid1) this.computeOverlaps(mid0, end0, mc, start1, mid1, mco)
  63. if (mid1 < end1) this.computeOverlaps(mid0, end0, mc, mid1, end1, mco)
  64. }
  65. }
  66. }
  67. setId(id) {
  68. this._id = id
  69. }
  70. select(searchEnv, mcs) {
  71. this.computeSelect(searchEnv, this._start, this._end, mcs)
  72. }
  73. getEnvelope() {
  74. if (this._env === null) {
  75. const p0 = this._pts[this._start]
  76. const p1 = this._pts[this._end]
  77. this._env = new Envelope(p0, p1)
  78. }
  79. return this._env
  80. }
  81. overlaps(start0, end0, mc, start1, end1) {
  82. return Envelope.intersects(this._pts[start0], this._pts[end0], mc._pts[start1], mc._pts[end1])
  83. }
  84. getEndIndex() {
  85. return this._end
  86. }
  87. getStartIndex() {
  88. return this._start
  89. }
  90. getContext() {
  91. return this._context
  92. }
  93. getId() {
  94. return this._id
  95. }
  96. }