AxisAlignedBoundingBox.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import Cartesian3 from "./Cartesian3.js";
  2. import Check from "./Check.js";
  3. import defaultValue from "./defaultValue.js";
  4. import defined from "./defined.js";
  5. import Intersect from "./Intersect.js";
  6. /**
  7. * Creates an instance of an AxisAlignedBoundingBox from the minimum and maximum points along the x, y, and z axes.
  8. * @alias AxisAlignedBoundingBox
  9. * @constructor
  10. *
  11. * @param {Cartesian3} [minimum=Cartesian3.ZERO] The minimum point along the x, y, and z axes.
  12. * @param {Cartesian3} [maximum=Cartesian3.ZERO] The maximum point along the x, y, and z axes.
  13. * @param {Cartesian3} [center] The center of the box; automatically computed if not supplied.
  14. *
  15. * @see BoundingSphere
  16. * @see BoundingRectangle
  17. */
  18. function AxisAlignedBoundingBox(minimum, maximum, center) {
  19. /**
  20. * The minimum point defining the bounding box.
  21. * @type {Cartesian3}
  22. * @default {@link Cartesian3.ZERO}
  23. */
  24. this.minimum = Cartesian3.clone(defaultValue(minimum, Cartesian3.ZERO));
  25. /**
  26. * The maximum point defining the bounding box.
  27. * @type {Cartesian3}
  28. * @default {@link Cartesian3.ZERO}
  29. */
  30. this.maximum = Cartesian3.clone(defaultValue(maximum, Cartesian3.ZERO));
  31. // If center was not defined, compute it.
  32. if (!defined(center)) {
  33. center = Cartesian3.midpoint(this.minimum, this.maximum, new Cartesian3());
  34. } else {
  35. center = Cartesian3.clone(center);
  36. }
  37. /**
  38. * The center point of the bounding box.
  39. * @type {Cartesian3}
  40. */
  41. this.center = center;
  42. }
  43. /**
  44. * Creates an instance of an AxisAlignedBoundingBox from its corners.
  45. *
  46. * @param {Cartesian3} minimum The minimum point along the x, y, and z axes.
  47. * @param {Cartesian3} maximum The maximum point along the x, y, and z axes.
  48. * @param {AxisAlignedBoundingBox} [result] The object onto which to store the result.
  49. * @returns {AxisAlignedBoundingBox} The modified result parameter or a new AxisAlignedBoundingBox instance if one was not provided.
  50. *
  51. * @example
  52. * // Compute an axis aligned bounding box from the two corners.
  53. * const box = Cesium.AxisAlignedBoundingBox.fromCorners(new Cesium.Cartesian3(-1, -1, -1), new Cesium.Cartesian3(1, 1, 1));
  54. */
  55. AxisAlignedBoundingBox.fromCorners = function (minimum, maximum, result) {
  56. //>>includeStart('debug', pragmas.debug);
  57. Check.defined("minimum", minimum);
  58. Check.defined("maximum", maximum);
  59. //>>includeEnd('debug');
  60. if (!defined(result)) {
  61. result = new AxisAlignedBoundingBox();
  62. }
  63. result.minimum = Cartesian3.clone(minimum, result.minimum);
  64. result.maximum = Cartesian3.clone(maximum, result.maximum);
  65. result.center = Cartesian3.midpoint(minimum, maximum, result.center);
  66. return result;
  67. };
  68. /**
  69. * Computes an instance of an AxisAlignedBoundingBox. The box is determined by
  70. * finding the points spaced the farthest apart on the x, y, and z axes.
  71. *
  72. * @param {Cartesian3[]} positions List of points that the bounding box will enclose. Each point must have a <code>x</code>, <code>y</code>, and <code>z</code> properties.
  73. * @param {AxisAlignedBoundingBox} [result] The object onto which to store the result.
  74. * @returns {AxisAlignedBoundingBox} The modified result parameter or a new AxisAlignedBoundingBox instance if one was not provided.
  75. *
  76. * @example
  77. * // Compute an axis aligned bounding box enclosing two points.
  78. * const box = Cesium.AxisAlignedBoundingBox.fromPoints([new Cesium.Cartesian3(2, 0, 0), new Cesium.Cartesian3(-2, 0, 0)]);
  79. */
  80. AxisAlignedBoundingBox.fromPoints = function (positions, result) {
  81. if (!defined(result)) {
  82. result = new AxisAlignedBoundingBox();
  83. }
  84. if (!defined(positions) || positions.length === 0) {
  85. result.minimum = Cartesian3.clone(Cartesian3.ZERO, result.minimum);
  86. result.maximum = Cartesian3.clone(Cartesian3.ZERO, result.maximum);
  87. result.center = Cartesian3.clone(Cartesian3.ZERO, result.center);
  88. return result;
  89. }
  90. let minimumX = positions[0].x;
  91. let minimumY = positions[0].y;
  92. let minimumZ = positions[0].z;
  93. let maximumX = positions[0].x;
  94. let maximumY = positions[0].y;
  95. let maximumZ = positions[0].z;
  96. const length = positions.length;
  97. for (let i = 1; i < length; i++) {
  98. const p = positions[i];
  99. const x = p.x;
  100. const y = p.y;
  101. const z = p.z;
  102. minimumX = Math.min(x, minimumX);
  103. maximumX = Math.max(x, maximumX);
  104. minimumY = Math.min(y, minimumY);
  105. maximumY = Math.max(y, maximumY);
  106. minimumZ = Math.min(z, minimumZ);
  107. maximumZ = Math.max(z, maximumZ);
  108. }
  109. const minimum = result.minimum;
  110. minimum.x = minimumX;
  111. minimum.y = minimumY;
  112. minimum.z = minimumZ;
  113. const maximum = result.maximum;
  114. maximum.x = maximumX;
  115. maximum.y = maximumY;
  116. maximum.z = maximumZ;
  117. result.center = Cartesian3.midpoint(minimum, maximum, result.center);
  118. return result;
  119. };
  120. /**
  121. * Duplicates a AxisAlignedBoundingBox instance.
  122. *
  123. * @param {AxisAlignedBoundingBox} box The bounding box to duplicate.
  124. * @param {AxisAlignedBoundingBox} [result] The object onto which to store the result.
  125. * @returns {AxisAlignedBoundingBox} The modified result parameter or a new AxisAlignedBoundingBox instance if none was provided. (Returns undefined if box is undefined)
  126. */
  127. AxisAlignedBoundingBox.clone = function (box, result) {
  128. if (!defined(box)) {
  129. return undefined;
  130. }
  131. if (!defined(result)) {
  132. return new AxisAlignedBoundingBox(box.minimum, box.maximum, box.center);
  133. }
  134. result.minimum = Cartesian3.clone(box.minimum, result.minimum);
  135. result.maximum = Cartesian3.clone(box.maximum, result.maximum);
  136. result.center = Cartesian3.clone(box.center, result.center);
  137. return result;
  138. };
  139. /**
  140. * Compares the provided AxisAlignedBoundingBox componentwise and returns
  141. * <code>true</code> if they are equal, <code>false</code> otherwise.
  142. *
  143. * @param {AxisAlignedBoundingBox} [left] The first AxisAlignedBoundingBox.
  144. * @param {AxisAlignedBoundingBox} [right] The second AxisAlignedBoundingBox.
  145. * @returns {boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
  146. */
  147. AxisAlignedBoundingBox.equals = function (left, right) {
  148. return (
  149. left === right ||
  150. (defined(left) &&
  151. defined(right) &&
  152. Cartesian3.equals(left.center, right.center) &&
  153. Cartesian3.equals(left.minimum, right.minimum) &&
  154. Cartesian3.equals(left.maximum, right.maximum))
  155. );
  156. };
  157. let intersectScratch = new Cartesian3();
  158. /**
  159. * Determines which side of a plane a box is located.
  160. *
  161. * @param {AxisAlignedBoundingBox} box The bounding box to test.
  162. * @param {Plane} plane The plane to test against.
  163. * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane
  164. * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is
  165. * on the opposite side, and {@link Intersect.INTERSECTING} if the box
  166. * intersects the plane.
  167. */
  168. AxisAlignedBoundingBox.intersectPlane = function (box, plane) {
  169. //>>includeStart('debug', pragmas.debug);
  170. Check.defined("box", box);
  171. Check.defined("plane", plane);
  172. //>>includeEnd('debug');
  173. intersectScratch = Cartesian3.subtract(
  174. box.maximum,
  175. box.minimum,
  176. intersectScratch
  177. );
  178. const h = Cartesian3.multiplyByScalar(
  179. intersectScratch,
  180. 0.5,
  181. intersectScratch
  182. ); //The positive half diagonal
  183. const normal = plane.normal;
  184. const e =
  185. h.x * Math.abs(normal.x) +
  186. h.y * Math.abs(normal.y) +
  187. h.z * Math.abs(normal.z);
  188. const s = Cartesian3.dot(box.center, normal) + plane.distance; //signed distance from center
  189. if (s - e > 0) {
  190. return Intersect.INSIDE;
  191. }
  192. if (s + e < 0) {
  193. //Not in front because normals point inward
  194. return Intersect.OUTSIDE;
  195. }
  196. return Intersect.INTERSECTING;
  197. };
  198. /**
  199. * Duplicates this AxisAlignedBoundingBox instance.
  200. *
  201. * @param {AxisAlignedBoundingBox} [result] The object onto which to store the result.
  202. * @returns {AxisAlignedBoundingBox} The modified result parameter or a new AxisAlignedBoundingBox instance if one was not provided.
  203. */
  204. AxisAlignedBoundingBox.prototype.clone = function (result) {
  205. return AxisAlignedBoundingBox.clone(this, result);
  206. };
  207. /**
  208. * Determines which side of a plane this box is located.
  209. *
  210. * @param {Plane} plane The plane to test against.
  211. * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane
  212. * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is
  213. * on the opposite side, and {@link Intersect.INTERSECTING} if the box
  214. * intersects the plane.
  215. */
  216. AxisAlignedBoundingBox.prototype.intersectPlane = function (plane) {
  217. return AxisAlignedBoundingBox.intersectPlane(this, plane);
  218. };
  219. /**
  220. * Compares this AxisAlignedBoundingBox against the provided AxisAlignedBoundingBox componentwise and returns
  221. * <code>true</code> if they are equal, <code>false</code> otherwise.
  222. *
  223. * @param {AxisAlignedBoundingBox} [right] The right hand side AxisAlignedBoundingBox.
  224. * @returns {boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
  225. */
  226. AxisAlignedBoundingBox.prototype.equals = function (right) {
  227. return AxisAlignedBoundingBox.equals(this, right);
  228. };
  229. export default AxisAlignedBoundingBox;