OrientedBoundingRect.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import Point from './Point.js';
  2. import { createIntersectContext } from './BoundingRect.js';
  3. var mathMin = Math.min;
  4. var mathMax = Math.max;
  5. var mathAbs = Math.abs;
  6. var _extent = [0, 0];
  7. var _extent2 = [0, 0];
  8. var _intersectCtx = createIntersectContext();
  9. var _minTv = _intersectCtx.minTv;
  10. var _maxTv = _intersectCtx.maxTv;
  11. var OrientedBoundingRect = (function () {
  12. function OrientedBoundingRect(rect, transform) {
  13. this._corners = [];
  14. this._axes = [];
  15. this._origin = [0, 0];
  16. for (var i = 0; i < 4; i++) {
  17. this._corners[i] = new Point();
  18. }
  19. for (var i = 0; i < 2; i++) {
  20. this._axes[i] = new Point();
  21. }
  22. if (rect) {
  23. this.fromBoundingRect(rect, transform);
  24. }
  25. }
  26. OrientedBoundingRect.prototype.fromBoundingRect = function (rect, transform) {
  27. var corners = this._corners;
  28. var axes = this._axes;
  29. var x = rect.x;
  30. var y = rect.y;
  31. var x2 = x + rect.width;
  32. var y2 = y + rect.height;
  33. corners[0].set(x, y);
  34. corners[1].set(x2, y);
  35. corners[2].set(x2, y2);
  36. corners[3].set(x, y2);
  37. if (transform) {
  38. for (var i = 0; i < 4; i++) {
  39. corners[i].transform(transform);
  40. }
  41. }
  42. Point.sub(axes[0], corners[1], corners[0]);
  43. Point.sub(axes[1], corners[3], corners[0]);
  44. axes[0].normalize();
  45. axes[1].normalize();
  46. for (var i = 0; i < 2; i++) {
  47. this._origin[i] = axes[i].dot(corners[0]);
  48. }
  49. };
  50. OrientedBoundingRect.prototype.intersect = function (other, mtv, opt) {
  51. var overlapped = true;
  52. var noMtv = !mtv;
  53. if (mtv) {
  54. Point.set(mtv, 0, 0);
  55. }
  56. _intersectCtx.reset(opt, !noMtv);
  57. if (!this._intersectCheckOneSide(this, other, noMtv, 1)) {
  58. overlapped = false;
  59. if (noMtv) {
  60. return overlapped;
  61. }
  62. }
  63. if (!this._intersectCheckOneSide(other, this, noMtv, -1)) {
  64. overlapped = false;
  65. if (noMtv) {
  66. return overlapped;
  67. }
  68. }
  69. if (!noMtv && !_intersectCtx.negativeSize) {
  70. Point.copy(mtv, overlapped
  71. ? (_intersectCtx.useDir ? _intersectCtx.dirMinTv : _minTv)
  72. : _maxTv);
  73. }
  74. return overlapped;
  75. };
  76. OrientedBoundingRect.prototype._intersectCheckOneSide = function (self, other, noMtv, inverse) {
  77. var overlapped = true;
  78. for (var i = 0; i < 2; i++) {
  79. var axis = self._axes[i];
  80. self._getProjMinMaxOnAxis(i, self._corners, _extent);
  81. self._getProjMinMaxOnAxis(i, other._corners, _extent2);
  82. if (_intersectCtx.negativeSize || _extent[1] < _extent2[0] || _extent[0] > _extent2[1]) {
  83. overlapped = false;
  84. if (_intersectCtx.negativeSize || noMtv) {
  85. return overlapped;
  86. }
  87. var dist0 = mathAbs(_extent2[0] - _extent[1]);
  88. var dist1 = mathAbs(_extent[0] - _extent2[1]);
  89. if (mathMin(dist0, dist1) > _maxTv.len()) {
  90. if (dist0 < dist1) {
  91. Point.scale(_maxTv, axis, -dist0 * inverse);
  92. }
  93. else {
  94. Point.scale(_maxTv, axis, dist1 * inverse);
  95. }
  96. }
  97. }
  98. else if (!noMtv) {
  99. var dist0 = mathAbs(_extent2[0] - _extent[1]);
  100. var dist1 = mathAbs(_extent[0] - _extent2[1]);
  101. if (_intersectCtx.useDir || mathMin(dist0, dist1) < _minTv.len()) {
  102. if (dist0 < dist1 || !_intersectCtx.bidirectional) {
  103. Point.scale(_minTv, axis, dist0 * inverse);
  104. if (_intersectCtx.useDir) {
  105. _intersectCtx.calcDirMTV();
  106. }
  107. }
  108. if (dist0 >= dist1 || !_intersectCtx.bidirectional) {
  109. Point.scale(_minTv, axis, -dist1 * inverse);
  110. if (_intersectCtx.useDir) {
  111. _intersectCtx.calcDirMTV();
  112. }
  113. }
  114. }
  115. }
  116. }
  117. return overlapped;
  118. };
  119. OrientedBoundingRect.prototype._getProjMinMaxOnAxis = function (dim, corners, out) {
  120. var axis = this._axes[dim];
  121. var origin = this._origin;
  122. var proj = corners[0].dot(axis) + origin[dim];
  123. var min = proj;
  124. var max = proj;
  125. for (var i = 1; i < corners.length; i++) {
  126. var proj_1 = corners[i].dot(axis) + origin[dim];
  127. min = mathMin(proj_1, min);
  128. max = mathMax(proj_1, max);
  129. }
  130. out[0] = min + _intersectCtx.touchThreshold;
  131. out[1] = max - _intersectCtx.touchThreshold;
  132. _intersectCtx.negativeSize = out[1] < out[0];
  133. };
  134. return OrientedBoundingRect;
  135. }());
  136. export default OrientedBoundingRect;