rotationMatrix.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.createRotationMatrix = void 0;
  6. var _is = require("../../utils/is.js");
  7. var _factory = require("../../utils/factory.js");
  8. var name = 'rotationMatrix';
  9. var dependencies = ['typed', 'config', 'multiplyScalar', 'addScalar', 'unaryMinus', 'norm', 'matrix', 'BigNumber', 'DenseMatrix', 'SparseMatrix', 'cos', 'sin'];
  10. var createRotationMatrix = /* #__PURE__ */(0, _factory.factory)(name, dependencies, function (_ref) {
  11. var typed = _ref.typed,
  12. config = _ref.config,
  13. multiplyScalar = _ref.multiplyScalar,
  14. addScalar = _ref.addScalar,
  15. unaryMinus = _ref.unaryMinus,
  16. norm = _ref.norm,
  17. BigNumber = _ref.BigNumber,
  18. matrix = _ref.matrix,
  19. DenseMatrix = _ref.DenseMatrix,
  20. SparseMatrix = _ref.SparseMatrix,
  21. cos = _ref.cos,
  22. sin = _ref.sin;
  23. /**
  24. * Create a 2-dimensional counter-clockwise rotation matrix (2x2) for a given angle (expressed in radians).
  25. * Create a 2-dimensional counter-clockwise rotation matrix (3x3) by a given angle (expressed in radians) around a given axis (1x3).
  26. *
  27. * Syntax:
  28. *
  29. * math.rotationMatrix(theta)
  30. * math.rotationMatrix(theta, format)
  31. * math.rotationMatrix(theta, [v])
  32. * math.rotationMatrix(theta, [v], format)
  33. *
  34. * Examples:
  35. *
  36. * math.rotationMatrix(math.pi / 2) // returns [[0, -1], [1, 0]]
  37. * math.rotationMatrix(math.bignumber(1)) // returns [[bignumber(cos(1)), bignumber(-sin(1))], [bignumber(sin(1)), bignumber(cos(1))]]
  38. * math.rotationMatrix(math.complex(1 + i)) // returns [[cos(1 + i), -sin(1 + i)], [sin(1 + i), cos(1 + i)]]
  39. * math.rotationMatrix(math.unit('1rad')) // returns [[cos(1), -sin(1)], [sin(1), cos(1)]]
  40. *
  41. * math.rotationMatrix(math.pi / 2, [0, 1, 0]) // returns [[0, 0, 1], [0, 1, 0], [-1, 0, 0]]
  42. * math.rotationMatrix(math.pi / 2, matrix([0, 1, 0])) // returns matrix([[0, 0, 1], [0, 1, 0], [-1, 0, 0]])
  43. *
  44. *
  45. * See also:
  46. *
  47. * matrix, cos, sin
  48. *
  49. *
  50. * @param {number | BigNumber | Complex | Unit} theta Rotation angle
  51. * @param {Array | Matrix} [v] Rotation axis
  52. * @param {string} [format] Result Matrix storage format
  53. * @return {Array | Matrix} Rotation matrix
  54. */
  55. return typed(name, {
  56. '': function _() {
  57. return config.matrix === 'Matrix' ? matrix([]) : [];
  58. },
  59. string: function string(format) {
  60. return matrix(format);
  61. },
  62. 'number | BigNumber | Complex | Unit': function numberBigNumberComplexUnit(theta) {
  63. return _rotationMatrix2x2(theta, config.matrix === 'Matrix' ? 'dense' : undefined);
  64. },
  65. 'number | BigNumber | Complex | Unit, string': function numberBigNumberComplexUnitString(theta, format) {
  66. return _rotationMatrix2x2(theta, format);
  67. },
  68. 'number | BigNumber | Complex | Unit, Array': function numberBigNumberComplexUnitArray(theta, v) {
  69. var matrixV = matrix(v);
  70. _validateVector(matrixV);
  71. return _rotationMatrix3x3(theta, matrixV, undefined);
  72. },
  73. 'number | BigNumber | Complex | Unit, Matrix': function numberBigNumberComplexUnitMatrix(theta, v) {
  74. _validateVector(v);
  75. var storageType = v.storage() || (config.matrix === 'Matrix' ? 'dense' : undefined);
  76. return _rotationMatrix3x3(theta, v, storageType);
  77. },
  78. 'number | BigNumber | Complex | Unit, Array, string': function numberBigNumberComplexUnitArrayString(theta, v, format) {
  79. var matrixV = matrix(v);
  80. _validateVector(matrixV);
  81. return _rotationMatrix3x3(theta, matrixV, format);
  82. },
  83. 'number | BigNumber | Complex | Unit, Matrix, string': function numberBigNumberComplexUnitMatrixString(theta, v, format) {
  84. _validateVector(v);
  85. return _rotationMatrix3x3(theta, v, format);
  86. }
  87. });
  88. /**
  89. * Returns 2x2 matrix of 2D rotation of angle theta
  90. *
  91. * @param {number | BigNumber | Complex | Unit} theta The rotation angle
  92. * @param {string} format The result Matrix storage format
  93. * @returns {Matrix}
  94. * @private
  95. */
  96. function _rotationMatrix2x2(theta, format) {
  97. var Big = (0, _is.isBigNumber)(theta);
  98. var minusOne = Big ? new BigNumber(-1) : -1;
  99. var cosTheta = cos(theta);
  100. var sinTheta = sin(theta);
  101. var data = [[cosTheta, multiplyScalar(minusOne, sinTheta)], [sinTheta, cosTheta]];
  102. return _convertToFormat(data, format);
  103. }
  104. function _validateVector(v) {
  105. var size = v.size();
  106. if (size.length < 1 || size[0] !== 3) {
  107. throw new RangeError('Vector must be of dimensions 1x3');
  108. }
  109. }
  110. function _mul(array) {
  111. return array.reduce(function (p, curr) {
  112. return multiplyScalar(p, curr);
  113. });
  114. }
  115. function _convertToFormat(data, format) {
  116. if (format) {
  117. if (format === 'sparse') {
  118. return new SparseMatrix(data);
  119. }
  120. if (format === 'dense') {
  121. return new DenseMatrix(data);
  122. }
  123. throw new TypeError("Unknown matrix type \"".concat(format, "\""));
  124. }
  125. return data;
  126. }
  127. /**
  128. * Returns a 3x3 matrix of rotation of angle theta around vector v
  129. *
  130. * @param {number | BigNumber | Complex | Unit} theta The rotation angle
  131. * @param {Matrix} v The rotation axis vector
  132. * @param {string} format The storage format of the resulting matrix
  133. * @returns {Matrix}
  134. * @private
  135. */
  136. function _rotationMatrix3x3(theta, v, format) {
  137. var normV = norm(v);
  138. if (normV === 0) {
  139. throw new RangeError('Rotation around zero vector');
  140. }
  141. var Big = (0, _is.isBigNumber)(theta) ? BigNumber : null;
  142. var one = Big ? new Big(1) : 1;
  143. var minusOne = Big ? new Big(-1) : -1;
  144. var vx = Big ? new Big(v.get([0]) / normV) : v.get([0]) / normV;
  145. var vy = Big ? new Big(v.get([1]) / normV) : v.get([1]) / normV;
  146. var vz = Big ? new Big(v.get([2]) / normV) : v.get([2]) / normV;
  147. var c = cos(theta);
  148. var oneMinusC = addScalar(one, unaryMinus(c));
  149. var s = sin(theta);
  150. var r11 = addScalar(c, _mul([vx, vx, oneMinusC]));
  151. var r12 = addScalar(_mul([vx, vy, oneMinusC]), _mul([minusOne, vz, s]));
  152. var r13 = addScalar(_mul([vx, vz, oneMinusC]), _mul([vy, s]));
  153. var r21 = addScalar(_mul([vx, vy, oneMinusC]), _mul([vz, s]));
  154. var r22 = addScalar(c, _mul([vy, vy, oneMinusC]));
  155. var r23 = addScalar(_mul([vy, vz, oneMinusC]), _mul([minusOne, vx, s]));
  156. var r31 = addScalar(_mul([vx, vz, oneMinusC]), _mul([minusOne, vy, s]));
  157. var r32 = addScalar(_mul([vy, vz, oneMinusC]), _mul([vx, s]));
  158. var r33 = addScalar(c, _mul([vz, vz, oneMinusC]));
  159. var data = [[r11, r12, r13], [r21, r22, r23], [r31, r32, r33]];
  160. return _convertToFormat(data, format);
  161. }
  162. });
  163. exports.createRotationMatrix = createRotationMatrix;