OrientedBoundingRect.js 4.1 KB

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