Matrix2.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  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. * @returns {Matrix2} The modified result parameter.
  547. *
  548. * @see Matrix2.fromRotation
  549. * @see Matrix2.getRotation
  550. */
  551. Matrix2.setRotation = function (matrix, rotation, result) {
  552. //>>includeStart('debug', pragmas.debug);
  553. Check.typeOf.object("matrix", matrix);
  554. Check.typeOf.object("result", result);
  555. //>>includeEnd('debug');
  556. const scale = Matrix2.getScale(matrix, scaleScratch4);
  557. result[0] = rotation[0] * scale.x;
  558. result[1] = rotation[1] * scale.x;
  559. result[2] = rotation[2] * scale.y;
  560. result[3] = rotation[3] * scale.y;
  561. return result;
  562. };
  563. const scaleScratch5 = new Cartesian2();
  564. /**
  565. * Extracts the rotation matrix assuming the matrix is an affine transformation.
  566. *
  567. * @param {Matrix2} matrix The matrix.
  568. * @param {Matrix2} result The object onto which to store the result.
  569. * @returns {Matrix2} The modified result parameter.
  570. *
  571. * @see Matrix2.setRotation
  572. * @see Matrix2.fromRotation
  573. */
  574. Matrix2.getRotation = function (matrix, result) {
  575. //>>includeStart('debug', pragmas.debug);
  576. Check.typeOf.object("matrix", matrix);
  577. Check.typeOf.object("result", result);
  578. //>>includeEnd('debug');
  579. const scale = Matrix2.getScale(matrix, scaleScratch5);
  580. result[0] = matrix[0] / scale.x;
  581. result[1] = matrix[1] / scale.x;
  582. result[2] = matrix[2] / scale.y;
  583. result[3] = matrix[3] / scale.y;
  584. return result;
  585. };
  586. /**
  587. * Computes the product of two matrices.
  588. *
  589. * @param {Matrix2} left The first matrix.
  590. * @param {Matrix2} right The second matrix.
  591. * @param {Matrix2} result The object onto which to store the result.
  592. * @returns {Matrix2} The modified result parameter.
  593. */
  594. Matrix2.multiply = function (left, right, result) {
  595. //>>includeStart('debug', pragmas.debug);
  596. Check.typeOf.object("left", left);
  597. Check.typeOf.object("right", right);
  598. Check.typeOf.object("result", result);
  599. //>>includeEnd('debug');
  600. const column0Row0 = left[0] * right[0] + left[2] * right[1];
  601. const column1Row0 = left[0] * right[2] + left[2] * right[3];
  602. const column0Row1 = left[1] * right[0] + left[3] * right[1];
  603. const column1Row1 = left[1] * right[2] + left[3] * right[3];
  604. result[0] = column0Row0;
  605. result[1] = column0Row1;
  606. result[2] = column1Row0;
  607. result[3] = column1Row1;
  608. return result;
  609. };
  610. /**
  611. * Computes the sum of two matrices.
  612. *
  613. * @param {Matrix2} left The first matrix.
  614. * @param {Matrix2} right The second matrix.
  615. * @param {Matrix2} result The object onto which to store the result.
  616. * @returns {Matrix2} The modified result parameter.
  617. */
  618. Matrix2.add = function (left, right, result) {
  619. //>>includeStart('debug', pragmas.debug);
  620. Check.typeOf.object("left", left);
  621. Check.typeOf.object("right", right);
  622. Check.typeOf.object("result", result);
  623. //>>includeEnd('debug');
  624. result[0] = left[0] + right[0];
  625. result[1] = left[1] + right[1];
  626. result[2] = left[2] + right[2];
  627. result[3] = left[3] + right[3];
  628. return result;
  629. };
  630. /**
  631. * Computes the difference of two matrices.
  632. *
  633. * @param {Matrix2} left The first matrix.
  634. * @param {Matrix2} right The second matrix.
  635. * @param {Matrix2} result The object onto which to store the result.
  636. * @returns {Matrix2} The modified result parameter.
  637. */
  638. Matrix2.subtract = function (left, right, result) {
  639. //>>includeStart('debug', pragmas.debug);
  640. Check.typeOf.object("left", left);
  641. Check.typeOf.object("right", right);
  642. Check.typeOf.object("result", result);
  643. //>>includeEnd('debug');
  644. result[0] = left[0] - right[0];
  645. result[1] = left[1] - right[1];
  646. result[2] = left[2] - right[2];
  647. result[3] = left[3] - right[3];
  648. return result;
  649. };
  650. /**
  651. * Computes the product of a matrix and a column vector.
  652. *
  653. * @param {Matrix2} matrix The matrix.
  654. * @param {Cartesian2} cartesian The column.
  655. * @param {Cartesian2} result The object onto which to store the result.
  656. * @returns {Cartesian2} The modified result parameter.
  657. */
  658. Matrix2.multiplyByVector = function (matrix, cartesian, result) {
  659. //>>includeStart('debug', pragmas.debug);
  660. Check.typeOf.object("matrix", matrix);
  661. Check.typeOf.object("cartesian", cartesian);
  662. Check.typeOf.object("result", result);
  663. //>>includeEnd('debug');
  664. const x = matrix[0] * cartesian.x + matrix[2] * cartesian.y;
  665. const y = matrix[1] * cartesian.x + matrix[3] * cartesian.y;
  666. result.x = x;
  667. result.y = y;
  668. return result;
  669. };
  670. /**
  671. * Computes the product of a matrix and a scalar.
  672. *
  673. * @param {Matrix2} matrix The matrix.
  674. * @param {Number} scalar The number to multiply by.
  675. * @param {Matrix2} result The object onto which to store the result.
  676. * @returns {Matrix2} The modified result parameter.
  677. */
  678. Matrix2.multiplyByScalar = function (matrix, scalar, result) {
  679. //>>includeStart('debug', pragmas.debug);
  680. Check.typeOf.object("matrix", matrix);
  681. Check.typeOf.number("scalar", scalar);
  682. Check.typeOf.object("result", result);
  683. //>>includeEnd('debug');
  684. result[0] = matrix[0] * scalar;
  685. result[1] = matrix[1] * scalar;
  686. result[2] = matrix[2] * scalar;
  687. result[3] = matrix[3] * scalar;
  688. return result;
  689. };
  690. /**
  691. * Computes the product of a matrix times a (non-uniform) scale, as if the scale were a scale matrix.
  692. *
  693. * @param {Matrix2} matrix The matrix on the left-hand side.
  694. * @param {Number} scale The non-uniform scale on the right-hand side.
  695. * @param {Matrix2} result The object onto which to store the result.
  696. * @returns {Matrix2} The modified result parameter.
  697. *
  698. *
  699. * @example
  700. * // Instead of Cesium.Matrix2.multiply(m, Cesium.Matrix2.fromScale(scale), m);
  701. * Cesium.Matrix2.multiplyByScale(m, scale, m);
  702. *
  703. * @see Matrix2.multiplyByUniformScale
  704. * @see Matrix2.fromScale
  705. * @see Matrix2.fromUniformScale
  706. * @see Matrix2.setScale
  707. * @see Matrix2.setUniformScale
  708. * @see Matrix2.getScale
  709. */
  710. Matrix2.multiplyByScale = function (matrix, scale, result) {
  711. //>>includeStart('debug', pragmas.debug);
  712. Check.typeOf.object("matrix", matrix);
  713. Check.typeOf.object("scale", scale);
  714. Check.typeOf.object("result", result);
  715. //>>includeEnd('debug');
  716. result[0] = matrix[0] * scale.x;
  717. result[1] = matrix[1] * scale.x;
  718. result[2] = matrix[2] * scale.y;
  719. result[3] = matrix[3] * scale.y;
  720. return result;
  721. };
  722. /**
  723. * Computes the product of a matrix times a uniform scale, as if the scale were a scale matrix.
  724. *
  725. * @param {Matrix2} matrix The matrix on the left-hand side.
  726. * @param {Number} scale The uniform scale on the right-hand side.
  727. * @param {Matrix2} result The object onto which to store the result.
  728. * @returns {Matrix2} The modified result parameter.
  729. *
  730. * @example
  731. * // Instead of Cesium.Matrix2.multiply(m, Cesium.Matrix2.fromUniformScale(scale), m);
  732. * Cesium.Matrix2.multiplyByUniformScale(m, scale, m);
  733. *
  734. * @see Matrix2.multiplyByScale
  735. * @see Matrix2.fromScale
  736. * @see Matrix2.fromUniformScale
  737. * @see Matrix2.setScale
  738. * @see Matrix2.setUniformScale
  739. * @see Matrix2.getScale
  740. */
  741. Matrix2.multiplyByUniformScale = function (matrix, scale, result) {
  742. //>>includeStart('debug', pragmas.debug);
  743. Check.typeOf.object("matrix", matrix);
  744. Check.typeOf.number("scale", scale);
  745. Check.typeOf.object("result", result);
  746. //>>includeEnd('debug');
  747. result[0] = matrix[0] * scale;
  748. result[1] = matrix[1] * scale;
  749. result[2] = matrix[2] * scale;
  750. result[3] = matrix[3] * scale;
  751. return result;
  752. };
  753. /**
  754. * Creates a negated copy of the provided matrix.
  755. *
  756. * @param {Matrix2} matrix The matrix to negate.
  757. * @param {Matrix2} result The object onto which to store the result.
  758. * @returns {Matrix2} The modified result parameter.
  759. */
  760. Matrix2.negate = function (matrix, result) {
  761. //>>includeStart('debug', pragmas.debug);
  762. Check.typeOf.object("matrix", matrix);
  763. Check.typeOf.object("result", result);
  764. //>>includeEnd('debug');
  765. result[0] = -matrix[0];
  766. result[1] = -matrix[1];
  767. result[2] = -matrix[2];
  768. result[3] = -matrix[3];
  769. return result;
  770. };
  771. /**
  772. * Computes the transpose of the provided matrix.
  773. *
  774. * @param {Matrix2} matrix The matrix to transpose.
  775. * @param {Matrix2} result The object onto which to store the result.
  776. * @returns {Matrix2} The modified result parameter.
  777. */
  778. Matrix2.transpose = function (matrix, result) {
  779. //>>includeStart('debug', pragmas.debug);
  780. Check.typeOf.object("matrix", matrix);
  781. Check.typeOf.object("result", result);
  782. //>>includeEnd('debug');
  783. const column0Row0 = matrix[0];
  784. const column0Row1 = matrix[2];
  785. const column1Row0 = matrix[1];
  786. const column1Row1 = matrix[3];
  787. result[0] = column0Row0;
  788. result[1] = column0Row1;
  789. result[2] = column1Row0;
  790. result[3] = column1Row1;
  791. return result;
  792. };
  793. /**
  794. * Computes a matrix, which contains the absolute (unsigned) values of the provided matrix's elements.
  795. *
  796. * @param {Matrix2} matrix The matrix with signed elements.
  797. * @param {Matrix2} result The object onto which to store the result.
  798. * @returns {Matrix2} The modified result parameter.
  799. */
  800. Matrix2.abs = function (matrix, result) {
  801. //>>includeStart('debug', pragmas.debug);
  802. Check.typeOf.object("matrix", matrix);
  803. Check.typeOf.object("result", result);
  804. //>>includeEnd('debug');
  805. result[0] = Math.abs(matrix[0]);
  806. result[1] = Math.abs(matrix[1]);
  807. result[2] = Math.abs(matrix[2]);
  808. result[3] = Math.abs(matrix[3]);
  809. return result;
  810. };
  811. /**
  812. * Compares the provided matrices componentwise and returns
  813. * <code>true</code> if they are equal, <code>false</code> otherwise.
  814. *
  815. * @param {Matrix2} [left] The first matrix.
  816. * @param {Matrix2} [right] The second matrix.
  817. * @returns {Boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
  818. */
  819. Matrix2.equals = function (left, right) {
  820. return (
  821. left === right ||
  822. (defined(left) &&
  823. defined(right) &&
  824. left[0] === right[0] &&
  825. left[1] === right[1] &&
  826. left[2] === right[2] &&
  827. left[3] === right[3])
  828. );
  829. };
  830. /**
  831. * @private
  832. */
  833. Matrix2.equalsArray = function (matrix, array, offset) {
  834. return (
  835. matrix[0] === array[offset] &&
  836. matrix[1] === array[offset + 1] &&
  837. matrix[2] === array[offset + 2] &&
  838. matrix[3] === array[offset + 3]
  839. );
  840. };
  841. /**
  842. * Compares the provided matrices componentwise and returns
  843. * <code>true</code> if they are within the provided epsilon,
  844. * <code>false</code> otherwise.
  845. *
  846. * @param {Matrix2} [left] The first matrix.
  847. * @param {Matrix2} [right] The second matrix.
  848. * @param {Number} [epsilon=0] The epsilon to use for equality testing.
  849. * @returns {Boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
  850. */
  851. Matrix2.equalsEpsilon = function (left, right, epsilon) {
  852. epsilon = defaultValue(epsilon, 0);
  853. return (
  854. left === right ||
  855. (defined(left) &&
  856. defined(right) &&
  857. Math.abs(left[0] - right[0]) <= epsilon &&
  858. Math.abs(left[1] - right[1]) <= epsilon &&
  859. Math.abs(left[2] - right[2]) <= epsilon &&
  860. Math.abs(left[3] - right[3]) <= epsilon)
  861. );
  862. };
  863. /**
  864. * An immutable Matrix2 instance initialized to the identity matrix.
  865. *
  866. * @type {Matrix2}
  867. * @constant
  868. */
  869. Matrix2.IDENTITY = Object.freeze(new Matrix2(1.0, 0.0, 0.0, 1.0));
  870. /**
  871. * An immutable Matrix2 instance initialized to the zero matrix.
  872. *
  873. * @type {Matrix2}
  874. * @constant
  875. */
  876. Matrix2.ZERO = Object.freeze(new Matrix2(0.0, 0.0, 0.0, 0.0));
  877. /**
  878. * The index into Matrix2 for column 0, row 0.
  879. *
  880. * @type {Number}
  881. * @constant
  882. *
  883. * @example
  884. * const matrix = new Cesium.Matrix2();
  885. * matrix[Cesium.Matrix2.COLUMN0ROW0] = 5.0; // set column 0, row 0 to 5.0
  886. */
  887. Matrix2.COLUMN0ROW0 = 0;
  888. /**
  889. * The index into Matrix2 for column 0, row 1.
  890. *
  891. * @type {Number}
  892. * @constant
  893. *
  894. * @example
  895. * const matrix = new Cesium.Matrix2();
  896. * matrix[Cesium.Matrix2.COLUMN0ROW1] = 5.0; // set column 0, row 1 to 5.0
  897. */
  898. Matrix2.COLUMN0ROW1 = 1;
  899. /**
  900. * The index into Matrix2 for column 1, row 0.
  901. *
  902. * @type {Number}
  903. * @constant
  904. *
  905. * @example
  906. * const matrix = new Cesium.Matrix2();
  907. * matrix[Cesium.Matrix2.COLUMN1ROW0] = 5.0; // set column 1, row 0 to 5.0
  908. */
  909. Matrix2.COLUMN1ROW0 = 2;
  910. /**
  911. * The index into Matrix2 for column 1, row 1.
  912. *
  913. * @type {Number}
  914. * @constant
  915. *
  916. * @example
  917. * const matrix = new Cesium.Matrix2();
  918. * matrix[Cesium.Matrix2.COLUMN1ROW1] = 5.0; // set column 1, row 1 to 5.0
  919. */
  920. Matrix2.COLUMN1ROW1 = 3;
  921. Object.defineProperties(Matrix2.prototype, {
  922. /**
  923. * Gets the number of items in the collection.
  924. * @memberof Matrix2.prototype
  925. *
  926. * @type {Number}
  927. */
  928. length: {
  929. get: function () {
  930. return Matrix2.packedLength;
  931. },
  932. },
  933. });
  934. /**
  935. * Duplicates the provided Matrix2 instance.
  936. *
  937. * @param {Matrix2} [result] The object onto which to store the result.
  938. * @returns {Matrix2} The modified result parameter or a new Matrix2 instance if one was not provided.
  939. */
  940. Matrix2.prototype.clone = function (result) {
  941. return Matrix2.clone(this, result);
  942. };
  943. /**
  944. * Compares this matrix to the provided matrix componentwise and returns
  945. * <code>true</code> if they are equal, <code>false</code> otherwise.
  946. *
  947. * @param {Matrix2} [right] The right hand side matrix.
  948. * @returns {Boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
  949. */
  950. Matrix2.prototype.equals = function (right) {
  951. return Matrix2.equals(this, right);
  952. };
  953. /**
  954. * Compares this matrix to the provided matrix componentwise and returns
  955. * <code>true</code> if they are within the provided epsilon,
  956. * <code>false</code> otherwise.
  957. *
  958. * @param {Matrix2} [right] The right hand side matrix.
  959. * @param {Number} [epsilon=0] The epsilon to use for equality testing.
  960. * @returns {Boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
  961. */
  962. Matrix2.prototype.equalsEpsilon = function (right, epsilon) {
  963. return Matrix2.equalsEpsilon(this, right, epsilon);
  964. };
  965. /**
  966. * Creates a string representing this Matrix with each row being
  967. * on a separate line and in the format '(column0, column1)'.
  968. *
  969. * @returns {String} A string representing the provided Matrix with each row being on a separate line and in the format '(column0, column1)'.
  970. */
  971. Matrix2.prototype.toString = function () {
  972. return `(${this[0]}, ${this[2]})\n` + `(${this[1]}, ${this[3]})`;
  973. };
  974. export default Matrix2;