Matrix2.js 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093
  1. import Cartesian2 from "./Cartesian2.js";
  2. import Check from "./Check.js";
  3. import defaultValue from "./defaultValue.js";
  4. import defined from "./defined.js";
  5. import DeveloperError from "./DeveloperError.js";
  6. /**
  7. * A 2x2 matrix, indexable as a column-major order array.
  8. * Constructor parameters are in row-major order for code readability.
  9. * @alias Matrix2
  10. * @constructor
  11. * @implements {ArrayLike<number>}
  12. *
  13. * @param {number} [column0Row0=0.0] The value for column 0, row 0.
  14. * @param {number} [column1Row0=0.0] The value for column 1, row 0.
  15. * @param {number} [column0Row1=0.0] The value for column 0, row 1.
  16. * @param {number} [column1Row1=0.0] The value for column 1, row 1.
  17. *
  18. * @see Matrix2.fromArray
  19. * @see Matrix2.fromColumnMajorArray
  20. * @see Matrix2.fromRowMajorArray
  21. * @see Matrix2.fromScale
  22. * @see Matrix2.fromUniformScale
  23. * @see Matrix2.fromRotation
  24. * @see Matrix3
  25. * @see Matrix4
  26. */
  27. function Matrix2(column0Row0, column1Row0, column0Row1, column1Row1) {
  28. this[0] = defaultValue(column0Row0, 0.0);
  29. this[1] = defaultValue(column0Row1, 0.0);
  30. this[2] = defaultValue(column1Row0, 0.0);
  31. this[3] = defaultValue(column1Row1, 0.0);
  32. }
  33. /**
  34. * The number of elements used to pack the object into an array.
  35. * @type {number}
  36. */
  37. Matrix2.packedLength = 4;
  38. /**
  39. * Stores the provided instance into the provided array.
  40. *
  41. * @param {Matrix2} value The value to pack.
  42. * @param {number[]} array The array to pack into.
  43. * @param {number} [startingIndex=0] The index into the array at which to start packing the elements.
  44. *
  45. * @returns {number[]} The array that was packed into
  46. */
  47. Matrix2.pack = function (value, array, startingIndex) {
  48. //>>includeStart('debug', pragmas.debug);
  49. Check.typeOf.object("value", value);
  50. Check.defined("array", array);
  51. //>>includeEnd('debug');
  52. startingIndex = defaultValue(startingIndex, 0);
  53. array[startingIndex++] = value[0];
  54. array[startingIndex++] = value[1];
  55. array[startingIndex++] = value[2];
  56. array[startingIndex++] = value[3];
  57. return array;
  58. };
  59. /**
  60. * Retrieves an instance from a packed array.
  61. *
  62. * @param {number[]} array The packed array.
  63. * @param {number} [startingIndex=0] The starting index of the element to be unpacked.
  64. * @param {Matrix2} [result] The object into which to store the result.
  65. * @returns {Matrix2} The modified result parameter or a new Matrix2 instance if one was not provided.
  66. */
  67. Matrix2.unpack = function (array, startingIndex, result) {
  68. //>>includeStart('debug', pragmas.debug);
  69. Check.defined("array", array);
  70. //>>includeEnd('debug');
  71. startingIndex = defaultValue(startingIndex, 0);
  72. if (!defined(result)) {
  73. result = new Matrix2();
  74. }
  75. result[0] = array[startingIndex++];
  76. result[1] = array[startingIndex++];
  77. result[2] = array[startingIndex++];
  78. result[3] = array[startingIndex++];
  79. return result;
  80. };
  81. /**
  82. * Flattens an array of Matrix2s into an array of components. The components
  83. * are stored in column-major order.
  84. *
  85. * @param {Matrix2[]} array The array of matrices to pack.
  86. * @param {number[]} [result] The array onto which to store the result. If this is a typed array, it must have array.length * 4 components, else a {@link DeveloperError} will be thrown. If it is a regular array, it will be resized to have (array.length * 4) elements.
  87. * @returns {number[]} The packed array.
  88. */
  89. Matrix2.packArray = function (array, result) {
  90. //>>includeStart('debug', pragmas.debug);
  91. Check.defined("array", array);
  92. //>>includeEnd('debug');
  93. const length = array.length;
  94. const resultLength = length * 4;
  95. if (!defined(result)) {
  96. result = new Array(resultLength);
  97. } else if (!Array.isArray(result) && result.length !== resultLength) {
  98. //>>includeStart('debug', pragmas.debug);
  99. throw new DeveloperError(
  100. "If result is a typed array, it must have exactly array.length * 4 elements"
  101. );
  102. //>>includeEnd('debug');
  103. } else if (result.length !== resultLength) {
  104. result.length = resultLength;
  105. }
  106. for (let i = 0; i < length; ++i) {
  107. Matrix2.pack(array[i], result, i * 4);
  108. }
  109. return result;
  110. };
  111. /**
  112. * Unpacks an array of column-major matrix components into an array of Matrix2s.
  113. *
  114. * @param {number[]} array The array of components to unpack.
  115. * @param {Matrix2[]} [result] The array onto which to store the result.
  116. * @returns {Matrix2[]} The unpacked array.
  117. */
  118. Matrix2.unpackArray = function (array, result) {
  119. //>>includeStart('debug', pragmas.debug);
  120. Check.defined("array", array);
  121. Check.typeOf.number.greaterThanOrEquals("array.length", array.length, 4);
  122. if (array.length % 4 !== 0) {
  123. throw new DeveloperError("array length must be a multiple of 4.");
  124. }
  125. //>>includeEnd('debug');
  126. const length = array.length;
  127. if (!defined(result)) {
  128. result = new Array(length / 4);
  129. } else {
  130. result.length = length / 4;
  131. }
  132. for (let i = 0; i < length; i += 4) {
  133. const index = i / 4;
  134. result[index] = Matrix2.unpack(array, i, result[index]);
  135. }
  136. return result;
  137. };
  138. /**
  139. * Duplicates a Matrix2 instance.
  140. *
  141. * @param {Matrix2} matrix The matrix to duplicate.
  142. * @param {Matrix2} [result] The object onto which to store the result.
  143. * @returns {Matrix2} The modified result parameter or a new Matrix2 instance if one was not provided. (Returns undefined if matrix is undefined)
  144. */
  145. Matrix2.clone = function (matrix, result) {
  146. if (!defined(matrix)) {
  147. return undefined;
  148. }
  149. if (!defined(result)) {
  150. return new Matrix2(matrix[0], matrix[2], matrix[1], matrix[3]);
  151. }
  152. result[0] = matrix[0];
  153. result[1] = matrix[1];
  154. result[2] = matrix[2];
  155. result[3] = matrix[3];
  156. return result;
  157. };
  158. /**
  159. * Creates a Matrix2 from 4 consecutive elements in an array.
  160. *
  161. * @function
  162. * @param {number[]} array The array whose 4 consecutive elements correspond to the positions of the matrix. Assumes column-major order.
  163. * @param {number} [startingIndex=0] The offset into the array of the first element, which corresponds to first column first row position in the matrix.
  164. * @param {Matrix2} [result] The object onto which to store the result.
  165. * @returns {Matrix2} The modified result parameter or a new Matrix2 instance if one was not provided.
  166. *
  167. * @example
  168. * // Create the Matrix2:
  169. * // [1.0, 2.0]
  170. * // [1.0, 2.0]
  171. *
  172. * const v = [1.0, 1.0, 2.0, 2.0];
  173. * const m = Cesium.Matrix2.fromArray(v);
  174. *
  175. * // Create same Matrix2 with using an offset into an array
  176. * const v2 = [0.0, 0.0, 1.0, 1.0, 2.0, 2.0];
  177. * const m2 = Cesium.Matrix2.fromArray(v2, 2);
  178. */
  179. Matrix2.fromArray = Matrix2.unpack;
  180. /**
  181. * Creates a Matrix2 instance from a column-major order array.
  182. *
  183. * @param {number[]} values The column-major order array.
  184. * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.
  185. * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.
  186. */
  187. Matrix2.fromColumnMajorArray = function (values, result) {
  188. //>>includeStart('debug', pragmas.debug);
  189. Check.defined("values", values);
  190. //>>includeEnd('debug');
  191. return Matrix2.clone(values, result);
  192. };
  193. /**
  194. * Creates a Matrix2 instance from a row-major order array.
  195. * The resulting matrix will be in column-major order.
  196. *
  197. * @param {number[]} values The row-major order array.
  198. * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.
  199. * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.
  200. */
  201. Matrix2.fromRowMajorArray = function (values, result) {
  202. //>>includeStart('debug', pragmas.debug);
  203. Check.defined("values", values);
  204. //>>includeEnd('debug');
  205. if (!defined(result)) {
  206. return new Matrix2(values[0], values[1], values[2], values[3]);
  207. }
  208. result[0] = values[0];
  209. result[1] = values[2];
  210. result[2] = values[1];
  211. result[3] = values[3];
  212. return result;
  213. };
  214. /**
  215. * Computes a Matrix2 instance representing a non-uniform scale.
  216. *
  217. * @param {Cartesian2} scale The x and y scale factors.
  218. * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.
  219. * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.
  220. *
  221. * @example
  222. * // Creates
  223. * // [7.0, 0.0]
  224. * // [0.0, 8.0]
  225. * const m = Cesium.Matrix2.fromScale(new Cesium.Cartesian2(7.0, 8.0));
  226. */
  227. Matrix2.fromScale = function (scale, result) {
  228. //>>includeStart('debug', pragmas.debug);
  229. Check.typeOf.object("scale", scale);
  230. //>>includeEnd('debug');
  231. if (!defined(result)) {
  232. return new Matrix2(scale.x, 0.0, 0.0, scale.y);
  233. }
  234. result[0] = scale.x;
  235. result[1] = 0.0;
  236. result[2] = 0.0;
  237. result[3] = scale.y;
  238. return result;
  239. };
  240. /**
  241. * Computes a Matrix2 instance representing a uniform scale.
  242. *
  243. * @param {number} scale The uniform scale factor.
  244. * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.
  245. * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.
  246. *
  247. * @example
  248. * // Creates
  249. * // [2.0, 0.0]
  250. * // [0.0, 2.0]
  251. * const m = Cesium.Matrix2.fromUniformScale(2.0);
  252. */
  253. Matrix2.fromUniformScale = function (scale, result) {
  254. //>>includeStart('debug', pragmas.debug);
  255. Check.typeOf.number("scale", scale);
  256. //>>includeEnd('debug');
  257. if (!defined(result)) {
  258. return new Matrix2(scale, 0.0, 0.0, scale);
  259. }
  260. result[0] = scale;
  261. result[1] = 0.0;
  262. result[2] = 0.0;
  263. result[3] = scale;
  264. return result;
  265. };
  266. /**
  267. * Creates a rotation matrix.
  268. *
  269. * @param {number} angle The angle, in radians, of the rotation. Positive angles are counterclockwise.
  270. * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.
  271. * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.
  272. *
  273. * @example
  274. * // Rotate a point 45 degrees counterclockwise.
  275. * const p = new Cesium.Cartesian2(5, 6);
  276. * const m = Cesium.Matrix2.fromRotation(Cesium.Math.toRadians(45.0));
  277. * const rotated = Cesium.Matrix2.multiplyByVector(m, p, new Cesium.Cartesian2());
  278. */
  279. Matrix2.fromRotation = function (angle, result) {
  280. //>>includeStart('debug', pragmas.debug);
  281. Check.typeOf.number("angle", angle);
  282. //>>includeEnd('debug');
  283. const cosAngle = Math.cos(angle);
  284. const sinAngle = Math.sin(angle);
  285. if (!defined(result)) {
  286. return new Matrix2(cosAngle, -sinAngle, sinAngle, cosAngle);
  287. }
  288. result[0] = cosAngle;
  289. result[1] = sinAngle;
  290. result[2] = -sinAngle;
  291. result[3] = cosAngle;
  292. return result;
  293. };
  294. /**
  295. * Creates an Array from the provided Matrix2 instance.
  296. * The array will be in column-major order.
  297. *
  298. * @param {Matrix2} matrix The matrix to use..
  299. * @param {number[]} [result] The Array onto which to store the result.
  300. * @returns {number[]} The modified Array parameter or a new Array instance if one was not provided.
  301. */
  302. Matrix2.toArray = function (matrix, result) {
  303. //>>includeStart('debug', pragmas.debug);
  304. Check.typeOf.object("matrix", matrix);
  305. //>>includeEnd('debug');
  306. if (!defined(result)) {
  307. return [matrix[0], matrix[1], matrix[2], matrix[3]];
  308. }
  309. result[0] = matrix[0];
  310. result[1] = matrix[1];
  311. result[2] = matrix[2];
  312. result[3] = matrix[3];
  313. return result;
  314. };
  315. /**
  316. * Computes the array index of the element at the provided row and column.
  317. *
  318. * @param {number} row The zero-based index of the row.
  319. * @param {number} column The zero-based index of the column.
  320. * @returns {number} The index of the element at the provided row and column.
  321. *
  322. * @exception {DeveloperError} row must be 0 or 1.
  323. * @exception {DeveloperError} column must be 0 or 1.
  324. *
  325. * @example
  326. * const myMatrix = new Cesium.Matrix2();
  327. * const column1Row0Index = Cesium.Matrix2.getElementIndex(1, 0);
  328. * const column1Row0 = myMatrix[column1Row0Index]
  329. * myMatrix[column1Row0Index] = 10.0;
  330. */
  331. Matrix2.getElementIndex = function (column, row) {
  332. //>>includeStart('debug', pragmas.debug);
  333. Check.typeOf.number.greaterThanOrEquals("row", row, 0);
  334. Check.typeOf.number.lessThanOrEquals("row", row, 1);
  335. Check.typeOf.number.greaterThanOrEquals("column", column, 0);
  336. Check.typeOf.number.lessThanOrEquals("column", column, 1);
  337. //>>includeEnd('debug');
  338. return column * 2 + row;
  339. };
  340. /**
  341. * Retrieves a copy of the matrix column at the provided index as a Cartesian2 instance.
  342. *
  343. * @param {Matrix2} matrix The matrix to use.
  344. * @param {number} index The zero-based index of the column to retrieve.
  345. * @param {Cartesian2} result The object onto which to store the result.
  346. * @returns {Cartesian2} The modified result parameter.
  347. *
  348. * @exception {DeveloperError} index must be 0 or 1.
  349. */
  350. Matrix2.getColumn = function (matrix, index, result) {
  351. //>>includeStart('debug', pragmas.debug);
  352. Check.typeOf.object("matrix", matrix);
  353. Check.typeOf.number.greaterThanOrEquals("index", index, 0);
  354. Check.typeOf.number.lessThanOrEquals("index", index, 1);
  355. Check.typeOf.object("result", result);
  356. //>>includeEnd('debug');
  357. const startIndex = index * 2;
  358. const x = matrix[startIndex];
  359. const y = matrix[startIndex + 1];
  360. result.x = x;
  361. result.y = y;
  362. return result;
  363. };
  364. /**
  365. * Computes a new matrix that replaces the specified column in the provided matrix with the provided Cartesian2 instance.
  366. *
  367. * @param {Matrix2} matrix The matrix to use.
  368. * @param {number} index The zero-based index of the column to set.
  369. * @param {Cartesian2} cartesian The Cartesian whose values will be assigned to the specified column.
  370. * @param {Cartesian2} result The object onto which to store the result.
  371. * @returns {Matrix2} The modified result parameter.
  372. *
  373. * @exception {DeveloperError} index must be 0 or 1.
  374. */
  375. Matrix2.setColumn = function (matrix, index, cartesian, result) {
  376. //>>includeStart('debug', pragmas.debug);
  377. Check.typeOf.object("matrix", matrix);
  378. Check.typeOf.number.greaterThanOrEquals("index", index, 0);
  379. Check.typeOf.number.lessThanOrEquals("index", index, 1);
  380. Check.typeOf.object("cartesian", cartesian);
  381. Check.typeOf.object("result", result);
  382. //>>includeEnd('debug');
  383. result = Matrix2.clone(matrix, result);
  384. const startIndex = index * 2;
  385. result[startIndex] = cartesian.x;
  386. result[startIndex + 1] = cartesian.y;
  387. return result;
  388. };
  389. /**
  390. * Retrieves a copy of the matrix row at the provided index as a Cartesian2 instance.
  391. *
  392. * @param {Matrix2} matrix The matrix to use.
  393. * @param {number} index The zero-based index of the row to retrieve.
  394. * @param {Cartesian2} result The object onto which to store the result.
  395. * @returns {Cartesian2} The modified result parameter.
  396. *
  397. * @exception {DeveloperError} index must be 0 or 1.
  398. */
  399. Matrix2.getRow = function (matrix, index, result) {
  400. //>>includeStart('debug', pragmas.debug);
  401. Check.typeOf.object("matrix", matrix);
  402. Check.typeOf.number.greaterThanOrEquals("index", index, 0);
  403. Check.typeOf.number.lessThanOrEquals("index", index, 1);
  404. Check.typeOf.object("result", result);
  405. //>>includeEnd('debug');
  406. const x = matrix[index];
  407. const y = matrix[index + 2];
  408. result.x = x;
  409. result.y = y;
  410. return result;
  411. };
  412. /**
  413. * Computes a new matrix that replaces the specified row in the provided matrix with the provided Cartesian2 instance.
  414. *
  415. * @param {Matrix2} matrix The matrix to use.
  416. * @param {number} index The zero-based index of the row to set.
  417. * @param {Cartesian2} cartesian The Cartesian whose values will be assigned to the specified row.
  418. * @param {Matrix2} result The object onto which to store the result.
  419. * @returns {Matrix2} The modified result parameter.
  420. *
  421. * @exception {DeveloperError} index must be 0 or 1.
  422. */
  423. Matrix2.setRow = function (matrix, index, cartesian, result) {
  424. //>>includeStart('debug', pragmas.debug);
  425. Check.typeOf.object("matrix", matrix);
  426. Check.typeOf.number.greaterThanOrEquals("index", index, 0);
  427. Check.typeOf.number.lessThanOrEquals("index", index, 1);
  428. Check.typeOf.object("cartesian", cartesian);
  429. Check.typeOf.object("result", result);
  430. //>>includeEnd('debug');
  431. result = Matrix2.clone(matrix, result);
  432. result[index] = cartesian.x;
  433. result[index + 2] = cartesian.y;
  434. return result;
  435. };
  436. const scaleScratch1 = new Cartesian2();
  437. /**
  438. * Computes a new matrix that replaces the scale with the provided scale.
  439. * This assumes the matrix is an affine transformation.
  440. *
  441. * @param {Matrix2} matrix The matrix to use.
  442. * @param {Cartesian2} scale The scale that replaces the scale of the provided matrix.
  443. * @param {Matrix2} result The object onto which to store the result.
  444. * @returns {Matrix2} The modified result parameter.
  445. *
  446. * @see Matrix2.setUniformScale
  447. * @see Matrix2.fromScale
  448. * @see Matrix2.fromUniformScale
  449. * @see Matrix2.multiplyByScale
  450. * @see Matrix2.multiplyByUniformScale
  451. * @see Matrix2.getScale
  452. */
  453. Matrix2.setScale = function (matrix, scale, result) {
  454. //>>includeStart('debug', pragmas.debug);
  455. Check.typeOf.object("matrix", matrix);
  456. Check.typeOf.object("scale", scale);
  457. Check.typeOf.object("result", result);
  458. //>>includeEnd('debug');
  459. const existingScale = Matrix2.getScale(matrix, scaleScratch1);
  460. const scaleRatioX = scale.x / existingScale.x;
  461. const scaleRatioY = scale.y / existingScale.y;
  462. result[0] = matrix[0] * scaleRatioX;
  463. result[1] = matrix[1] * scaleRatioX;
  464. result[2] = matrix[2] * scaleRatioY;
  465. result[3] = matrix[3] * scaleRatioY;
  466. return result;
  467. };
  468. const scaleScratch2 = new Cartesian2();
  469. /**
  470. * Computes a new matrix that replaces the scale with the provided uniform scale.
  471. * This assumes the matrix is an affine transformation.
  472. *
  473. * @param {Matrix2} matrix The matrix to use.
  474. * @param {number} scale The uniform scale that replaces the scale of the provided matrix.
  475. * @param {Matrix2} result The object onto which to store the result.
  476. * @returns {Matrix2} The modified result parameter.
  477. *
  478. * @see Matrix2.setScale
  479. * @see Matrix2.fromScale
  480. * @see Matrix2.fromUniformScale
  481. * @see Matrix2.multiplyByScale
  482. * @see Matrix2.multiplyByUniformScale
  483. * @see Matrix2.getScale
  484. */
  485. Matrix2.setUniformScale = function (matrix, scale, result) {
  486. //>>includeStart('debug', pragmas.debug);
  487. Check.typeOf.object("matrix", matrix);
  488. Check.typeOf.number("scale", scale);
  489. Check.typeOf.object("result", result);
  490. //>>includeEnd('debug');
  491. const existingScale = Matrix2.getScale(matrix, scaleScratch2);
  492. const scaleRatioX = scale / existingScale.x;
  493. const scaleRatioY = scale / existingScale.y;
  494. result[0] = matrix[0] * scaleRatioX;
  495. result[1] = matrix[1] * scaleRatioX;
  496. result[2] = matrix[2] * scaleRatioY;
  497. result[3] = matrix[3] * scaleRatioY;
  498. return result;
  499. };
  500. const scratchColumn = new Cartesian2();
  501. /**
  502. * Extracts the non-uniform scale assuming the matrix is an affine transformation.
  503. *
  504. * @param {Matrix2} matrix The matrix.
  505. * @param {Cartesian2} result The object onto which to store the result.
  506. * @returns {Cartesian2} The modified result parameter.
  507. *
  508. * @see Matrix2.multiplyByScale
  509. * @see Matrix2.multiplyByUniformScale
  510. * @see Matrix2.fromScale
  511. * @see Matrix2.fromUniformScale
  512. * @see Matrix2.setScale
  513. * @see Matrix2.setUniformScale
  514. */
  515. Matrix2.getScale = function (matrix, result) {
  516. //>>includeStart('debug', pragmas.debug);
  517. Check.typeOf.object("matrix", matrix);
  518. Check.typeOf.object("result", result);
  519. //>>includeEnd('debug');
  520. result.x = Cartesian2.magnitude(
  521. Cartesian2.fromElements(matrix[0], matrix[1], scratchColumn)
  522. );
  523. result.y = Cartesian2.magnitude(
  524. Cartesian2.fromElements(matrix[2], matrix[3], scratchColumn)
  525. );
  526. return result;
  527. };
  528. const scaleScratch3 = new Cartesian2();
  529. /**
  530. * Computes the maximum scale assuming the matrix is an affine transformation.
  531. * The maximum scale is the maximum length of the column vectors.
  532. *
  533. * @param {Matrix2} matrix The matrix.
  534. * @returns {number} The maximum scale.
  535. */
  536. Matrix2.getMaximumScale = function (matrix) {
  537. Matrix2.getScale(matrix, scaleScratch3);
  538. return Cartesian2.maximumComponent(scaleScratch3);
  539. };
  540. const scaleScratch4 = new Cartesian2();
  541. /**
  542. * Sets the rotation assuming the matrix is an affine transformation.
  543. *
  544. * @param {Matrix2} matrix The matrix.
  545. * @param {Matrix2} rotation The rotation matrix.
  546. * @param {Matrix2} result The object onto which to store the result.
  547. * @returns {Matrix2} The modified result parameter.
  548. *
  549. * @see Matrix2.fromRotation
  550. * @see Matrix2.getRotation
  551. */
  552. Matrix2.setRotation = function (matrix, rotation, result) {
  553. //>>includeStart('debug', pragmas.debug);
  554. Check.typeOf.object("matrix", matrix);
  555. Check.typeOf.object("result", result);
  556. //>>includeEnd('debug');
  557. const scale = Matrix2.getScale(matrix, scaleScratch4);
  558. result[0] = rotation[0] * scale.x;
  559. result[1] = rotation[1] * scale.x;
  560. result[2] = rotation[2] * scale.y;
  561. result[3] = rotation[3] * scale.y;
  562. return result;
  563. };
  564. const scaleScratch5 = new Cartesian2();
  565. /**
  566. * Extracts the rotation matrix assuming the matrix is an affine transformation.
  567. *
  568. * @param {Matrix2} matrix The matrix.
  569. * @param {Matrix2} result The object onto which to store the result.
  570. * @returns {Matrix2} The modified result parameter.
  571. *
  572. * @see Matrix2.setRotation
  573. * @see Matrix2.fromRotation
  574. */
  575. Matrix2.getRotation = function (matrix, result) {
  576. //>>includeStart('debug', pragmas.debug);
  577. Check.typeOf.object("matrix", matrix);
  578. Check.typeOf.object("result", result);
  579. //>>includeEnd('debug');
  580. const scale = Matrix2.getScale(matrix, scaleScratch5);
  581. result[0] = matrix[0] / scale.x;
  582. result[1] = matrix[1] / scale.x;
  583. result[2] = matrix[2] / scale.y;
  584. result[3] = matrix[3] / scale.y;
  585. return result;
  586. };
  587. /**
  588. * Computes the product of two matrices.
  589. *
  590. * @param {Matrix2} left The first matrix.
  591. * @param {Matrix2} right The second matrix.
  592. * @param {Matrix2} result The object onto which to store the result.
  593. * @returns {Matrix2} The modified result parameter.
  594. */
  595. Matrix2.multiply = function (left, right, result) {
  596. //>>includeStart('debug', pragmas.debug);
  597. Check.typeOf.object("left", left);
  598. Check.typeOf.object("right", right);
  599. Check.typeOf.object("result", result);
  600. //>>includeEnd('debug');
  601. const column0Row0 = left[0] * right[0] + left[2] * right[1];
  602. const column1Row0 = left[0] * right[2] + left[2] * right[3];
  603. const column0Row1 = left[1] * right[0] + left[3] * right[1];
  604. const column1Row1 = left[1] * right[2] + left[3] * right[3];
  605. result[0] = column0Row0;
  606. result[1] = column0Row1;
  607. result[2] = column1Row0;
  608. result[3] = column1Row1;
  609. return result;
  610. };
  611. /**
  612. * Computes the sum of two matrices.
  613. *
  614. * @param {Matrix2} left The first matrix.
  615. * @param {Matrix2} right The second matrix.
  616. * @param {Matrix2} result The object onto which to store the result.
  617. * @returns {Matrix2} The modified result parameter.
  618. */
  619. Matrix2.add = function (left, right, result) {
  620. //>>includeStart('debug', pragmas.debug);
  621. Check.typeOf.object("left", left);
  622. Check.typeOf.object("right", right);
  623. Check.typeOf.object("result", result);
  624. //>>includeEnd('debug');
  625. result[0] = left[0] + right[0];
  626. result[1] = left[1] + right[1];
  627. result[2] = left[2] + right[2];
  628. result[3] = left[3] + right[3];
  629. return result;
  630. };
  631. /**
  632. * Computes the difference of two matrices.
  633. *
  634. * @param {Matrix2} left The first matrix.
  635. * @param {Matrix2} right The second matrix.
  636. * @param {Matrix2} result The object onto which to store the result.
  637. * @returns {Matrix2} The modified result parameter.
  638. */
  639. Matrix2.subtract = function (left, right, result) {
  640. //>>includeStart('debug', pragmas.debug);
  641. Check.typeOf.object("left", left);
  642. Check.typeOf.object("right", right);
  643. Check.typeOf.object("result", result);
  644. //>>includeEnd('debug');
  645. result[0] = left[0] - right[0];
  646. result[1] = left[1] - right[1];
  647. result[2] = left[2] - right[2];
  648. result[3] = left[3] - right[3];
  649. return result;
  650. };
  651. /**
  652. * Computes the product of a matrix and a column vector.
  653. *
  654. * @param {Matrix2} matrix The matrix.
  655. * @param {Cartesian2} cartesian The column.
  656. * @param {Cartesian2} result The object onto which to store the result.
  657. * @returns {Cartesian2} The modified result parameter.
  658. */
  659. Matrix2.multiplyByVector = function (matrix, cartesian, result) {
  660. //>>includeStart('debug', pragmas.debug);
  661. Check.typeOf.object("matrix", matrix);
  662. Check.typeOf.object("cartesian", cartesian);
  663. Check.typeOf.object("result", result);
  664. //>>includeEnd('debug');
  665. const x = matrix[0] * cartesian.x + matrix[2] * cartesian.y;
  666. const y = matrix[1] * cartesian.x + matrix[3] * cartesian.y;
  667. result.x = x;
  668. result.y = y;
  669. return result;
  670. };
  671. /**
  672. * Computes the product of a matrix and a scalar.
  673. *
  674. * @param {Matrix2} matrix The matrix.
  675. * @param {number} scalar The number to multiply by.
  676. * @param {Matrix2} result The object onto which to store the result.
  677. * @returns {Matrix2} The modified result parameter.
  678. */
  679. Matrix2.multiplyByScalar = function (matrix, scalar, result) {
  680. //>>includeStart('debug', pragmas.debug);
  681. Check.typeOf.object("matrix", matrix);
  682. Check.typeOf.number("scalar", scalar);
  683. Check.typeOf.object("result", result);
  684. //>>includeEnd('debug');
  685. result[0] = matrix[0] * scalar;
  686. result[1] = matrix[1] * scalar;
  687. result[2] = matrix[2] * scalar;
  688. result[3] = matrix[3] * scalar;
  689. return result;
  690. };
  691. /**
  692. * Computes the product of a matrix times a (non-uniform) scale, as if the scale were a scale matrix.
  693. *
  694. * @param {Matrix2} matrix The matrix on the left-hand side.
  695. * @param {Cartesian2} scale The non-uniform scale on the right-hand side.
  696. * @param {Matrix2} result The object onto which to store the result.
  697. * @returns {Matrix2} The modified result parameter.
  698. *
  699. *
  700. * @example
  701. * // Instead of Cesium.Matrix2.multiply(m, Cesium.Matrix2.fromScale(scale), m);
  702. * Cesium.Matrix2.multiplyByScale(m, scale, m);
  703. *
  704. * @see Matrix2.multiplyByUniformScale
  705. * @see Matrix2.fromScale
  706. * @see Matrix2.fromUniformScale
  707. * @see Matrix2.setScale
  708. * @see Matrix2.setUniformScale
  709. * @see Matrix2.getScale
  710. */
  711. Matrix2.multiplyByScale = function (matrix, scale, result) {
  712. //>>includeStart('debug', pragmas.debug);
  713. Check.typeOf.object("matrix", matrix);
  714. Check.typeOf.object("scale", scale);
  715. Check.typeOf.object("result", result);
  716. //>>includeEnd('debug');
  717. result[0] = matrix[0] * scale.x;
  718. result[1] = matrix[1] * scale.x;
  719. result[2] = matrix[2] * scale.y;
  720. result[3] = matrix[3] * scale.y;
  721. return result;
  722. };
  723. /**
  724. * Computes the product of a matrix times a uniform scale, as if the scale were a scale matrix.
  725. *
  726. * @param {Matrix2} matrix The matrix on the left-hand side.
  727. * @param {number} scale The uniform scale on the right-hand side.
  728. * @param {Matrix2} result The object onto which to store the result.
  729. * @returns {Matrix2} The modified result parameter.
  730. *
  731. * @example
  732. * // Instead of Cesium.Matrix2.multiply(m, Cesium.Matrix2.fromUniformScale(scale), m);
  733. * Cesium.Matrix2.multiplyByUniformScale(m, scale, m);
  734. *
  735. * @see Matrix2.multiplyByScale
  736. * @see Matrix2.fromScale
  737. * @see Matrix2.fromUniformScale
  738. * @see Matrix2.setScale
  739. * @see Matrix2.setUniformScale
  740. * @see Matrix2.getScale
  741. */
  742. Matrix2.multiplyByUniformScale = function (matrix, scale, result) {
  743. //>>includeStart('debug', pragmas.debug);
  744. Check.typeOf.object("matrix", matrix);
  745. Check.typeOf.number("scale", scale);
  746. Check.typeOf.object("result", result);
  747. //>>includeEnd('debug');
  748. result[0] = matrix[0] * scale;
  749. result[1] = matrix[1] * scale;
  750. result[2] = matrix[2] * scale;
  751. result[3] = matrix[3] * scale;
  752. return result;
  753. };
  754. /**
  755. * Creates a negated copy of the provided matrix.
  756. *
  757. * @param {Matrix2} matrix The matrix to negate.
  758. * @param {Matrix2} result The object onto which to store the result.
  759. * @returns {Matrix2} The modified result parameter.
  760. */
  761. Matrix2.negate = function (matrix, result) {
  762. //>>includeStart('debug', pragmas.debug);
  763. Check.typeOf.object("matrix", matrix);
  764. Check.typeOf.object("result", result);
  765. //>>includeEnd('debug');
  766. result[0] = -matrix[0];
  767. result[1] = -matrix[1];
  768. result[2] = -matrix[2];
  769. result[3] = -matrix[3];
  770. return result;
  771. };
  772. /**
  773. * Computes the transpose of the provided matrix.
  774. *
  775. * @param {Matrix2} matrix The matrix to transpose.
  776. * @param {Matrix2} result The object onto which to store the result.
  777. * @returns {Matrix2} The modified result parameter.
  778. */
  779. Matrix2.transpose = function (matrix, result) {
  780. //>>includeStart('debug', pragmas.debug);
  781. Check.typeOf.object("matrix", matrix);
  782. Check.typeOf.object("result", result);
  783. //>>includeEnd('debug');
  784. const column0Row0 = matrix[0];
  785. const column0Row1 = matrix[2];
  786. const column1Row0 = matrix[1];
  787. const column1Row1 = matrix[3];
  788. result[0] = column0Row0;
  789. result[1] = column0Row1;
  790. result[2] = column1Row0;
  791. result[3] = column1Row1;
  792. return result;
  793. };
  794. /**
  795. * Computes a matrix, which contains the absolute (unsigned) values of the provided matrix's elements.
  796. *
  797. * @param {Matrix2} matrix The matrix with signed elements.
  798. * @param {Matrix2} result The object onto which to store the result.
  799. * @returns {Matrix2} The modified result parameter.
  800. */
  801. Matrix2.abs = function (matrix, result) {
  802. //>>includeStart('debug', pragmas.debug);
  803. Check.typeOf.object("matrix", matrix);
  804. Check.typeOf.object("result", result);
  805. //>>includeEnd('debug');
  806. result[0] = Math.abs(matrix[0]);
  807. result[1] = Math.abs(matrix[1]);
  808. result[2] = Math.abs(matrix[2]);
  809. result[3] = Math.abs(matrix[3]);
  810. return result;
  811. };
  812. /**
  813. * Compares the provided matrices componentwise and returns
  814. * <code>true</code> if they are equal, <code>false</code> otherwise.
  815. *
  816. * @param {Matrix2} [left] The first matrix.
  817. * @param {Matrix2} [right] The second matrix.
  818. * @returns {boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
  819. */
  820. Matrix2.equals = function (left, right) {
  821. return (
  822. left === right ||
  823. (defined(left) &&
  824. defined(right) &&
  825. left[0] === right[0] &&
  826. left[1] === right[1] &&
  827. left[2] === right[2] &&
  828. left[3] === right[3])
  829. );
  830. };
  831. /**
  832. * @private
  833. */
  834. Matrix2.equalsArray = function (matrix, array, offset) {
  835. return (
  836. matrix[0] === array[offset] &&
  837. matrix[1] === array[offset + 1] &&
  838. matrix[2] === array[offset + 2] &&
  839. matrix[3] === array[offset + 3]
  840. );
  841. };
  842. /**
  843. * Compares the provided matrices componentwise and returns
  844. * <code>true</code> if they are within the provided epsilon,
  845. * <code>false</code> otherwise.
  846. *
  847. * @param {Matrix2} [left] The first matrix.
  848. * @param {Matrix2} [right] The second matrix.
  849. * @param {number} [epsilon=0] The epsilon to use for equality testing.
  850. * @returns {boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
  851. */
  852. Matrix2.equalsEpsilon = function (left, right, epsilon) {
  853. epsilon = defaultValue(epsilon, 0);
  854. return (
  855. left === right ||
  856. (defined(left) &&
  857. defined(right) &&
  858. Math.abs(left[0] - right[0]) <= epsilon &&
  859. Math.abs(left[1] - right[1]) <= epsilon &&
  860. Math.abs(left[2] - right[2]) <= epsilon &&
  861. Math.abs(left[3] - right[3]) <= epsilon)
  862. );
  863. };
  864. /**
  865. * An immutable Matrix2 instance initialized to the identity matrix.
  866. *
  867. * @type {Matrix2}
  868. * @constant
  869. */
  870. Matrix2.IDENTITY = Object.freeze(new Matrix2(1.0, 0.0, 0.0, 1.0));
  871. /**
  872. * An immutable Matrix2 instance initialized to the zero matrix.
  873. *
  874. * @type {Matrix2}
  875. * @constant
  876. */
  877. Matrix2.ZERO = Object.freeze(new Matrix2(0.0, 0.0, 0.0, 0.0));
  878. /**
  879. * The index into Matrix2 for column 0, row 0.
  880. *
  881. * @type {number}
  882. * @constant
  883. *
  884. * @example
  885. * const matrix = new Cesium.Matrix2();
  886. * matrix[Cesium.Matrix2.COLUMN0ROW0] = 5.0; // set column 0, row 0 to 5.0
  887. */
  888. Matrix2.COLUMN0ROW0 = 0;
  889. /**
  890. * The index into Matrix2 for column 0, row 1.
  891. *
  892. * @type {number}
  893. * @constant
  894. *
  895. * @example
  896. * const matrix = new Cesium.Matrix2();
  897. * matrix[Cesium.Matrix2.COLUMN0ROW1] = 5.0; // set column 0, row 1 to 5.0
  898. */
  899. Matrix2.COLUMN0ROW1 = 1;
  900. /**
  901. * The index into Matrix2 for column 1, row 0.
  902. *
  903. * @type {number}
  904. * @constant
  905. *
  906. * @example
  907. * const matrix = new Cesium.Matrix2();
  908. * matrix[Cesium.Matrix2.COLUMN1ROW0] = 5.0; // set column 1, row 0 to 5.0
  909. */
  910. Matrix2.COLUMN1ROW0 = 2;
  911. /**
  912. * The index into Matrix2 for column 1, row 1.
  913. *
  914. * @type {number}
  915. * @constant
  916. *
  917. * @example
  918. * const matrix = new Cesium.Matrix2();
  919. * matrix[Cesium.Matrix2.COLUMN1ROW1] = 5.0; // set column 1, row 1 to 5.0
  920. */
  921. Matrix2.COLUMN1ROW1 = 3;
  922. Object.defineProperties(Matrix2.prototype, {
  923. /**
  924. * Gets the number of items in the collection.
  925. * @memberof Matrix2.prototype
  926. *
  927. * @type {number}
  928. */
  929. length: {
  930. get: function () {
  931. return Matrix2.packedLength;
  932. },
  933. },
  934. });
  935. /**
  936. * Duplicates the provided Matrix2 instance.
  937. *
  938. * @param {Matrix2} [result] The object onto which to store the result.
  939. * @returns {Matrix2} The modified result parameter or a new Matrix2 instance if one was not provided.
  940. */
  941. Matrix2.prototype.clone = function (result) {
  942. return Matrix2.clone(this, result);
  943. };
  944. /**
  945. * Compares this matrix to the provided matrix componentwise and returns
  946. * <code>true</code> if they are equal, <code>false</code> otherwise.
  947. *
  948. * @param {Matrix2} [right] The right hand side matrix.
  949. * @returns {boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
  950. */
  951. Matrix2.prototype.equals = function (right) {
  952. return Matrix2.equals(this, right);
  953. };
  954. /**
  955. * Compares this matrix to the provided matrix componentwise and returns
  956. * <code>true</code> if they are within the provided epsilon,
  957. * <code>false</code> otherwise.
  958. *
  959. * @param {Matrix2} [right] The right hand side matrix.
  960. * @param {number} [epsilon=0] The epsilon to use for equality testing.
  961. * @returns {boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
  962. */
  963. Matrix2.prototype.equalsEpsilon = function (right, epsilon) {
  964. return Matrix2.equalsEpsilon(this, right, epsilon);
  965. };
  966. /**
  967. * Creates a string representing this Matrix with each row being
  968. * on a separate line and in the format '(column0, column1)'.
  969. *
  970. * @returns {string} A string representing the provided Matrix with each row being on a separate line and in the format '(column0, column1)'.
  971. */
  972. Matrix2.prototype.toString = function () {
  973. return `(${this[0]}, ${this[2]})\n` + `(${this[1]}, ${this[3]})`;
  974. };
  975. export default Matrix2;