OrientedBoundingBox-a82b3552.js 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283
  1. /**
  2. * @license
  3. * Cesium - https://github.com/CesiumGS/cesium
  4. * Version 1.95
  5. *
  6. * Copyright 2011-2022 Cesium Contributors
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. *
  20. * Columbus View (Pat. Pend.)
  21. *
  22. * Portions licensed separately.
  23. * See https://github.com/CesiumGS/cesium/blob/main/LICENSE.md for full licensing details.
  24. */
  25. define(['exports', './Transforms-273eeb44', './Matrix2-9e1c22e2', './RuntimeError-4f8ec8a2', './defaultValue-97284df2', './EllipsoidTangentPlane-d42ee682', './ComponentDatatype-4eeb6d9b', './Plane-76b84425'], (function (exports, Transforms, Matrix2, RuntimeError, defaultValue, EllipsoidTangentPlane, ComponentDatatype, Plane) { 'use strict';
  26. /**
  27. * Creates an instance of an OrientedBoundingBox.
  28. * An OrientedBoundingBox of some object is a closed and convex cuboid. It can provide a tighter bounding volume than {@link BoundingSphere} or {@link AxisAlignedBoundingBox} in many cases.
  29. * @alias OrientedBoundingBox
  30. * @constructor
  31. *
  32. * @param {Cartesian3} [center=Cartesian3.ZERO] The center of the box.
  33. * @param {Matrix3} [halfAxes=Matrix3.ZERO] The three orthogonal half-axes of the bounding box.
  34. * Equivalently, the transformation matrix, to rotate and scale a 0x0x0
  35. * cube centered at the origin.
  36. *
  37. *
  38. * @example
  39. * // Create an OrientedBoundingBox using a transformation matrix, a position where the box will be translated, and a scale.
  40. * const center = new Cesium.Cartesian3(1.0, 0.0, 0.0);
  41. * const halfAxes = Cesium.Matrix3.fromScale(new Cesium.Cartesian3(1.0, 3.0, 2.0), new Cesium.Matrix3());
  42. *
  43. * const obb = new Cesium.OrientedBoundingBox(center, halfAxes);
  44. *
  45. * @see BoundingSphere
  46. * @see BoundingRectangle
  47. */
  48. function OrientedBoundingBox(center, halfAxes) {
  49. /**
  50. * The center of the box.
  51. * @type {Cartesian3}
  52. * @default {@link Cartesian3.ZERO}
  53. */
  54. this.center = Matrix2.Cartesian3.clone(defaultValue.defaultValue(center, Matrix2.Cartesian3.ZERO));
  55. /**
  56. * The transformation matrix, to rotate the box to the right position.
  57. * @type {Matrix3}
  58. * @default {@link Matrix3.ZERO}
  59. */
  60. this.halfAxes = Matrix2.Matrix3.clone(defaultValue.defaultValue(halfAxes, Matrix2.Matrix3.ZERO));
  61. }
  62. /**
  63. * The number of elements used to pack the object into an array.
  64. * @type {Number}
  65. */
  66. OrientedBoundingBox.packedLength =
  67. Matrix2.Cartesian3.packedLength + Matrix2.Matrix3.packedLength;
  68. /**
  69. * Stores the provided instance into the provided array.
  70. *
  71. * @param {OrientedBoundingBox} value The value to pack.
  72. * @param {Number[]} array The array to pack into.
  73. * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.
  74. *
  75. * @returns {Number[]} The array that was packed into
  76. */
  77. OrientedBoundingBox.pack = function (value, array, startingIndex) {
  78. //>>includeStart('debug', pragmas.debug);
  79. RuntimeError.Check.typeOf.object("value", value);
  80. RuntimeError.Check.defined("array", array);
  81. //>>includeEnd('debug');
  82. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  83. Matrix2.Cartesian3.pack(value.center, array, startingIndex);
  84. Matrix2.Matrix3.pack(value.halfAxes, array, startingIndex + Matrix2.Cartesian3.packedLength);
  85. return array;
  86. };
  87. /**
  88. * Retrieves an instance from a packed array.
  89. *
  90. * @param {Number[]} array The packed array.
  91. * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.
  92. * @param {OrientedBoundingBox} [result] The object into which to store the result.
  93. * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if one was not provided.
  94. */
  95. OrientedBoundingBox.unpack = function (array, startingIndex, result) {
  96. //>>includeStart('debug', pragmas.debug);
  97. RuntimeError.Check.defined("array", array);
  98. //>>includeEnd('debug');
  99. startingIndex = defaultValue.defaultValue(startingIndex, 0);
  100. if (!defaultValue.defined(result)) {
  101. result = new OrientedBoundingBox();
  102. }
  103. Matrix2.Cartesian3.unpack(array, startingIndex, result.center);
  104. Matrix2.Matrix3.unpack(
  105. array,
  106. startingIndex + Matrix2.Cartesian3.packedLength,
  107. result.halfAxes
  108. );
  109. return result;
  110. };
  111. const scratchCartesian1 = new Matrix2.Cartesian3();
  112. const scratchCartesian2 = new Matrix2.Cartesian3();
  113. const scratchCartesian3 = new Matrix2.Cartesian3();
  114. const scratchCartesian4 = new Matrix2.Cartesian3();
  115. const scratchCartesian5 = new Matrix2.Cartesian3();
  116. const scratchCartesian6 = new Matrix2.Cartesian3();
  117. const scratchCovarianceResult = new Matrix2.Matrix3();
  118. const scratchEigenResult = {
  119. unitary: new Matrix2.Matrix3(),
  120. diagonal: new Matrix2.Matrix3(),
  121. };
  122. /**
  123. * Computes an instance of an OrientedBoundingBox of the given positions.
  124. * This is an implementation of Stefan Gottschalk's Collision Queries using Oriented Bounding Boxes solution (PHD thesis).
  125. * Reference: http://gamma.cs.unc.edu/users/gottschalk/main.pdf
  126. *
  127. * @param {Cartesian3[]} [positions] List of {@link Cartesian3} points that the bounding box will enclose.
  128. * @param {OrientedBoundingBox} [result] The object onto which to store the result.
  129. * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if one was not provided.
  130. *
  131. * @example
  132. * // Compute an object oriented bounding box enclosing two points.
  133. * const box = Cesium.OrientedBoundingBox.fromPoints([new Cesium.Cartesian3(2, 0, 0), new Cesium.Cartesian3(-2, 0, 0)]);
  134. */
  135. OrientedBoundingBox.fromPoints = function (positions, result) {
  136. if (!defaultValue.defined(result)) {
  137. result = new OrientedBoundingBox();
  138. }
  139. if (!defaultValue.defined(positions) || positions.length === 0) {
  140. result.halfAxes = Matrix2.Matrix3.ZERO;
  141. result.center = Matrix2.Cartesian3.ZERO;
  142. return result;
  143. }
  144. let i;
  145. const length = positions.length;
  146. const meanPoint = Matrix2.Cartesian3.clone(positions[0], scratchCartesian1);
  147. for (i = 1; i < length; i++) {
  148. Matrix2.Cartesian3.add(meanPoint, positions[i], meanPoint);
  149. }
  150. const invLength = 1.0 / length;
  151. Matrix2.Cartesian3.multiplyByScalar(meanPoint, invLength, meanPoint);
  152. let exx = 0.0;
  153. let exy = 0.0;
  154. let exz = 0.0;
  155. let eyy = 0.0;
  156. let eyz = 0.0;
  157. let ezz = 0.0;
  158. let p;
  159. for (i = 0; i < length; i++) {
  160. p = Matrix2.Cartesian3.subtract(positions[i], meanPoint, scratchCartesian2);
  161. exx += p.x * p.x;
  162. exy += p.x * p.y;
  163. exz += p.x * p.z;
  164. eyy += p.y * p.y;
  165. eyz += p.y * p.z;
  166. ezz += p.z * p.z;
  167. }
  168. exx *= invLength;
  169. exy *= invLength;
  170. exz *= invLength;
  171. eyy *= invLength;
  172. eyz *= invLength;
  173. ezz *= invLength;
  174. const covarianceMatrix = scratchCovarianceResult;
  175. covarianceMatrix[0] = exx;
  176. covarianceMatrix[1] = exy;
  177. covarianceMatrix[2] = exz;
  178. covarianceMatrix[3] = exy;
  179. covarianceMatrix[4] = eyy;
  180. covarianceMatrix[5] = eyz;
  181. covarianceMatrix[6] = exz;
  182. covarianceMatrix[7] = eyz;
  183. covarianceMatrix[8] = ezz;
  184. const eigenDecomposition = Matrix2.Matrix3.computeEigenDecomposition(
  185. covarianceMatrix,
  186. scratchEigenResult
  187. );
  188. const rotation = Matrix2.Matrix3.clone(eigenDecomposition.unitary, result.halfAxes);
  189. let v1 = Matrix2.Matrix3.getColumn(rotation, 0, scratchCartesian4);
  190. let v2 = Matrix2.Matrix3.getColumn(rotation, 1, scratchCartesian5);
  191. let v3 = Matrix2.Matrix3.getColumn(rotation, 2, scratchCartesian6);
  192. let u1 = -Number.MAX_VALUE;
  193. let u2 = -Number.MAX_VALUE;
  194. let u3 = -Number.MAX_VALUE;
  195. let l1 = Number.MAX_VALUE;
  196. let l2 = Number.MAX_VALUE;
  197. let l3 = Number.MAX_VALUE;
  198. for (i = 0; i < length; i++) {
  199. p = positions[i];
  200. u1 = Math.max(Matrix2.Cartesian3.dot(v1, p), u1);
  201. u2 = Math.max(Matrix2.Cartesian3.dot(v2, p), u2);
  202. u3 = Math.max(Matrix2.Cartesian3.dot(v3, p), u3);
  203. l1 = Math.min(Matrix2.Cartesian3.dot(v1, p), l1);
  204. l2 = Math.min(Matrix2.Cartesian3.dot(v2, p), l2);
  205. l3 = Math.min(Matrix2.Cartesian3.dot(v3, p), l3);
  206. }
  207. v1 = Matrix2.Cartesian3.multiplyByScalar(v1, 0.5 * (l1 + u1), v1);
  208. v2 = Matrix2.Cartesian3.multiplyByScalar(v2, 0.5 * (l2 + u2), v2);
  209. v3 = Matrix2.Cartesian3.multiplyByScalar(v3, 0.5 * (l3 + u3), v3);
  210. const center = Matrix2.Cartesian3.add(v1, v2, result.center);
  211. Matrix2.Cartesian3.add(center, v3, center);
  212. const scale = scratchCartesian3;
  213. scale.x = u1 - l1;
  214. scale.y = u2 - l2;
  215. scale.z = u3 - l3;
  216. Matrix2.Cartesian3.multiplyByScalar(scale, 0.5, scale);
  217. Matrix2.Matrix3.multiplyByScale(result.halfAxes, scale, result.halfAxes);
  218. return result;
  219. };
  220. const scratchOffset = new Matrix2.Cartesian3();
  221. const scratchScale = new Matrix2.Cartesian3();
  222. function fromPlaneExtents(
  223. planeOrigin,
  224. planeXAxis,
  225. planeYAxis,
  226. planeZAxis,
  227. minimumX,
  228. maximumX,
  229. minimumY,
  230. maximumY,
  231. minimumZ,
  232. maximumZ,
  233. result
  234. ) {
  235. //>>includeStart('debug', pragmas.debug);
  236. if (
  237. !defaultValue.defined(minimumX) ||
  238. !defaultValue.defined(maximumX) ||
  239. !defaultValue.defined(minimumY) ||
  240. !defaultValue.defined(maximumY) ||
  241. !defaultValue.defined(minimumZ) ||
  242. !defaultValue.defined(maximumZ)
  243. ) {
  244. throw new RuntimeError.DeveloperError(
  245. "all extents (minimum/maximum X/Y/Z) are required."
  246. );
  247. }
  248. //>>includeEnd('debug');
  249. if (!defaultValue.defined(result)) {
  250. result = new OrientedBoundingBox();
  251. }
  252. const halfAxes = result.halfAxes;
  253. Matrix2.Matrix3.setColumn(halfAxes, 0, planeXAxis, halfAxes);
  254. Matrix2.Matrix3.setColumn(halfAxes, 1, planeYAxis, halfAxes);
  255. Matrix2.Matrix3.setColumn(halfAxes, 2, planeZAxis, halfAxes);
  256. let centerOffset = scratchOffset;
  257. centerOffset.x = (minimumX + maximumX) / 2.0;
  258. centerOffset.y = (minimumY + maximumY) / 2.0;
  259. centerOffset.z = (minimumZ + maximumZ) / 2.0;
  260. const scale = scratchScale;
  261. scale.x = (maximumX - minimumX) / 2.0;
  262. scale.y = (maximumY - minimumY) / 2.0;
  263. scale.z = (maximumZ - minimumZ) / 2.0;
  264. const center = result.center;
  265. centerOffset = Matrix2.Matrix3.multiplyByVector(halfAxes, centerOffset, centerOffset);
  266. Matrix2.Cartesian3.add(planeOrigin, centerOffset, center);
  267. Matrix2.Matrix3.multiplyByScale(halfAxes, scale, halfAxes);
  268. return result;
  269. }
  270. const scratchRectangleCenterCartographic = new Matrix2.Cartographic();
  271. const scratchRectangleCenter = new Matrix2.Cartesian3();
  272. const scratchPerimeterCartographicNC = new Matrix2.Cartographic();
  273. const scratchPerimeterCartographicNW = new Matrix2.Cartographic();
  274. const scratchPerimeterCartographicCW = new Matrix2.Cartographic();
  275. const scratchPerimeterCartographicSW = new Matrix2.Cartographic();
  276. const scratchPerimeterCartographicSC = new Matrix2.Cartographic();
  277. const scratchPerimeterCartesianNC = new Matrix2.Cartesian3();
  278. const scratchPerimeterCartesianNW = new Matrix2.Cartesian3();
  279. const scratchPerimeterCartesianCW = new Matrix2.Cartesian3();
  280. const scratchPerimeterCartesianSW = new Matrix2.Cartesian3();
  281. const scratchPerimeterCartesianSC = new Matrix2.Cartesian3();
  282. const scratchPerimeterProjectedNC = new Matrix2.Cartesian2();
  283. const scratchPerimeterProjectedNW = new Matrix2.Cartesian2();
  284. const scratchPerimeterProjectedCW = new Matrix2.Cartesian2();
  285. const scratchPerimeterProjectedSW = new Matrix2.Cartesian2();
  286. const scratchPerimeterProjectedSC = new Matrix2.Cartesian2();
  287. const scratchPlaneOrigin = new Matrix2.Cartesian3();
  288. const scratchPlaneNormal = new Matrix2.Cartesian3();
  289. const scratchPlaneXAxis = new Matrix2.Cartesian3();
  290. const scratchHorizonCartesian = new Matrix2.Cartesian3();
  291. const scratchHorizonProjected = new Matrix2.Cartesian2();
  292. const scratchMaxY = new Matrix2.Cartesian3();
  293. const scratchMinY = new Matrix2.Cartesian3();
  294. const scratchZ = new Matrix2.Cartesian3();
  295. const scratchPlane = new Plane.Plane(Matrix2.Cartesian3.UNIT_X, 0.0);
  296. /**
  297. * Computes an OrientedBoundingBox that bounds a {@link Rectangle} on the surface of an {@link Ellipsoid}.
  298. * There are no guarantees about the orientation of the bounding box.
  299. *
  300. * @param {Rectangle} rectangle The cartographic rectangle on the surface of the ellipsoid.
  301. * @param {Number} [minimumHeight=0.0] The minimum height (elevation) within the tile.
  302. * @param {Number} [maximumHeight=0.0] The maximum height (elevation) within the tile.
  303. * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the rectangle is defined.
  304. * @param {OrientedBoundingBox} [result] The object onto which to store the result.
  305. * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if none was provided.
  306. *
  307. * @exception {DeveloperError} rectangle.width must be between 0 and pi.
  308. * @exception {DeveloperError} rectangle.height must be between 0 and pi.
  309. * @exception {DeveloperError} ellipsoid must be an ellipsoid of revolution (<code>radii.x == radii.y</code>)
  310. */
  311. OrientedBoundingBox.fromRectangle = function (
  312. rectangle,
  313. minimumHeight,
  314. maximumHeight,
  315. ellipsoid,
  316. result
  317. ) {
  318. //>>includeStart('debug', pragmas.debug);
  319. if (!defaultValue.defined(rectangle)) {
  320. throw new RuntimeError.DeveloperError("rectangle is required");
  321. }
  322. if (rectangle.width < 0.0 || rectangle.width > ComponentDatatype.CesiumMath.TWO_PI) {
  323. throw new RuntimeError.DeveloperError("Rectangle width must be between 0 and 2*pi");
  324. }
  325. if (rectangle.height < 0.0 || rectangle.height > ComponentDatatype.CesiumMath.PI) {
  326. throw new RuntimeError.DeveloperError("Rectangle height must be between 0 and pi");
  327. }
  328. if (
  329. defaultValue.defined(ellipsoid) &&
  330. !ComponentDatatype.CesiumMath.equalsEpsilon(
  331. ellipsoid.radii.x,
  332. ellipsoid.radii.y,
  333. ComponentDatatype.CesiumMath.EPSILON15
  334. )
  335. ) {
  336. throw new RuntimeError.DeveloperError(
  337. "Ellipsoid must be an ellipsoid of revolution (radii.x == radii.y)"
  338. );
  339. }
  340. //>>includeEnd('debug');
  341. minimumHeight = defaultValue.defaultValue(minimumHeight, 0.0);
  342. maximumHeight = defaultValue.defaultValue(maximumHeight, 0.0);
  343. ellipsoid = defaultValue.defaultValue(ellipsoid, Matrix2.Ellipsoid.WGS84);
  344. let minX, maxX, minY, maxY, minZ, maxZ, plane;
  345. if (rectangle.width <= ComponentDatatype.CesiumMath.PI) {
  346. // The bounding box will be aligned with the tangent plane at the center of the rectangle.
  347. const tangentPointCartographic = Matrix2.Rectangle.center(
  348. rectangle,
  349. scratchRectangleCenterCartographic
  350. );
  351. const tangentPoint = ellipsoid.cartographicToCartesian(
  352. tangentPointCartographic,
  353. scratchRectangleCenter
  354. );
  355. const tangentPlane = new EllipsoidTangentPlane.EllipsoidTangentPlane(tangentPoint, ellipsoid);
  356. plane = tangentPlane.plane;
  357. // If the rectangle spans the equator, CW is instead aligned with the equator (because it sticks out the farthest at the equator).
  358. const lonCenter = tangentPointCartographic.longitude;
  359. const latCenter =
  360. rectangle.south < 0.0 && rectangle.north > 0.0
  361. ? 0.0
  362. : tangentPointCartographic.latitude;
  363. // Compute XY extents using the rectangle at maximum height
  364. const perimeterCartographicNC = Matrix2.Cartographic.fromRadians(
  365. lonCenter,
  366. rectangle.north,
  367. maximumHeight,
  368. scratchPerimeterCartographicNC
  369. );
  370. const perimeterCartographicNW = Matrix2.Cartographic.fromRadians(
  371. rectangle.west,
  372. rectangle.north,
  373. maximumHeight,
  374. scratchPerimeterCartographicNW
  375. );
  376. const perimeterCartographicCW = Matrix2.Cartographic.fromRadians(
  377. rectangle.west,
  378. latCenter,
  379. maximumHeight,
  380. scratchPerimeterCartographicCW
  381. );
  382. const perimeterCartographicSW = Matrix2.Cartographic.fromRadians(
  383. rectangle.west,
  384. rectangle.south,
  385. maximumHeight,
  386. scratchPerimeterCartographicSW
  387. );
  388. const perimeterCartographicSC = Matrix2.Cartographic.fromRadians(
  389. lonCenter,
  390. rectangle.south,
  391. maximumHeight,
  392. scratchPerimeterCartographicSC
  393. );
  394. const perimeterCartesianNC = ellipsoid.cartographicToCartesian(
  395. perimeterCartographicNC,
  396. scratchPerimeterCartesianNC
  397. );
  398. let perimeterCartesianNW = ellipsoid.cartographicToCartesian(
  399. perimeterCartographicNW,
  400. scratchPerimeterCartesianNW
  401. );
  402. const perimeterCartesianCW = ellipsoid.cartographicToCartesian(
  403. perimeterCartographicCW,
  404. scratchPerimeterCartesianCW
  405. );
  406. let perimeterCartesianSW = ellipsoid.cartographicToCartesian(
  407. perimeterCartographicSW,
  408. scratchPerimeterCartesianSW
  409. );
  410. const perimeterCartesianSC = ellipsoid.cartographicToCartesian(
  411. perimeterCartographicSC,
  412. scratchPerimeterCartesianSC
  413. );
  414. const perimeterProjectedNC = tangentPlane.projectPointToNearestOnPlane(
  415. perimeterCartesianNC,
  416. scratchPerimeterProjectedNC
  417. );
  418. const perimeterProjectedNW = tangentPlane.projectPointToNearestOnPlane(
  419. perimeterCartesianNW,
  420. scratchPerimeterProjectedNW
  421. );
  422. const perimeterProjectedCW = tangentPlane.projectPointToNearestOnPlane(
  423. perimeterCartesianCW,
  424. scratchPerimeterProjectedCW
  425. );
  426. const perimeterProjectedSW = tangentPlane.projectPointToNearestOnPlane(
  427. perimeterCartesianSW,
  428. scratchPerimeterProjectedSW
  429. );
  430. const perimeterProjectedSC = tangentPlane.projectPointToNearestOnPlane(
  431. perimeterCartesianSC,
  432. scratchPerimeterProjectedSC
  433. );
  434. minX = Math.min(
  435. perimeterProjectedNW.x,
  436. perimeterProjectedCW.x,
  437. perimeterProjectedSW.x
  438. );
  439. maxX = -minX; // symmetrical
  440. maxY = Math.max(perimeterProjectedNW.y, perimeterProjectedNC.y);
  441. minY = Math.min(perimeterProjectedSW.y, perimeterProjectedSC.y);
  442. // Compute minimum Z using the rectangle at minimum height, since it will be deeper than the maximum height
  443. perimeterCartographicNW.height = perimeterCartographicSW.height = minimumHeight;
  444. perimeterCartesianNW = ellipsoid.cartographicToCartesian(
  445. perimeterCartographicNW,
  446. scratchPerimeterCartesianNW
  447. );
  448. perimeterCartesianSW = ellipsoid.cartographicToCartesian(
  449. perimeterCartographicSW,
  450. scratchPerimeterCartesianSW
  451. );
  452. minZ = Math.min(
  453. Plane.Plane.getPointDistance(plane, perimeterCartesianNW),
  454. Plane.Plane.getPointDistance(plane, perimeterCartesianSW)
  455. );
  456. maxZ = maximumHeight; // Since the tangent plane touches the surface at height = 0, this is okay
  457. return fromPlaneExtents(
  458. tangentPlane.origin,
  459. tangentPlane.xAxis,
  460. tangentPlane.yAxis,
  461. tangentPlane.zAxis,
  462. minX,
  463. maxX,
  464. minY,
  465. maxY,
  466. minZ,
  467. maxZ,
  468. result
  469. );
  470. }
  471. // Handle the case where rectangle width is greater than PI (wraps around more than half the ellipsoid).
  472. const fullyAboveEquator = rectangle.south > 0.0;
  473. const fullyBelowEquator = rectangle.north < 0.0;
  474. const latitudeNearestToEquator = fullyAboveEquator
  475. ? rectangle.south
  476. : fullyBelowEquator
  477. ? rectangle.north
  478. : 0.0;
  479. const centerLongitude = Matrix2.Rectangle.center(
  480. rectangle,
  481. scratchRectangleCenterCartographic
  482. ).longitude;
  483. // Plane is located at the rectangle's center longitude and the rectangle's latitude that is closest to the equator. It rotates around the Z axis.
  484. // This results in a better fit than the obb approach for smaller rectangles, which orients with the rectangle's center normal.
  485. const planeOrigin = Matrix2.Cartesian3.fromRadians(
  486. centerLongitude,
  487. latitudeNearestToEquator,
  488. maximumHeight,
  489. ellipsoid,
  490. scratchPlaneOrigin
  491. );
  492. planeOrigin.z = 0.0; // center the plane on the equator to simpify plane normal calculation
  493. const isPole =
  494. Math.abs(planeOrigin.x) < ComponentDatatype.CesiumMath.EPSILON10 &&
  495. Math.abs(planeOrigin.y) < ComponentDatatype.CesiumMath.EPSILON10;
  496. const planeNormal = !isPole
  497. ? Matrix2.Cartesian3.normalize(planeOrigin, scratchPlaneNormal)
  498. : Matrix2.Cartesian3.UNIT_X;
  499. const planeYAxis = Matrix2.Cartesian3.UNIT_Z;
  500. const planeXAxis = Matrix2.Cartesian3.cross(
  501. planeNormal,
  502. planeYAxis,
  503. scratchPlaneXAxis
  504. );
  505. plane = Plane.Plane.fromPointNormal(planeOrigin, planeNormal, scratchPlane);
  506. // Get the horizon point relative to the center. This will be the farthest extent in the plane's X dimension.
  507. const horizonCartesian = Matrix2.Cartesian3.fromRadians(
  508. centerLongitude + ComponentDatatype.CesiumMath.PI_OVER_TWO,
  509. latitudeNearestToEquator,
  510. maximumHeight,
  511. ellipsoid,
  512. scratchHorizonCartesian
  513. );
  514. maxX = Matrix2.Cartesian3.dot(
  515. Plane.Plane.projectPointOntoPlane(
  516. plane,
  517. horizonCartesian,
  518. scratchHorizonProjected
  519. ),
  520. planeXAxis
  521. );
  522. minX = -maxX; // symmetrical
  523. // Get the min and max Y, using the height that will give the largest extent
  524. maxY = Matrix2.Cartesian3.fromRadians(
  525. 0.0,
  526. rectangle.north,
  527. fullyBelowEquator ? minimumHeight : maximumHeight,
  528. ellipsoid,
  529. scratchMaxY
  530. ).z;
  531. minY = Matrix2.Cartesian3.fromRadians(
  532. 0.0,
  533. rectangle.south,
  534. fullyAboveEquator ? minimumHeight : maximumHeight,
  535. ellipsoid,
  536. scratchMinY
  537. ).z;
  538. const farZ = Matrix2.Cartesian3.fromRadians(
  539. rectangle.east,
  540. latitudeNearestToEquator,
  541. maximumHeight,
  542. ellipsoid,
  543. scratchZ
  544. );
  545. minZ = Plane.Plane.getPointDistance(plane, farZ);
  546. maxZ = 0.0; // plane origin starts at maxZ already
  547. // min and max are local to the plane axes
  548. return fromPlaneExtents(
  549. planeOrigin,
  550. planeXAxis,
  551. planeYAxis,
  552. planeNormal,
  553. minX,
  554. maxX,
  555. minY,
  556. maxY,
  557. minZ,
  558. maxZ,
  559. result
  560. );
  561. };
  562. /**
  563. * Computes an OrientedBoundingBox that bounds an affine transformation.
  564. *
  565. * @param {Matrix4} transformation The affine transformation.
  566. * @param {OrientedBoundingBox} [result] The object onto which to store the result.
  567. * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if none was provided.
  568. */
  569. OrientedBoundingBox.fromTransformation = function (transformation, result) {
  570. //>>includeStart('debug', pragmas.debug);
  571. RuntimeError.Check.typeOf.object("transformation", transformation);
  572. //>>includeEnd('debug');
  573. if (!defaultValue.defined(result)) {
  574. result = new OrientedBoundingBox();
  575. }
  576. result.center = Matrix2.Matrix4.getTranslation(transformation, result.center);
  577. result.halfAxes = Matrix2.Matrix4.getMatrix3(transformation, result.halfAxes);
  578. result.halfAxes = Matrix2.Matrix3.multiplyByScalar(
  579. result.halfAxes,
  580. 0.5,
  581. result.halfAxes
  582. );
  583. return result;
  584. };
  585. /**
  586. * Duplicates a OrientedBoundingBox instance.
  587. *
  588. * @param {OrientedBoundingBox} box The bounding box to duplicate.
  589. * @param {OrientedBoundingBox} [result] The object onto which to store the result.
  590. * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if none was provided. (Returns undefined if box is undefined)
  591. */
  592. OrientedBoundingBox.clone = function (box, result) {
  593. if (!defaultValue.defined(box)) {
  594. return undefined;
  595. }
  596. if (!defaultValue.defined(result)) {
  597. return new OrientedBoundingBox(box.center, box.halfAxes);
  598. }
  599. Matrix2.Cartesian3.clone(box.center, result.center);
  600. Matrix2.Matrix3.clone(box.halfAxes, result.halfAxes);
  601. return result;
  602. };
  603. /**
  604. * Determines which side of a plane the oriented bounding box is located.
  605. *
  606. * @param {OrientedBoundingBox} box The oriented bounding box to test.
  607. * @param {Plane} plane The plane to test against.
  608. * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane
  609. * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is
  610. * on the opposite side, and {@link Intersect.INTERSECTING} if the box
  611. * intersects the plane.
  612. */
  613. OrientedBoundingBox.intersectPlane = function (box, plane) {
  614. //>>includeStart('debug', pragmas.debug);
  615. if (!defaultValue.defined(box)) {
  616. throw new RuntimeError.DeveloperError("box is required.");
  617. }
  618. if (!defaultValue.defined(plane)) {
  619. throw new RuntimeError.DeveloperError("plane is required.");
  620. }
  621. //>>includeEnd('debug');
  622. const center = box.center;
  623. const normal = plane.normal;
  624. const halfAxes = box.halfAxes;
  625. const normalX = normal.x,
  626. normalY = normal.y,
  627. normalZ = normal.z;
  628. // plane is used as if it is its normal; the first three components are assumed to be normalized
  629. const radEffective =
  630. Math.abs(
  631. normalX * halfAxes[Matrix2.Matrix3.COLUMN0ROW0] +
  632. normalY * halfAxes[Matrix2.Matrix3.COLUMN0ROW1] +
  633. normalZ * halfAxes[Matrix2.Matrix3.COLUMN0ROW2]
  634. ) +
  635. Math.abs(
  636. normalX * halfAxes[Matrix2.Matrix3.COLUMN1ROW0] +
  637. normalY * halfAxes[Matrix2.Matrix3.COLUMN1ROW1] +
  638. normalZ * halfAxes[Matrix2.Matrix3.COLUMN1ROW2]
  639. ) +
  640. Math.abs(
  641. normalX * halfAxes[Matrix2.Matrix3.COLUMN2ROW0] +
  642. normalY * halfAxes[Matrix2.Matrix3.COLUMN2ROW1] +
  643. normalZ * halfAxes[Matrix2.Matrix3.COLUMN2ROW2]
  644. );
  645. const distanceToPlane = Matrix2.Cartesian3.dot(normal, center) + plane.distance;
  646. if (distanceToPlane <= -radEffective) {
  647. // The entire box is on the negative side of the plane normal
  648. return Transforms.Intersect.OUTSIDE;
  649. } else if (distanceToPlane >= radEffective) {
  650. // The entire box is on the positive side of the plane normal
  651. return Transforms.Intersect.INSIDE;
  652. }
  653. return Transforms.Intersect.INTERSECTING;
  654. };
  655. const scratchCartesianU = new Matrix2.Cartesian3();
  656. const scratchCartesianV = new Matrix2.Cartesian3();
  657. const scratchCartesianW = new Matrix2.Cartesian3();
  658. const scratchValidAxis2 = new Matrix2.Cartesian3();
  659. const scratchValidAxis3 = new Matrix2.Cartesian3();
  660. const scratchPPrime = new Matrix2.Cartesian3();
  661. /**
  662. * Computes the estimated distance squared from the closest point on a bounding box to a point.
  663. *
  664. * @param {OrientedBoundingBox} box The box.
  665. * @param {Cartesian3} cartesian The point
  666. * @returns {Number} The distance squared from the oriented bounding box to the point. Returns 0 if the point is inside the box.
  667. *
  668. * @example
  669. * // Sort bounding boxes from back to front
  670. * boxes.sort(function(a, b) {
  671. * return Cesium.OrientedBoundingBox.distanceSquaredTo(b, camera.positionWC) - Cesium.OrientedBoundingBox.distanceSquaredTo(a, camera.positionWC);
  672. * });
  673. */
  674. OrientedBoundingBox.distanceSquaredTo = function (box, cartesian) {
  675. // See Geometric Tools for Computer Graphics 10.4.2
  676. //>>includeStart('debug', pragmas.debug);
  677. if (!defaultValue.defined(box)) {
  678. throw new RuntimeError.DeveloperError("box is required.");
  679. }
  680. if (!defaultValue.defined(cartesian)) {
  681. throw new RuntimeError.DeveloperError("cartesian is required.");
  682. }
  683. //>>includeEnd('debug');
  684. const offset = Matrix2.Cartesian3.subtract(cartesian, box.center, scratchOffset);
  685. const halfAxes = box.halfAxes;
  686. let u = Matrix2.Matrix3.getColumn(halfAxes, 0, scratchCartesianU);
  687. let v = Matrix2.Matrix3.getColumn(halfAxes, 1, scratchCartesianV);
  688. let w = Matrix2.Matrix3.getColumn(halfAxes, 2, scratchCartesianW);
  689. const uHalf = Matrix2.Cartesian3.magnitude(u);
  690. const vHalf = Matrix2.Cartesian3.magnitude(v);
  691. const wHalf = Matrix2.Cartesian3.magnitude(w);
  692. let uValid = true;
  693. let vValid = true;
  694. let wValid = true;
  695. if (uHalf > 0) {
  696. Matrix2.Cartesian3.divideByScalar(u, uHalf, u);
  697. } else {
  698. uValid = false;
  699. }
  700. if (vHalf > 0) {
  701. Matrix2.Cartesian3.divideByScalar(v, vHalf, v);
  702. } else {
  703. vValid = false;
  704. }
  705. if (wHalf > 0) {
  706. Matrix2.Cartesian3.divideByScalar(w, wHalf, w);
  707. } else {
  708. wValid = false;
  709. }
  710. const numberOfDegenerateAxes = !uValid + !vValid + !wValid;
  711. let validAxis1;
  712. let validAxis2;
  713. let validAxis3;
  714. if (numberOfDegenerateAxes === 1) {
  715. let degenerateAxis = u;
  716. validAxis1 = v;
  717. validAxis2 = w;
  718. if (!vValid) {
  719. degenerateAxis = v;
  720. validAxis1 = u;
  721. } else if (!wValid) {
  722. degenerateAxis = w;
  723. validAxis2 = u;
  724. }
  725. validAxis3 = Matrix2.Cartesian3.cross(validAxis1, validAxis2, scratchValidAxis3);
  726. if (degenerateAxis === u) {
  727. u = validAxis3;
  728. } else if (degenerateAxis === v) {
  729. v = validAxis3;
  730. } else if (degenerateAxis === w) {
  731. w = validAxis3;
  732. }
  733. } else if (numberOfDegenerateAxes === 2) {
  734. validAxis1 = u;
  735. if (vValid) {
  736. validAxis1 = v;
  737. } else if (wValid) {
  738. validAxis1 = w;
  739. }
  740. let crossVector = Matrix2.Cartesian3.UNIT_Y;
  741. if (crossVector.equalsEpsilon(validAxis1, ComponentDatatype.CesiumMath.EPSILON3)) {
  742. crossVector = Matrix2.Cartesian3.UNIT_X;
  743. }
  744. validAxis2 = Matrix2.Cartesian3.cross(validAxis1, crossVector, scratchValidAxis2);
  745. Matrix2.Cartesian3.normalize(validAxis2, validAxis2);
  746. validAxis3 = Matrix2.Cartesian3.cross(validAxis1, validAxis2, scratchValidAxis3);
  747. Matrix2.Cartesian3.normalize(validAxis3, validAxis3);
  748. if (validAxis1 === u) {
  749. v = validAxis2;
  750. w = validAxis3;
  751. } else if (validAxis1 === v) {
  752. w = validAxis2;
  753. u = validAxis3;
  754. } else if (validAxis1 === w) {
  755. u = validAxis2;
  756. v = validAxis3;
  757. }
  758. } else if (numberOfDegenerateAxes === 3) {
  759. u = Matrix2.Cartesian3.UNIT_X;
  760. v = Matrix2.Cartesian3.UNIT_Y;
  761. w = Matrix2.Cartesian3.UNIT_Z;
  762. }
  763. const pPrime = scratchPPrime;
  764. pPrime.x = Matrix2.Cartesian3.dot(offset, u);
  765. pPrime.y = Matrix2.Cartesian3.dot(offset, v);
  766. pPrime.z = Matrix2.Cartesian3.dot(offset, w);
  767. let distanceSquared = 0.0;
  768. let d;
  769. if (pPrime.x < -uHalf) {
  770. d = pPrime.x + uHalf;
  771. distanceSquared += d * d;
  772. } else if (pPrime.x > uHalf) {
  773. d = pPrime.x - uHalf;
  774. distanceSquared += d * d;
  775. }
  776. if (pPrime.y < -vHalf) {
  777. d = pPrime.y + vHalf;
  778. distanceSquared += d * d;
  779. } else if (pPrime.y > vHalf) {
  780. d = pPrime.y - vHalf;
  781. distanceSquared += d * d;
  782. }
  783. if (pPrime.z < -wHalf) {
  784. d = pPrime.z + wHalf;
  785. distanceSquared += d * d;
  786. } else if (pPrime.z > wHalf) {
  787. d = pPrime.z - wHalf;
  788. distanceSquared += d * d;
  789. }
  790. return distanceSquared;
  791. };
  792. const scratchCorner = new Matrix2.Cartesian3();
  793. const scratchToCenter = new Matrix2.Cartesian3();
  794. /**
  795. * The distances calculated by the vector from the center of the bounding box to position projected onto direction.
  796. * <br>
  797. * If you imagine the infinite number of planes with normal direction, this computes the smallest distance to the
  798. * closest and farthest planes from position that intersect the bounding box.
  799. *
  800. * @param {OrientedBoundingBox} box The bounding box to calculate the distance to.
  801. * @param {Cartesian3} position The position to calculate the distance from.
  802. * @param {Cartesian3} direction The direction from position.
  803. * @param {Interval} [result] A Interval to store the nearest and farthest distances.
  804. * @returns {Interval} The nearest and farthest distances on the bounding box from position in direction.
  805. */
  806. OrientedBoundingBox.computePlaneDistances = function (
  807. box,
  808. position,
  809. direction,
  810. result
  811. ) {
  812. //>>includeStart('debug', pragmas.debug);
  813. if (!defaultValue.defined(box)) {
  814. throw new RuntimeError.DeveloperError("box is required.");
  815. }
  816. if (!defaultValue.defined(position)) {
  817. throw new RuntimeError.DeveloperError("position is required.");
  818. }
  819. if (!defaultValue.defined(direction)) {
  820. throw new RuntimeError.DeveloperError("direction is required.");
  821. }
  822. //>>includeEnd('debug');
  823. if (!defaultValue.defined(result)) {
  824. result = new Transforms.Interval();
  825. }
  826. let minDist = Number.POSITIVE_INFINITY;
  827. let maxDist = Number.NEGATIVE_INFINITY;
  828. const center = box.center;
  829. const halfAxes = box.halfAxes;
  830. const u = Matrix2.Matrix3.getColumn(halfAxes, 0, scratchCartesianU);
  831. const v = Matrix2.Matrix3.getColumn(halfAxes, 1, scratchCartesianV);
  832. const w = Matrix2.Matrix3.getColumn(halfAxes, 2, scratchCartesianW);
  833. // project first corner
  834. const corner = Matrix2.Cartesian3.add(u, v, scratchCorner);
  835. Matrix2.Cartesian3.add(corner, w, corner);
  836. Matrix2.Cartesian3.add(corner, center, corner);
  837. const toCenter = Matrix2.Cartesian3.subtract(corner, position, scratchToCenter);
  838. let mag = Matrix2.Cartesian3.dot(direction, toCenter);
  839. minDist = Math.min(mag, minDist);
  840. maxDist = Math.max(mag, maxDist);
  841. // project second corner
  842. Matrix2.Cartesian3.add(center, u, corner);
  843. Matrix2.Cartesian3.add(corner, v, corner);
  844. Matrix2.Cartesian3.subtract(corner, w, corner);
  845. Matrix2.Cartesian3.subtract(corner, position, toCenter);
  846. mag = Matrix2.Cartesian3.dot(direction, toCenter);
  847. minDist = Math.min(mag, minDist);
  848. maxDist = Math.max(mag, maxDist);
  849. // project third corner
  850. Matrix2.Cartesian3.add(center, u, corner);
  851. Matrix2.Cartesian3.subtract(corner, v, corner);
  852. Matrix2.Cartesian3.add(corner, w, corner);
  853. Matrix2.Cartesian3.subtract(corner, position, toCenter);
  854. mag = Matrix2.Cartesian3.dot(direction, toCenter);
  855. minDist = Math.min(mag, minDist);
  856. maxDist = Math.max(mag, maxDist);
  857. // project fourth corner
  858. Matrix2.Cartesian3.add(center, u, corner);
  859. Matrix2.Cartesian3.subtract(corner, v, corner);
  860. Matrix2.Cartesian3.subtract(corner, w, corner);
  861. Matrix2.Cartesian3.subtract(corner, position, toCenter);
  862. mag = Matrix2.Cartesian3.dot(direction, toCenter);
  863. minDist = Math.min(mag, minDist);
  864. maxDist = Math.max(mag, maxDist);
  865. // project fifth corner
  866. Matrix2.Cartesian3.subtract(center, u, corner);
  867. Matrix2.Cartesian3.add(corner, v, corner);
  868. Matrix2.Cartesian3.add(corner, w, corner);
  869. Matrix2.Cartesian3.subtract(corner, position, toCenter);
  870. mag = Matrix2.Cartesian3.dot(direction, toCenter);
  871. minDist = Math.min(mag, minDist);
  872. maxDist = Math.max(mag, maxDist);
  873. // project sixth corner
  874. Matrix2.Cartesian3.subtract(center, u, corner);
  875. Matrix2.Cartesian3.add(corner, v, corner);
  876. Matrix2.Cartesian3.subtract(corner, w, corner);
  877. Matrix2.Cartesian3.subtract(corner, position, toCenter);
  878. mag = Matrix2.Cartesian3.dot(direction, toCenter);
  879. minDist = Math.min(mag, minDist);
  880. maxDist = Math.max(mag, maxDist);
  881. // project seventh corner
  882. Matrix2.Cartesian3.subtract(center, u, corner);
  883. Matrix2.Cartesian3.subtract(corner, v, corner);
  884. Matrix2.Cartesian3.add(corner, w, corner);
  885. Matrix2.Cartesian3.subtract(corner, position, toCenter);
  886. mag = Matrix2.Cartesian3.dot(direction, toCenter);
  887. minDist = Math.min(mag, minDist);
  888. maxDist = Math.max(mag, maxDist);
  889. // project eighth corner
  890. Matrix2.Cartesian3.subtract(center, u, corner);
  891. Matrix2.Cartesian3.subtract(corner, v, corner);
  892. Matrix2.Cartesian3.subtract(corner, w, corner);
  893. Matrix2.Cartesian3.subtract(corner, position, toCenter);
  894. mag = Matrix2.Cartesian3.dot(direction, toCenter);
  895. minDist = Math.min(mag, minDist);
  896. maxDist = Math.max(mag, maxDist);
  897. result.start = minDist;
  898. result.stop = maxDist;
  899. return result;
  900. };
  901. const scratchXAxis = new Matrix2.Cartesian3();
  902. const scratchYAxis = new Matrix2.Cartesian3();
  903. const scratchZAxis = new Matrix2.Cartesian3();
  904. /**
  905. * Computes the eight corners of an oriented bounding box. The corners are ordered by (-X, -Y, -Z), (-X, -Y, +Z), (-X, +Y, -Z), (-X, +Y, +Z), (+X, -Y, -Z), (+X, -Y, +Z), (+X, +Y, -Z), (+X, +Y, +Z).
  906. *
  907. * @param {OrientedBoundingBox} box The oriented bounding box.
  908. * @param {Cartesian3[]} [result] An array of eight {@link Cartesian3} instances onto which to store the corners.
  909. * @returns {Cartesian3[]} The modified result parameter or a new array if none was provided.
  910. */
  911. OrientedBoundingBox.computeCorners = function (box, result) {
  912. //>>includeStart('debug', pragmas.debug);
  913. RuntimeError.Check.typeOf.object("box", box);
  914. //>>includeEnd('debug');
  915. if (!defaultValue.defined(result)) {
  916. result = [
  917. new Matrix2.Cartesian3(),
  918. new Matrix2.Cartesian3(),
  919. new Matrix2.Cartesian3(),
  920. new Matrix2.Cartesian3(),
  921. new Matrix2.Cartesian3(),
  922. new Matrix2.Cartesian3(),
  923. new Matrix2.Cartesian3(),
  924. new Matrix2.Cartesian3(),
  925. ];
  926. }
  927. const center = box.center;
  928. const halfAxes = box.halfAxes;
  929. const xAxis = Matrix2.Matrix3.getColumn(halfAxes, 0, scratchXAxis);
  930. const yAxis = Matrix2.Matrix3.getColumn(halfAxes, 1, scratchYAxis);
  931. const zAxis = Matrix2.Matrix3.getColumn(halfAxes, 2, scratchZAxis);
  932. Matrix2.Cartesian3.clone(center, result[0]);
  933. Matrix2.Cartesian3.subtract(result[0], xAxis, result[0]);
  934. Matrix2.Cartesian3.subtract(result[0], yAxis, result[0]);
  935. Matrix2.Cartesian3.subtract(result[0], zAxis, result[0]);
  936. Matrix2.Cartesian3.clone(center, result[1]);
  937. Matrix2.Cartesian3.subtract(result[1], xAxis, result[1]);
  938. Matrix2.Cartesian3.subtract(result[1], yAxis, result[1]);
  939. Matrix2.Cartesian3.add(result[1], zAxis, result[1]);
  940. Matrix2.Cartesian3.clone(center, result[2]);
  941. Matrix2.Cartesian3.subtract(result[2], xAxis, result[2]);
  942. Matrix2.Cartesian3.add(result[2], yAxis, result[2]);
  943. Matrix2.Cartesian3.subtract(result[2], zAxis, result[2]);
  944. Matrix2.Cartesian3.clone(center, result[3]);
  945. Matrix2.Cartesian3.subtract(result[3], xAxis, result[3]);
  946. Matrix2.Cartesian3.add(result[3], yAxis, result[3]);
  947. Matrix2.Cartesian3.add(result[3], zAxis, result[3]);
  948. Matrix2.Cartesian3.clone(center, result[4]);
  949. Matrix2.Cartesian3.add(result[4], xAxis, result[4]);
  950. Matrix2.Cartesian3.subtract(result[4], yAxis, result[4]);
  951. Matrix2.Cartesian3.subtract(result[4], zAxis, result[4]);
  952. Matrix2.Cartesian3.clone(center, result[5]);
  953. Matrix2.Cartesian3.add(result[5], xAxis, result[5]);
  954. Matrix2.Cartesian3.subtract(result[5], yAxis, result[5]);
  955. Matrix2.Cartesian3.add(result[5], zAxis, result[5]);
  956. Matrix2.Cartesian3.clone(center, result[6]);
  957. Matrix2.Cartesian3.add(result[6], xAxis, result[6]);
  958. Matrix2.Cartesian3.add(result[6], yAxis, result[6]);
  959. Matrix2.Cartesian3.subtract(result[6], zAxis, result[6]);
  960. Matrix2.Cartesian3.clone(center, result[7]);
  961. Matrix2.Cartesian3.add(result[7], xAxis, result[7]);
  962. Matrix2.Cartesian3.add(result[7], yAxis, result[7]);
  963. Matrix2.Cartesian3.add(result[7], zAxis, result[7]);
  964. return result;
  965. };
  966. const scratchRotationScale = new Matrix2.Matrix3();
  967. /**
  968. * Computes a transformation matrix from an oriented bounding box.
  969. *
  970. * @param {OrientedBoundingBox} box The oriented bounding box.
  971. * @param {Matrix4} result The object onto which to store the result.
  972. * @returns {Matrix4} The modified result parameter or a new {@link Matrix4} instance if none was provided.
  973. */
  974. OrientedBoundingBox.computeTransformation = function (box, result) {
  975. //>>includeStart('debug', pragmas.debug);
  976. RuntimeError.Check.typeOf.object("box", box);
  977. //>>includeEnd('debug');
  978. if (!defaultValue.defined(result)) {
  979. result = new Matrix2.Matrix4();
  980. }
  981. const translation = box.center;
  982. const rotationScale = Matrix2.Matrix3.multiplyByUniformScale(
  983. box.halfAxes,
  984. 2.0,
  985. scratchRotationScale
  986. );
  987. return Matrix2.Matrix4.fromRotationTranslation(rotationScale, translation, result);
  988. };
  989. const scratchBoundingSphere = new Transforms.BoundingSphere();
  990. /**
  991. * Determines whether or not a bounding box is hidden from view by the occluder.
  992. *
  993. * @param {OrientedBoundingBox} box The bounding box surrounding the occludee object.
  994. * @param {Occluder} occluder The occluder.
  995. * @returns {Boolean} <code>true</code> if the box is not visible; otherwise <code>false</code>.
  996. */
  997. OrientedBoundingBox.isOccluded = function (box, occluder) {
  998. //>>includeStart('debug', pragmas.debug);
  999. if (!defaultValue.defined(box)) {
  1000. throw new RuntimeError.DeveloperError("box is required.");
  1001. }
  1002. if (!defaultValue.defined(occluder)) {
  1003. throw new RuntimeError.DeveloperError("occluder is required.");
  1004. }
  1005. //>>includeEnd('debug');
  1006. const sphere = Transforms.BoundingSphere.fromOrientedBoundingBox(
  1007. box,
  1008. scratchBoundingSphere
  1009. );
  1010. return !occluder.isBoundingSphereVisible(sphere);
  1011. };
  1012. /**
  1013. * Determines which side of a plane the oriented bounding box is located.
  1014. *
  1015. * @param {Plane} plane The plane to test against.
  1016. * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane
  1017. * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is
  1018. * on the opposite side, and {@link Intersect.INTERSECTING} if the box
  1019. * intersects the plane.
  1020. */
  1021. OrientedBoundingBox.prototype.intersectPlane = function (plane) {
  1022. return OrientedBoundingBox.intersectPlane(this, plane);
  1023. };
  1024. /**
  1025. * Computes the estimated distance squared from the closest point on a bounding box to a point.
  1026. *
  1027. * @param {Cartesian3} cartesian The point
  1028. * @returns {Number} The estimated distance squared from the bounding sphere to the point.
  1029. *
  1030. * @example
  1031. * // Sort bounding boxes from back to front
  1032. * boxes.sort(function(a, b) {
  1033. * return b.distanceSquaredTo(camera.positionWC) - a.distanceSquaredTo(camera.positionWC);
  1034. * });
  1035. */
  1036. OrientedBoundingBox.prototype.distanceSquaredTo = function (cartesian) {
  1037. return OrientedBoundingBox.distanceSquaredTo(this, cartesian);
  1038. };
  1039. /**
  1040. * The distances calculated by the vector from the center of the bounding box to position projected onto direction.
  1041. * <br>
  1042. * If you imagine the infinite number of planes with normal direction, this computes the smallest distance to the
  1043. * closest and farthest planes from position that intersect the bounding box.
  1044. *
  1045. * @param {Cartesian3} position The position to calculate the distance from.
  1046. * @param {Cartesian3} direction The direction from position.
  1047. * @param {Interval} [result] A Interval to store the nearest and farthest distances.
  1048. * @returns {Interval} The nearest and farthest distances on the bounding box from position in direction.
  1049. */
  1050. OrientedBoundingBox.prototype.computePlaneDistances = function (
  1051. position,
  1052. direction,
  1053. result
  1054. ) {
  1055. return OrientedBoundingBox.computePlaneDistances(
  1056. this,
  1057. position,
  1058. direction,
  1059. result
  1060. );
  1061. };
  1062. /**
  1063. * Computes the eight corners of an oriented bounding box. The corners are ordered by (-X, -Y, -Z), (-X, -Y, +Z), (-X, +Y, -Z), (-X, +Y, +Z), (+X, -Y, -Z), (+X, -Y, +Z), (+X, +Y, -Z), (+X, +Y, +Z).
  1064. *
  1065. * @param {Cartesian3[]} [result] An array of eight {@link Cartesian3} instances onto which to store the corners.
  1066. * @returns {Cartesian3[]} The modified result parameter or a new array if none was provided.
  1067. */
  1068. OrientedBoundingBox.prototype.computeCorners = function (result) {
  1069. return OrientedBoundingBox.computeCorners(this, result);
  1070. };
  1071. /**
  1072. * Computes a transformation matrix from an oriented bounding box.
  1073. *
  1074. * @param {Matrix4} result The object onto which to store the result.
  1075. * @returns {Matrix4} The modified result parameter or a new {@link Matrix4} instance if none was provided.
  1076. */
  1077. OrientedBoundingBox.prototype.computeTransformation = function (result) {
  1078. return OrientedBoundingBox.computeTransformation(this, result);
  1079. };
  1080. /**
  1081. * Determines whether or not a bounding box is hidden from view by the occluder.
  1082. *
  1083. * @param {Occluder} occluder The occluder.
  1084. * @returns {Boolean} <code>true</code> if the sphere is not visible; otherwise <code>false</code>.
  1085. */
  1086. OrientedBoundingBox.prototype.isOccluded = function (occluder) {
  1087. return OrientedBoundingBox.isOccluded(this, occluder);
  1088. };
  1089. /**
  1090. * Compares the provided OrientedBoundingBox componentwise and returns
  1091. * <code>true</code> if they are equal, <code>false</code> otherwise.
  1092. *
  1093. * @param {OrientedBoundingBox} left The first OrientedBoundingBox.
  1094. * @param {OrientedBoundingBox} right The second OrientedBoundingBox.
  1095. * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
  1096. */
  1097. OrientedBoundingBox.equals = function (left, right) {
  1098. return (
  1099. left === right ||
  1100. (defaultValue.defined(left) &&
  1101. defaultValue.defined(right) &&
  1102. Matrix2.Cartesian3.equals(left.center, right.center) &&
  1103. Matrix2.Matrix3.equals(left.halfAxes, right.halfAxes))
  1104. );
  1105. };
  1106. /**
  1107. * Duplicates this OrientedBoundingBox instance.
  1108. *
  1109. * @param {OrientedBoundingBox} [result] The object onto which to store the result.
  1110. * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if one was not provided.
  1111. */
  1112. OrientedBoundingBox.prototype.clone = function (result) {
  1113. return OrientedBoundingBox.clone(this, result);
  1114. };
  1115. /**
  1116. * Compares this OrientedBoundingBox against the provided OrientedBoundingBox componentwise and returns
  1117. * <code>true</code> if they are equal, <code>false</code> otherwise.
  1118. *
  1119. * @param {OrientedBoundingBox} [right] The right hand side OrientedBoundingBox.
  1120. * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
  1121. */
  1122. OrientedBoundingBox.prototype.equals = function (right) {
  1123. return OrientedBoundingBox.equals(this, right);
  1124. };
  1125. exports.OrientedBoundingBox = OrientedBoundingBox;
  1126. }));
  1127. //# sourceMappingURL=OrientedBoundingBox-a82b3552.js.map