@itwin/core-geometry 3.6.0-dev.8 → 4.0.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/CHANGELOG.md +28 -1
  2. package/LICENSE.md +1 -1
  3. package/lib/cjs/Geometry.d.ts +25 -14
  4. package/lib/cjs/Geometry.d.ts.map +1 -1
  5. package/lib/cjs/Geometry.js +25 -14
  6. package/lib/cjs/Geometry.js.map +1 -1
  7. package/lib/cjs/curve/CurveChainWithDistanceIndex.d.ts +10 -6
  8. package/lib/cjs/curve/CurveChainWithDistanceIndex.d.ts.map +1 -1
  9. package/lib/cjs/curve/CurveChainWithDistanceIndex.js +10 -19
  10. package/lib/cjs/curve/CurveChainWithDistanceIndex.js.map +1 -1
  11. package/lib/cjs/geometry3d/Angle.d.ts +1 -0
  12. package/lib/cjs/geometry3d/Angle.d.ts.map +1 -1
  13. package/lib/cjs/geometry3d/Angle.js +1 -0
  14. package/lib/cjs/geometry3d/Angle.js.map +1 -1
  15. package/lib/cjs/geometry3d/AngleSweep.d.ts +1 -0
  16. package/lib/cjs/geometry3d/AngleSweep.d.ts.map +1 -1
  17. package/lib/cjs/geometry3d/AngleSweep.js +1 -0
  18. package/lib/cjs/geometry3d/AngleSweep.js.map +1 -1
  19. package/lib/cjs/geometry3d/GrowableXYArray.d.ts +1 -1
  20. package/lib/cjs/geometry3d/GrowableXYArray.js +1 -1
  21. package/lib/cjs/geometry3d/GrowableXYArray.js.map +1 -1
  22. package/lib/cjs/geometry3d/Matrix3d.d.ts +221 -159
  23. package/lib/cjs/geometry3d/Matrix3d.d.ts.map +1 -1
  24. package/lib/cjs/geometry3d/Matrix3d.js +365 -249
  25. package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
  26. package/lib/cjs/geometry3d/OrderedRotationAngles.d.ts +71 -14
  27. package/lib/cjs/geometry3d/OrderedRotationAngles.d.ts.map +1 -1
  28. package/lib/cjs/geometry3d/OrderedRotationAngles.js +204 -114
  29. package/lib/cjs/geometry3d/OrderedRotationAngles.js.map +1 -1
  30. package/lib/cjs/geometry3d/Point2dVector2d.d.ts +1 -0
  31. package/lib/cjs/geometry3d/Point2dVector2d.d.ts.map +1 -1
  32. package/lib/cjs/geometry3d/Point2dVector2d.js +1 -0
  33. package/lib/cjs/geometry3d/Point2dVector2d.js.map +1 -1
  34. package/lib/cjs/geometry3d/Point3dVector3d.d.ts +4 -3
  35. package/lib/cjs/geometry3d/Point3dVector3d.d.ts.map +1 -1
  36. package/lib/cjs/geometry3d/Point3dVector3d.js +6 -5
  37. package/lib/cjs/geometry3d/Point3dVector3d.js.map +1 -1
  38. package/lib/cjs/geometry3d/YawPitchRollAngles.d.ts +49 -25
  39. package/lib/cjs/geometry3d/YawPitchRollAngles.d.ts.map +1 -1
  40. package/lib/cjs/geometry3d/YawPitchRollAngles.js +146 -50
  41. package/lib/cjs/geometry3d/YawPitchRollAngles.js.map +1 -1
  42. package/lib/cjs/polyface/PolyfaceBuilder.d.ts +4 -4
  43. package/lib/cjs/polyface/PolyfaceBuilder.js +4 -4
  44. package/lib/cjs/polyface/PolyfaceBuilder.js.map +1 -1
  45. package/lib/cjs/polyface/PolyfaceQuery.d.ts +28 -0
  46. package/lib/cjs/polyface/PolyfaceQuery.d.ts.map +1 -1
  47. package/lib/cjs/polyface/PolyfaceQuery.js +79 -0
  48. package/lib/cjs/polyface/PolyfaceQuery.js.map +1 -1
  49. package/lib/cjs/serialization/IModelJsonSchema.d.ts +1 -1
  50. package/lib/cjs/serialization/IModelJsonSchema.js.map +1 -1
  51. package/lib/esm/Geometry.d.ts +25 -14
  52. package/lib/esm/Geometry.d.ts.map +1 -1
  53. package/lib/esm/Geometry.js +25 -14
  54. package/lib/esm/Geometry.js.map +1 -1
  55. package/lib/esm/curve/CurveChainWithDistanceIndex.d.ts +10 -6
  56. package/lib/esm/curve/CurveChainWithDistanceIndex.d.ts.map +1 -1
  57. package/lib/esm/curve/CurveChainWithDistanceIndex.js +10 -19
  58. package/lib/esm/curve/CurveChainWithDistanceIndex.js.map +1 -1
  59. package/lib/esm/geometry3d/Angle.d.ts +1 -0
  60. package/lib/esm/geometry3d/Angle.d.ts.map +1 -1
  61. package/lib/esm/geometry3d/Angle.js +1 -0
  62. package/lib/esm/geometry3d/Angle.js.map +1 -1
  63. package/lib/esm/geometry3d/AngleSweep.d.ts +1 -0
  64. package/lib/esm/geometry3d/AngleSweep.d.ts.map +1 -1
  65. package/lib/esm/geometry3d/AngleSweep.js +1 -0
  66. package/lib/esm/geometry3d/AngleSweep.js.map +1 -1
  67. package/lib/esm/geometry3d/GrowableXYArray.d.ts +1 -1
  68. package/lib/esm/geometry3d/GrowableXYArray.js +1 -1
  69. package/lib/esm/geometry3d/GrowableXYArray.js.map +1 -1
  70. package/lib/esm/geometry3d/Matrix3d.d.ts +221 -159
  71. package/lib/esm/geometry3d/Matrix3d.d.ts.map +1 -1
  72. package/lib/esm/geometry3d/Matrix3d.js +365 -249
  73. package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
  74. package/lib/esm/geometry3d/OrderedRotationAngles.d.ts +71 -14
  75. package/lib/esm/geometry3d/OrderedRotationAngles.d.ts.map +1 -1
  76. package/lib/esm/geometry3d/OrderedRotationAngles.js +205 -115
  77. package/lib/esm/geometry3d/OrderedRotationAngles.js.map +1 -1
  78. package/lib/esm/geometry3d/Point2dVector2d.d.ts +1 -0
  79. package/lib/esm/geometry3d/Point2dVector2d.d.ts.map +1 -1
  80. package/lib/esm/geometry3d/Point2dVector2d.js +1 -0
  81. package/lib/esm/geometry3d/Point2dVector2d.js.map +1 -1
  82. package/lib/esm/geometry3d/Point3dVector3d.d.ts +4 -3
  83. package/lib/esm/geometry3d/Point3dVector3d.d.ts.map +1 -1
  84. package/lib/esm/geometry3d/Point3dVector3d.js +6 -5
  85. package/lib/esm/geometry3d/Point3dVector3d.js.map +1 -1
  86. package/lib/esm/geometry3d/YawPitchRollAngles.d.ts +49 -25
  87. package/lib/esm/geometry3d/YawPitchRollAngles.d.ts.map +1 -1
  88. package/lib/esm/geometry3d/YawPitchRollAngles.js +146 -50
  89. package/lib/esm/geometry3d/YawPitchRollAngles.js.map +1 -1
  90. package/lib/esm/polyface/PolyfaceBuilder.d.ts +4 -4
  91. package/lib/esm/polyface/PolyfaceBuilder.js +4 -4
  92. package/lib/esm/polyface/PolyfaceBuilder.js.map +1 -1
  93. package/lib/esm/polyface/PolyfaceQuery.d.ts +28 -0
  94. package/lib/esm/polyface/PolyfaceQuery.d.ts.map +1 -1
  95. package/lib/esm/polyface/PolyfaceQuery.js +79 -0
  96. package/lib/esm/polyface/PolyfaceQuery.js.map +1 -1
  97. package/lib/esm/serialization/IModelJsonSchema.d.ts +1 -1
  98. package/lib/esm/serialization/IModelJsonSchema.js.map +1 -1
  99. package/package.json +4 -4
@@ -47,7 +47,7 @@ export class PackedMatrix3dOps {
47
47
  dest[8] = a22;
48
48
  }
49
49
  /**
50
- * * multiply 3x3 matrix `a*b`, store in c.
50
+ * Multiply 3x3 matrix `a*b`, store in `result`.
51
51
  * * All params assumed length 9, allocated by caller.
52
52
  * * c may alias either input.
53
53
  */
@@ -58,7 +58,7 @@ export class PackedMatrix3dOps {
58
58
  return result;
59
59
  }
60
60
  /**
61
- * * multiply 3x3 matrix `a*bTranspose`, store in c.
61
+ * Multiply 3x3 matrix `a*bTranspose`, store in `result`.
62
62
  * * All params assumed length 9, allocated by caller.
63
63
  * * c may alias either input.
64
64
  */
@@ -69,7 +69,7 @@ export class PackedMatrix3dOps {
69
69
  return result;
70
70
  }
71
71
  /**
72
- * * multiply 3x3 matrix `a*bTranspose`, store in c.
72
+ * Multiply 3x3 matrix `aTranspose*b`, store in `result`.
73
73
  * * All params assumed length 9, allocated by caller.
74
74
  * * c may alias either input.
75
75
  */
@@ -79,7 +79,7 @@ export class PackedMatrix3dOps {
79
79
  PackedMatrix3dOps.loadMatrix(result, (a[0] * b[0] + a[3] * b[3] + a[6] * b[6]), (a[0] * b[1] + a[3] * b[4] + a[6] * b[7]), (a[0] * b[2] + a[3] * b[5] + a[6] * b[8]), (a[1] * b[0] + a[4] * b[3] + a[7] * b[6]), (a[1] * b[1] + a[4] * b[4] + a[7] * b[7]), (a[1] * b[2] + a[4] * b[5] + a[7] * b[8]), (a[2] * b[0] + a[5] * b[3] + a[8] * b[6]), (a[2] * b[1] + a[5] * b[4] + a[8] * b[7]), (a[2] * b[2] + a[5] * b[5] + a[8] * b[8]));
80
80
  return result;
81
81
  }
82
- /** transpose 3x3 coefficients in place */
82
+ /** Transpose 3x3 matrix `a` in place */
83
83
  static transposeInPlace(a) {
84
84
  let q = a[1];
85
85
  a[1] = a[3];
@@ -91,10 +91,14 @@ export class PackedMatrix3dOps {
91
91
  a[5] = a[7];
92
92
  a[7] = q;
93
93
  }
94
- /** transpose 3x3 coefficients in place */
94
+ /**
95
+ * Returns the transpose of 3x3 matrix `a`
96
+ * * If `dest` is passed as argument, then the function copies the transpose of 3x3 matrix `a` into `dest`
97
+ * * `a` is not changed unless also passed as the dest, i.e., copyTransposed(a,a) transposes `a` in place
98
+ */
95
99
  static copyTransposed(a, dest) {
96
100
  if (dest === a) {
97
- PackedMatrix3dOps.transposeInPlace(a);
101
+ PackedMatrix3dOps.transposeInPlace(dest);
98
102
  }
99
103
  else {
100
104
  if (!dest)
@@ -111,7 +115,7 @@ export class PackedMatrix3dOps {
111
115
  }
112
116
  return dest;
113
117
  }
114
- /** transpose 3x3 coefficients in place */
118
+ /** Copy matrix `a` entries into `dest` */
115
119
  static copy(a, dest) {
116
120
  if (dest !== a) {
117
121
  dest[0] = a[0];
@@ -129,29 +133,31 @@ export class PackedMatrix3dOps {
129
133
  }
130
134
  /** A Matrix3d is tagged indicating one of the following states:
131
135
  * * unknown: it is not know if the matrix is invertible.
132
- * * inverseStored: the matrix has its inverse stored
136
+ * * inverseStored: the matrix has its inverse stored.
133
137
  * * singular: the matrix is known to be singular.
134
138
  * @public
135
139
  */
136
140
  export var InverseMatrixState;
137
141
  (function (InverseMatrixState) {
138
142
  /**
139
- * * The invertibility of the `coffs` array has not been determined.
140
- * * Any `inverseCoffs` contents are random.
143
+ * The invertibility of the `coffs` array has not been determined.
144
+ * Any `inverseCoffs` contents are random.
141
145
  */
142
146
  InverseMatrixState[InverseMatrixState["unknown"] = 0] = "unknown";
143
- /** An inverse was computed and stored as the `inverseCoffs` */
147
+ /**
148
+ * An inverse was computed and stored as the `inverseCoffs`
149
+ */
144
150
  InverseMatrixState[InverseMatrixState["inverseStored"] = 1] = "inverseStored";
145
151
  /**
146
- * * The `coffs` array is known to be singular.
147
- * * Any `inverseCoffs` contents are random.
152
+ * The `coffs` array is known to be singular.
153
+ * Any `inverseCoffs` contents are random.
148
154
  */
149
155
  InverseMatrixState[InverseMatrixState["singular"] = 2] = "singular";
150
156
  })(InverseMatrixState || (InverseMatrixState = {}));
151
157
  /** A Matrix3d is a 3x3 matrix.
152
158
  * * A very common use is to hold a rigid body rotation (which has no scaling or skew), but the 3x3 contents can
153
159
  * also hold scaling and skewing.
154
- * * The matrix with 2-dimensional layout
160
+ * * The matrix with 2-dimensional layout (note: a 2d array can be shown by a matrix)
155
161
  * ```
156
162
  * equation
157
163
  * \matrixXY{A}
@@ -163,19 +169,21 @@ export var InverseMatrixState;
163
169
  * ```
164
170
  * * If the matrix inverse is known it is stored in the inverseCoffs array.
165
171
  * * The inverse status (`unknown`, `inverseStored`, `singular`) status is indicated by the `inverseState` property.
166
- * * construction methods that are able to trivially construct the inverse store it immediately and note that in the inverseState.
167
- * * constructions (e.g. createRowValues) for which the inverse is not immediately known mark the
168
- * inverseState as unknown.
169
- * * Later queries for the inverse trigger full computation if needed at that time.
172
+ * * Construction methods that are able to trivially construct the inverse, store it immediately and note that in
173
+ * the inverseState.
174
+ * * Constructions (e.g. createRowValues) for which the inverse is not immediately known mark the inverseState as
175
+ * unknown.
176
+ * * Later queries for the inverse, trigger full computation if needed at that time.
170
177
  * * Most matrix queries are present with both "column" and "row" variants.
171
- * * Usage elsewhere in the library is typically "column" based. For example, in a Transform
172
- * that carries a coordinate frame the matrix columns are the unit vectors for the axes.
178
+ * * Usage elsewhere in the library is typically "column" based. For example, in a Transform that carries a
179
+ * coordinate frame, the matrix columns are the unit vectors for the axes.
173
180
  * @public
174
181
  */
175
182
  export class Matrix3d {
176
183
  /**
177
- *
178
- * @param coffs optional coefficient array. This is captured.
184
+ * Constructor
185
+ * @param coffs optional coefficient array.
186
+ * * **WARNING:** coffs is captured (i.e., is now owned by the Matrix3d object and can be modified by it).
179
187
  */
180
188
  constructor(coffs) {
181
189
  this.coffs = coffs ? coffs : new Float64Array(9);
@@ -193,14 +201,16 @@ export class Matrix3d {
193
201
  /** Freeze this Matrix3d. */
194
202
  freeze() {
195
203
  this.computeCachedInverse(true);
196
- /* hm.. can't freeze the Float64Arrays . . .
204
+ /*
205
+ hm.. can't freeze the Float64Arrays..
197
206
  Object.freeze(this.coffs);
198
207
  if (this.inverseCoffs)
199
208
  Object.freeze(this.inverseCoffs);
200
209
  */
201
210
  return Object.freeze(this);
202
211
  }
203
- /** Return a json object containing the 9 numeric entries as a single array in row major order,
212
+ /**
213
+ * Return a json object containing the 9 numeric entries as a single array in row major order,
204
214
  * `[ [1, 2, 3],[ 4, 5, 6], [7, 8, 9] ]`
205
215
  */
206
216
  toJSON() {
@@ -208,46 +218,81 @@ export class Matrix3d {
208
218
  [this.coffs[3], this.coffs[4], this.coffs[5]],
209
219
  [this.coffs[6], this.coffs[7], this.coffs[8]]];
210
220
  }
211
- /** copy data from various input forms to this matrix.
221
+ /**
222
+ * Copy data from various input forms to this matrix.
212
223
  * The source can be:
213
224
  * * Another `Matrix3d`
214
225
  * * An array of 3 arrays, each of which has the 3 numbers for a row of the matrix.
215
- * * An array of 9 numbers in row major order.
226
+ * * An array of 4 or 9 numbers in row major order.
227
+ * * **WARNING:** if json is an array of numbers but size is not 4 or 9, the matrix is set to zeros.
216
228
  */
217
229
  setFromJSON(json) {
218
230
  this.inverseCoffs = undefined;
231
+ // if no json is passed
219
232
  if (!json) {
220
233
  this.setRowValues(0, 0, 0, 0, 0, 0, 0, 0, 0);
221
234
  return;
222
235
  }
236
+ // if json is Matrix3d
223
237
  if (!Array.isArray(json)) {
224
238
  if (json instanceof Matrix3d)
225
239
  this.setFrom(json);
226
240
  return;
227
241
  }
242
+ // if json is Matrix3dProps and is an array of arrays
228
243
  if (Geometry.isArrayOfNumberArray(json, 3, 3)) {
229
244
  const data = json;
230
245
  this.setRowValues(data[0][0], data[0][1], data[0][2], data[1][0], data[1][1], data[1][2], data[2][0], data[2][1], data[2][2]);
231
246
  return;
232
247
  }
248
+ // if json is Matrix3dProps and is an array of numbers
233
249
  if (json.length === 9) {
234
250
  const data = json;
235
251
  this.setRowValues(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]);
252
+ return;
236
253
  }
237
254
  else if (json.length === 4) {
238
255
  const data = json;
239
256
  this.setRowValues(data[0], data[1], 0, data[2], data[3], 0, 0, 0, 1);
257
+ return;
240
258
  }
259
+ // if json is Matrix3dProps but is not the right size
260
+ this.setRowValues(0, 0, 0, 0, 0, 0, 0, 0, 0);
261
+ return;
262
+ }
263
+ /** Return a new Matrix3d constructed from contents of the json value. See `setFromJSON` for layout rules */
264
+ static fromJSON(json) {
265
+ const result = Matrix3d.createIdentity();
266
+ result.setFromJSON(json);
267
+ return result;
241
268
  }
242
- /** Return a new Matrix3d constructed from contents of the json value. Se `setFromJSON` for layout rules */
243
- static fromJSON(json) { const result = Matrix3d.createIdentity(); result.setFromJSON(json); return result; }
244
- /** Test if this Matrix3d and other are within tolerance in all numeric entries.
269
+ /**
270
+ * Test if `this` and `other` are within tolerance in all numeric entries.
245
271
  * @param tol optional tolerance for comparisons by Geometry.isDistanceWithinTol
246
272
  */
247
273
  isAlmostEqual(other, tol) {
248
274
  return Geometry.isDistanceWithinTol(this.maxDiff(other), tol);
249
275
  }
250
- /** Test if `this` and `other` have almost equal Z column and have X and Y columns differing only by a rotation around that Z.
276
+ /**
277
+ * Test if `this` and `other` are within tolerance in the column entries specified by `columnIndex`.
278
+ * @param tol optional tolerance for comparisons by Geometry.isDistanceWithinTol
279
+ */
280
+ isAlmostEqualColumn(columnIndex, other, tol) {
281
+ const max = Geometry.maxAbsXYZ(this.coffs[columnIndex] - other.coffs[columnIndex], this.coffs[columnIndex + 3] - other.coffs[columnIndex + 3], this.coffs[columnIndex + 6] - other.coffs[columnIndex + 6]);
282
+ return Geometry.isDistanceWithinTol(max, tol);
283
+ }
284
+ /**
285
+ * Test if column (specified by `columnIndex`) entries of `this` and [ax,ay,az] are within tolerance.
286
+ * @param tol optional tolerance for comparisons by Geometry.isDistanceWithinTol
287
+ */
288
+ isAlmostEqualColumnXYZ(columnIndex, ax, ay, az, tol) {
289
+ const max = Geometry.maxAbsXYZ(this.coffs[columnIndex] - ax, this.coffs[columnIndex + 3] - ay, this.coffs[columnIndex + 6] - az);
290
+ return Geometry.isDistanceWithinTol(max, tol);
291
+ }
292
+ /**
293
+ * Test if `this` and `other` have almost equal Z column and have X and Y columns differing only by a
294
+ * rotation of the same angle around that Z.
295
+ * * **WARNING:** X and Y columns have to be perpendicular to Z column in both `this` and `other`.
251
296
  * @param tol optional tolerance for comparisons by Geometry.isDistanceWithinTol
252
297
  */
253
298
  isAlmostEqualAllowZRotation(other, tol) {
@@ -255,10 +300,15 @@ export class Matrix3d {
255
300
  return true;
256
301
  if (this.isAlmostEqualColumn(AxisIndex.Z, other, tol)) {
257
302
  const radians = Angle.radiansBetweenVectorsXYZ(this.coffs[0], this.coffs[3], this.coffs[6], other.coffs[0], other.coffs[3], other.coffs[6]);
258
- const angle = Angle.createRadians(radians);
303
+ const angle = Angle.createRadians(radians); // angle between X columns in `this` and `other`
259
304
  const columnX = this.columnX();
260
305
  const columnY = this.columnY();
261
306
  const columnZ = this.columnZ();
307
+ /**
308
+ * Here we rotate this.columnX() around this.columnZ() by "angle" and expect to get other.columnX().
309
+ * Then we rotate this.columnY() around this.columnZ() by the same "angle" and if we get other.columnY(),
310
+ * that means this` and `other` have X and Y columns differing only by a rotation around that Z.
311
+ */
262
312
  let column = Vector3d.createRotateVectorAroundVector(columnX, columnZ, angle);
263
313
  if (other.isAlmostEqualColumnXYZ(0, column.x, column.y, column.z, tol)) {
264
314
  column = Vector3d.createRotateVectorAroundVector(columnY, columnZ, angle);
@@ -267,16 +317,10 @@ export class Matrix3d {
267
317
  }
268
318
  return false;
269
319
  }
270
- isAlmostEqualColumn(columnIndex, other, tol) {
271
- const a = Geometry.maxAbsXYZ(this.coffs[columnIndex] - other.coffs[columnIndex], this.coffs[columnIndex + 3] - other.coffs[columnIndex + 3], this.coffs[columnIndex + 6] - other.coffs[columnIndex + 6]);
272
- return Geometry.isDistanceWithinTol(a, tol);
273
- }
274
- isAlmostEqualColumnXYZ(columnIndex, ax, ay, az, tol) {
275
- const a = Geometry.maxAbsXYZ(this.coffs[columnIndex] - ax, this.coffs[columnIndex + 3] - ay, this.coffs[columnIndex + 6] - az);
276
- return Geometry.isDistanceWithinTol(a, tol);
277
- }
278
320
  /** Test for exact (bitwise) equality with other. */
279
- isExactEqual(other) { return this.maxDiff(other) === 0.0; }
321
+ isExactEqual(other) {
322
+ return this.maxDiff(other) === 0.0;
323
+ }
280
324
  /** test if all entries in the z row and column are exact 001, i.e. the matrix only acts in 2d */
281
325
  get isXY() {
282
326
  return this.coffs[2] === 0.0
@@ -285,10 +329,16 @@ export class Matrix3d {
285
329
  && this.coffs[7] === 0.0
286
330
  && this.coffs[8] === 1.0;
287
331
  }
288
- // !! does not clear supplied result !!
289
- static _create(result) { return result ? result : new Matrix3d(); }
290
- /** Returns a Matrix3d populated by numeric values given in row-major order.
291
- * set all entries in the matrix from call parameters appearing in row - major order, i.e.
332
+ /**
333
+ * If result is not provided, then the method returns a new (zeroed) matrix; otherwise the result is
334
+ * not zeroed first and is just returned as-is.
335
+ */
336
+ static _create(result) {
337
+ return result ? result : new Matrix3d();
338
+ }
339
+ /**
340
+ * Returns a Matrix3d populated by numeric values given in row-major order.
341
+ * Sets all entries in the matrix from call parameters appearing in row-major order, i.e.
292
342
  * ```
293
343
  * equation
294
344
  * \begin{bmatrix}a_{xx}\ a_{xy}\ a_{xz}\\ a_{yx}\ a_{yy}\ a_{yz}\\ a_{zx}\ a_{zy}\ a_{zz}\end{bmatrix}
@@ -319,7 +369,7 @@ export class Matrix3d {
319
369
  }
320
370
  /**
321
371
  * Create a Matrix3d with caller-supplied coefficients and optional inverse coefficients.
322
- * * The inputs are captured into the new Matrix3d.
372
+ * * The inputs are captured into (i.e., owned by) the new Matrix3d.
323
373
  * * The caller is responsible for validity of the inverse coefficients.
324
374
  * @param coffs (required) array of 9 coefficients.
325
375
  * @param inverseCoffs (optional) array of 9 coefficients.
@@ -337,12 +387,15 @@ export class Matrix3d {
337
387
  return result;
338
388
  }
339
389
  /**
340
- * create a matrix by distributing vectors to columns in one of 6 orders.
390
+ * Create a matrix by distributing vectors to columns in one of 6 orders.
341
391
  * @param axisOrder identifies where the columns are placed.
342
- * @param columnA vector to place in the first column named by the axis order.
343
- * @param columnB vector to place in the second column named by the axis order.
344
- * @param columnC vector to place in the third column named by the axis order.
345
- * @param result
392
+ * @param columnA vector to place in the column specified by first letter in the AxisOrder name.
393
+ * @param columnB vector to place in the column specified by second letter in the AxisOrder name.
394
+ * @param columnC vector to place in the column specified by third letter in the AxisOrder name.
395
+ * @param result optional result matrix3d
396
+ * * Example: If you pass AxisOrder.YZX, then result will be [columnC, columnA, columnB] because
397
+ * first letter Y means columnA should go to the second column, second letter Z means columnB should
398
+ * go to the third column, and third letter X means columnC should go to the first column.
346
399
  */
347
400
  static createColumnsInAxisOrder(axisOrder, columnA, columnB, columnC, result) {
348
401
  if (!result)
@@ -362,13 +415,26 @@ export class Matrix3d {
362
415
  else if (axisOrder === AxisOrder.ZYX) {
363
416
  result.setColumns(columnC, columnB, columnA);
364
417
  }
365
- else { // fallthrough should only happen for AxisOrder.XYZ
418
+ else { // AxisOrder.XYZ
366
419
  result.setColumns(columnA, columnB, columnC);
367
420
  }
368
421
  return result;
369
422
  }
370
423
  /**
371
- * set all entries in the matrix from call parameters appearing in row-major order.
424
+ * Copy the transpose of the coffs to the inverseCoffs.
425
+ * * Mark the matrix as inverseStored.
426
+ */
427
+ setupInverseTranspose() {
428
+ const coffs = this.coffs;
429
+ this.inverseState = InverseMatrixState.inverseStored;
430
+ this.inverseCoffs = Float64Array.from([
431
+ coffs[0], coffs[3], coffs[6],
432
+ coffs[1], coffs[4], coffs[7],
433
+ coffs[2], coffs[5], coffs[8],
434
+ ]);
435
+ }
436
+ /**
437
+ * Set all entries in the matrix from call parameters appearing in row-major order.
372
438
  * @param axx Row x, column x (0,0) entry
373
439
  * @param axy Row x, column y (0,1) entry
374
440
  * @param axz Row x, column z (0,2) entry
@@ -392,15 +458,22 @@ export class Matrix3d {
392
458
  this.inverseState = InverseMatrixState.unknown;
393
459
  }
394
460
  /** Set the matrix to an identity. */
395
- setIdentity() { this.setRowValues(1, 0, 0, 0, 1, 0, 0, 0, 1); this.setupInverseTranspose(); }
461
+ setIdentity() {
462
+ this.setRowValues(1, 0, 0, 0, 1, 0, 0, 0, 1);
463
+ this.setupInverseTranspose();
464
+ }
396
465
  /** Set the matrix to all zeros. */
397
- setZero() { this.setRowValues(0, 0, 0, 0, 0, 0, 0, 0, 0); this.inverseState = InverseMatrixState.singular; }
398
- /** copy contents from another matrix. */
466
+ setZero() {
467
+ this.setRowValues(0, 0, 0, 0, 0, 0, 0, 0, 0);
468
+ this.inverseState = InverseMatrixState.singular;
469
+ }
470
+ /** Copy contents from another matrix. */
399
471
  setFrom(other) {
400
472
  if (other === undefined) {
401
473
  this.setIdentity();
474
+ return;
402
475
  }
403
- else if (other !== this) {
476
+ if (other !== this) {
404
477
  for (let i = 0; i < 9; i++)
405
478
  this.coffs[i] = other.coffs[i];
406
479
  if (other.inverseState === InverseMatrixState.inverseStored && other.inverseCoffs !== undefined) {
@@ -412,28 +485,29 @@ export class Matrix3d {
412
485
  else if (other.inverseState !== InverseMatrixState.inverseStored) {
413
486
  this.inverseState = other.inverseState;
414
487
  }
415
- else { // This is reached of other says stored but does not have coffs. This should not happen.
488
+ else { // This is reached when other says stored but does not have coffs. This should not happen.
416
489
  this.inverseState = InverseMatrixState.unknown;
417
490
  }
418
491
  }
419
492
  }
420
- /** return a clone of this matrix.
421
- * * coefficients are copied.
422
- * * inverse coefficients are NOT copied.
423
- * * inverse status is set to unknown
493
+ /**
494
+ * Return a clone of this matrix.
495
+ * * Coefficients are copied.
496
+ * * Inverse coefficients and inverse status are copied if stored by `this`.
424
497
  */
425
498
  clone(result) {
426
499
  result = result ? result : new Matrix3d();
427
500
  result.setFrom(this);
428
501
  return result;
429
502
  }
430
- /** create a matrix with all zeros.
503
+ /**
504
+ * Create a matrix with all zeros.
431
505
  * * Note that for geometry transformations "all zeros" is not a useful default state.
432
- * * Hence almost always use `createIdentity` for graphics transformations.
433
- * * "all zeros" is appropriate for summing moment data.
506
+ * * Hence, almost always use `createIdentity` for graphics transformations.
507
+ * * "All zeros" is appropriate for summing moment data.
434
508
  * ```
435
509
  * equation
436
- * \begin{bmatrix}0 0 0 \\ 0 0 0 \\ 0 0 0\end{bmatrix}
510
+ * \begin{bmatrix}0 & 0 & 0 \\ 0 & 0 & 0 \\ 0 & 0 & 0\end{bmatrix}
437
511
  * ```
438
512
  */
439
513
  static createZero() {
@@ -441,13 +515,14 @@ export class Matrix3d {
441
515
  retVal.inverseState = InverseMatrixState.singular;
442
516
  return retVal;
443
517
  }
444
- /** create an identity matrix.
445
- * * all diagonal entries (xx,yy,zz) are one
446
- * * all others are zero.
447
- * * This (rather than all zeros) is the useful state for most graphics transformations.
518
+ /**
519
+ * Create an identity matrix.
520
+ * * All diagonal entries (xx,yy,zz) are one
521
+ * * All others are zero.
522
+ * * This (rather than "all zeros") is the useful state for most graphics transformations.
448
523
  * ```
449
524
  * equation
450
- * \begin{bmatrix}1 0 0 \\ 0 1 0 \\ 0 0 1\end{bmatrix}
525
+ * \begin{bmatrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1\end{bmatrix}
451
526
  * ```
452
527
  *
453
528
  */
@@ -457,55 +532,7 @@ export class Matrix3d {
457
532
  return result;
458
533
  }
459
534
  /**
460
- * Create a matrix with uniform scale factors.
461
- * For scale factor _s_,
462
- * ```
463
- * equation
464
- * \begin{bmatrix}s & 0 & 0 \\ 0 & s & 0\\ 0 & 0 & s\end{bmatrix}
465
- * ```
466
- */
467
- static createUniformScale(scaleFactor) {
468
- return Matrix3d.createScale(scaleFactor, scaleFactor, scaleFactor);
469
- }
470
- /**
471
- * Construct a rigid matrix using createPerpendicularVectorFavorXYPlane to generate a vector perpendicular to vectorA.
472
- * *
473
- */
474
- static createRigidHeadsUp(vectorA, axisOrder = AxisOrder.ZXY, result) {
475
- const vectorB = Matrix3d.createPerpendicularVectorFavorXYPlane(vectorA);
476
- const matrix = Matrix3d.createRigidFromColumns(vectorA, vectorB, axisOrder, result);
477
- if (matrix) {
478
- matrix.setupInverseTranspose();
479
- return matrix;
480
- }
481
- return Matrix3d.createIdentity(result);
482
- }
483
- /**
484
- * return a vector that is perpendicular to the input direction.
485
- * * Among the infinite number of perpendiculars possible, this method
486
- * favors having one in the xy plane.
487
- * * Hence, when vectorA is NOT close to the Z axis, the returned vector is Z cross vectorA.
488
- * * But vectorA is close to the Z axis, the returned vector is unitY cross vectorA.
489
- */
490
- static createPerpendicularVectorFavorXYPlane(vector, result) {
491
- const a = vector.magnitude();
492
- const b = a / 64.0; // A constant from the dawn of time in the CAD industry.
493
- if (Math.abs(vector.x) < b && Math.abs(vector.y) < b) {
494
- return Vector3d.createCrossProduct(vector.x, vector.y, vector.z, 0, -1, 0, result);
495
- }
496
- return Vector3d.createCrossProduct(0, 0, 1, vector.x, vector.y, vector.z, result);
497
- }
498
- /**
499
- * return a vector that is perpendicular to the input direction.
500
- * * Among the infinite number of perpendiculars possible, this method
501
- * favors having one near the Z.
502
- * That is achieved by crossing "this" vector with the result of createPerpendicularVectorFavorXYPlane.
503
- */
504
- static createPerpendicularVectorFavorPlaneContainingZ(vector, result) {
505
- result = Matrix3d.createPerpendicularVectorFavorXYPlane(vector, result);
506
- return vector.crossProduct(result, result);
507
- }
508
- /** Create a matrix with distinct x,y,z diagonal (scale) entries.
535
+ * Create a matrix with distinct x,y,z diagonal (scale) entries.
509
536
  * ```
510
537
  * equation
511
538
  * \begin{bmatrix}s_x & 0 & 0 \\ 0 & s_y & 0\\ 0 & 0 & s_z\end{bmatrix}
@@ -530,8 +557,103 @@ export class Matrix3d {
530
557
  }
531
558
  return result;
532
559
  }
533
- /** return a rotation of specified angle around an axis */
560
+ /**
561
+ * Create a matrix with uniform scale factors for scale factor "s"
562
+ * ```
563
+ * equation
564
+ * \begin{bmatrix}s & 0 & 0 \\ 0 & s & 0\\ 0 & 0 & s\end{bmatrix}
565
+ * ```
566
+ */
567
+ static createUniformScale(scaleFactor) {
568
+ return Matrix3d.createScale(scaleFactor, scaleFactor, scaleFactor);
569
+ }
570
+ /**
571
+ * Return a vector that is perpendicular to the input `vectorA`.
572
+ * * Among the infinite number of perpendiculars possible, this method favors having one in the xy plane.
573
+ * * Hence, when `vectorA` is close to the Z axis, the returned vector is `vectorA cross -unitY`
574
+ * but when `vectorA` is NOT close to the Z axis, the returned vector is `unitZ cross vectorA`.
575
+ */
576
+ static createPerpendicularVectorFavorXYPlane(vectorA, result) {
577
+ const a = vectorA.magnitude();
578
+ const scale = 64.0; // A constant from the dawn of time in the CAD industry
579
+ const b = a / scale;
580
+ // if vectorA is close to the Z axis
581
+ if (Math.abs(vectorA.x) < b && Math.abs(vectorA.y) < b) {
582
+ return Vector3d.createCrossProduct(vectorA.x, vectorA.y, vectorA.z, 0, -1, 0, result);
583
+ }
584
+ // if vectorA is NOT close to the Z axis
585
+ return Vector3d.createCrossProduct(0, 0, 1, vectorA.x, vectorA.y, vectorA.z, result);
586
+ }
587
+ /**
588
+ * Return a vector that is perpendicular to the input `vectorA`.
589
+ * * Among the infinite number of perpendiculars possible, this method favors having one near the plane
590
+ * containing Z.
591
+ * That is achieved by cross product of `this` vector with the result of createPerpendicularVectorFavorXYPlane.
592
+ */
593
+ static createPerpendicularVectorFavorPlaneContainingZ(vectorA, result) {
594
+ /**
595
+ * vectorA, result (below), and "vectorA cross result" form a coordinate system where "result" is located on
596
+ * the XY-plane. Once you've got a coordinate system with an axis in the XY-plane, your other two axes form
597
+ * a plane that includes the z-axis.
598
+ */
599
+ result = Matrix3d.createPerpendicularVectorFavorXYPlane(vectorA, result);
600
+ return vectorA.crossProduct(result, result);
601
+ }
602
+ /**
603
+ * Create a matrix from column vectors, shuffled into place per axisOrder
604
+ * For example, if axisOrder = XYZ then it returns [vectorU, vectorV, vectorW]
605
+ * Another example, if axisOrder = YZX then it returns [vectorW, vectorU, vectorV] because
606
+ * Y is at index 0 so vectorU goes to the column Y (column 2), Z is at index 1 so vectorV goes
607
+ * to the column Z (column 3), and X is at index 2 so vectorW goes to the column X (column 1)
608
+ */
609
+ static createShuffledColumns(vectorU, vectorV, vectorW, axisOrder, result) {
610
+ const target = Matrix3d._create(result);
611
+ target.setColumn(Geometry.axisOrderToAxis(axisOrder, 0), vectorU);
612
+ target.setColumn(Geometry.axisOrderToAxis(axisOrder, 1), vectorV);
613
+ target.setColumn(Geometry.axisOrderToAxis(axisOrder, 2), vectorW);
614
+ return target;
615
+ }
616
+ /**
617
+ * Create a new orthogonal matrix (perpendicular columns, unit length, transpose is inverse).
618
+ * * `vectorA1 = Normalized vectorA` is placed in the column specified by **first** letter in
619
+ * the AxisOrder name.
620
+ * * Normalized `vectorC1 = vectorA1 cross vectorB` is placed in the column specified by **third**
621
+ * letter in the AxisOrder name.
622
+ * * Normalized `vectorC1 cross vectorA` is placed in the column specified by **second**
623
+ * letter in the AxisOrder name.
624
+ * * This function internally uses createShuffledColumns.
625
+ */
626
+ static createRigidFromColumns(vectorA, vectorB, axisOrder, result) {
627
+ const vectorA1 = vectorA.normalize();
628
+ if (vectorA1) {
629
+ const vectorC1 = vectorA1.unitCrossProduct(vectorB);
630
+ if (vectorC1) {
631
+ const vectorB1 = vectorC1.unitCrossProduct(vectorA);
632
+ if (vectorB1) {
633
+ const retVal = Matrix3d.createShuffledColumns(vectorA1, vectorB1, vectorC1, axisOrder, result);
634
+ retVal.setupInverseTranspose();
635
+ return retVal;
636
+ }
637
+ }
638
+ }
639
+ return undefined;
640
+ }
641
+ /**
642
+ * Construct a rigid matrix using vectorA and its 2 perpendicular.
643
+ * * This function internally uses createPerpendicularVectorFavorXYPlane and createRigidFromColumns.
644
+ */
645
+ static createRigidHeadsUp(vectorA, axisOrder = AxisOrder.ZXY, result) {
646
+ const vectorB = Matrix3d.createPerpendicularVectorFavorXYPlane(vectorA);
647
+ const matrix = Matrix3d.createRigidFromColumns(vectorA, vectorB, axisOrder, result);
648
+ if (matrix) {
649
+ matrix.setupInverseTranspose();
650
+ return matrix;
651
+ }
652
+ return Matrix3d.createIdentity(result);
653
+ }
654
+ /** Return the matrix for rotation of `angle` around `axis` */
534
655
  static createRotationAroundVector(axis, angle, result) {
656
+ // Rodriguez formula (matrix form), https://mathworld.wolfram.com/RodriguesRotationFormula.html
535
657
  const c = angle.cos();
536
658
  const s = angle.sin();
537
659
  const v = 1.0 - c;
@@ -547,6 +669,7 @@ export class Matrix3d {
547
669
  * @param axisIndex index of axis (AxisIndex.X, AxisIndex.Y, AxisIndex.Z) kept fixed by the rotation.
548
670
  * @param angle angle of rotation
549
671
  * @param result optional result matrix.
672
+ * * Math details of 3d rotation matrices derivation can be found at docs/learning/geometry/Angle.md
550
673
  */
551
674
  static createRotationAroundAxisIndex(axisIndex, angle, result) {
552
675
  const c = angle.cos();
@@ -564,27 +687,77 @@ export class Matrix3d {
564
687
  myResult.setupInverseTranspose();
565
688
  return myResult;
566
689
  }
690
+ /**
691
+ * Replace current columns Ui and Uj with (c*Ui - s*Uj) and (c*Uj + s*Ui).
692
+ * * There is no checking for i,j being 0,1,2.
693
+ * * This is used in compute intensive inner loops
694
+ * @param i first row index. **must be 0,1,2** (unchecked)
695
+ * @param j second row index. **must be 0,1,2** (unchecked)
696
+ * @param c fist coefficient
697
+ * @param s second coefficient
698
+ */
699
+ applyGivensColumnOp(i, j, c, s) {
700
+ const limit = i + 9;
701
+ for (; i < limit; i += 3, j += 3) {
702
+ const a = this.coffs[i];
703
+ const b = this.coffs[j];
704
+ this.coffs[i] = a * c + b * s;
705
+ this.coffs[j] = -a * s + b * c;
706
+ }
707
+ }
708
+ /**
709
+ * Create a matrix from column vectors.
710
+ * ```
711
+ * equation
712
+ * \begin{bmatrix}U_x & V_x & W_x \\ U_y & V_y & W_y \\ U_z & V_z & W_z \end{bmatrix}
713
+ * ```
714
+ */
715
+ static createColumns(vectorU, vectorV, vectorW, result) {
716
+ return Matrix3d.createRowValues(vectorU.x, vectorV.x, vectorW.x, vectorU.y, vectorV.y, vectorW.y, vectorU.z, vectorV.z, vectorW.z, result);
717
+ }
718
+ /** Create a matrix with each column's _x,y_ parts given `XAndY` and separate numeric z values.
719
+ * ```
720
+ * equation
721
+ * \begin{bmatrix}U_x & V_x & W_x \\ U_y & V_y & W_y \\ u & v & w \end{bmatrix}
722
+ * ```
723
+ */
724
+ static createColumnsXYW(vectorU, u, vectorV, v, vectorW, w, result) {
725
+ return Matrix3d.createRowValues(vectorU.x, vectorV.x, vectorW.x, vectorU.y, vectorV.y, vectorW.y, u, v, w, result);
726
+ }
567
727
  /** Create a matrix from "as viewed" right and up vectors.
568
728
  * * ColumnX points in the rightVector direction
569
- * * ColumnY points in in the upVectorDirection
570
- * * ColumnZ is a unit cross product.
571
- * Optionally rotate the standard cube by 45 to bring its left or right vertical edge to center
572
- * * leftNoneRight = [-1,0,1] respectively for left edge, no rotation, or right edge
573
- * * bottomNoneTop = [-1,0,1] respectively for isometric rotation to view the bottom, no isometric rotation, and isometric rotation to view the top
574
- * This is expected to be used with various principal unit vectors that are perpendicular to each other.
575
- * * STANDARD TOP VIEW: (Vector3d.UnitX (), Vector3d.UnitY (), 0, 0)
576
- * * STANDARD FRONT VIEW: (Vector3d.UnitX (), Vector3d.UnitZ (), 0, 0)
577
- * * STANDARD BACK VIEW: (Vector3d.UnitX (-1), Vector3d.UnitZ (), 0, 0)
578
- * * STANDARD RIGHT VIEW: (Vector3d.UnitY (1), Vector3d.UnitZ (), 0, 0)
579
- * * STANDARD LEFT VIEW: (Vector3d.UnitY (-1), Vector3d.UnitZ (), 0, 0)
580
- * * STANDARD BOTTOM VIEW: (Vector3d.UnitX (1), Vector3d.UnitY (-1), 0, 0)
581
- * @param leftNoneRight Normally one of {-1,0,1}, where (-1) indicates the left vertical is rotated to center and (1) for right. Other numbers are used as multiplier for this 45 degree rotation
582
- * @returns undefined if columnX, columnY are coplanar.
729
+ * * ColumnY points in the upVector direction
730
+ * * ColumnZ is a unit cross product of ColumnX and ColumnY.
731
+ * * Optionally rotate the standard cube by 45 degrees ccw around Y to bring its left or right vertical edge to center.
732
+ * * Optionally rotate the standard cube by 35.264 degrees ccw around X (isometric rotation).
733
+ * * This is expected to be used with various principal unit vectors that are perpendicular to each other.
734
+ * * STANDARD TOP VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitY(), 0, 0)
735
+ * * STANDARD FRONT VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitZ(), 0, 0)
736
+ * * STANDARD BACK VIEW: createViewedAxes(Vector3d.unitX(-1), Vector3d.unitZ(), 0, 0)
737
+ * * STANDARD RIGHT VIEW: createViewedAxes(Vector3d.unitY(), Vector3d.unitZ(), 0, 0)
738
+ * * STANDARD LEFT VIEW: createViewedAxes(Vector3d.unitY(-1), Vector3d.unitZ(), 0, 0)
739
+ * * STANDARD BOTTOM VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitY(-1), 0, 0)
740
+ * * Note: createViewedAxes is column-based so always returns local to world
741
+ *
742
+ * @param rightVector ColumnX of the returned matrix. Expected to be perpendicular to upVector.
743
+ * @param upVector ColumnY of the returned matrix. Expected to be perpendicular to rightVector.
744
+ * @param leftNoneRight Specifies the ccw rotation around Y axis. Normally one of "-1", "0", and "1", where
745
+ * "-1" indicates rotation by 45 degrees to bring the left vertical edge to center, "0" means no rotation,
746
+ * and "1" indicates rotation by 45 degrees to bring the right vertical edge to center. Other numbers are
747
+ * used as multiplier for this 45 degree rotation.
748
+ * @param topNoneBottom Specifies the ccw rotation around X axis. Normally one of "-1", "0", and "1", where
749
+ * "-1" indicates isometric rotation (35.264 degrees) to bring the bottom upward, "0" means no rotation,
750
+ * and "1" indicates isometric rotation (35.264 degrees) to bring the top downward. Other numbers are
751
+ * used as multiplier for the 35.264 degree rotation.
752
+ * @returns matrix = [rightVector, upVector, rightVector cross upVector] with the applied rotations specified
753
+ * by leftNoneRight and topNoneBottom. Returns undefined if rightVector and upVector are parallel.
583
754
  */
584
755
  static createViewedAxes(rightVector, upVector, leftNoneRight = 0, topNoneBottom = 0) {
585
756
  const columnZ = rightVector.crossProduct(upVector);
586
757
  if (columnZ.normalizeInPlace()) {
587
- const geometry = Matrix3d.createColumns(rightVector, upVector, columnZ);
758
+ // matrix = [rightVector, upVector, rightVector cross upVector]
759
+ const matrix = Matrix3d.createColumns(rightVector, upVector, columnZ);
760
+ // "45 degrees * leftNoneRight" rotation around Y
588
761
  if (leftNoneRight !== 0.0) {
589
762
  let c = Math.sqrt(0.5);
590
763
  let s = leftNoneRight < 0.0 ? -c : c;
@@ -593,51 +766,63 @@ export class Matrix3d {
593
766
  c = Math.cos(radians);
594
767
  s = Math.sin(radians);
595
768
  }
596
- geometry.applyGivensColumnOp(2, 0, c, s); // rotate around Y
769
+ matrix.applyGivensColumnOp(2, 0, c, s); // rotate around Y (equivalent to matrix*rotationY)
597
770
  }
771
+ // "35.264 degrees * topNoneBottom" rotation around X
598
772
  if (topNoneBottom !== 0.0) {
599
773
  const theta = topNoneBottom * Math.atan(Math.sqrt(0.5));
600
774
  const c = Math.cos(theta);
601
775
  const s = Math.sin(theta);
602
- geometry.applyGivensColumnOp(1, 2, c, -s); // rotate around X
776
+ matrix.applyGivensColumnOp(1, 2, c, -s); // rotate around X (equivalent to matrix*rotationX)
603
777
  }
604
- return geometry;
778
+ return matrix;
605
779
  }
606
780
  return undefined;
607
781
  }
608
782
  /**
609
783
  * Create a rotation matrix for one of the 8 standard views.
610
- * * With `invert === false` the return is such that `matrix.multiply(worldVector)` returns the vector as seen in the xy (projected) coordinates of the view.
611
- * * With invert === true the matrix is transposed so that `matrix.multiply(viewVector` maps the "in view" vector to a world vector.
784
+ * * Default is TOP view (`local X = world X`, `local Y = world Y`, `local Z = world Z`).
785
+ * * To change view from the TOP to one of the other 7 standard views, we need to multiply "world data" to
786
+ * the corresponding matrix1 provided by `createStandardWorldToView(index, false)` and then
787
+ * `matrix1.multiply(world data)` will returns "local data".
788
+ * * To change view back to the TOP, we need to multiply "local data" to the corresponding matrix2 provided
789
+ * by `createStandardWorldToView(index, true)` and then `matrix2.multiply(local data)` will returns "world data".
612
790
  *
613
- * @param index standard view index `StandardViewIndex.Top, Bottom, LEft, Right, Front, Back, Iso, LeftIso`
614
- * @param invert if false (default), the returned Matrix3d "projects" world vectors into XY view vectors. If true, it is inverted to map view vectors to world.
791
+ * @param index standard view index `StandardViewIndex.Top, Bottom, Left, Right, Front, Back, Iso, RightIso`
792
+ * @param invert if false (default), the return matrix is world to local (view) and if true, the the return
793
+ * matrix is local (view) to world.
615
794
  * @param result optional result.
616
795
  */
617
796
  static createStandardWorldToView(index, invert = false, result) {
618
797
  switch (index) {
798
+ // start with TOP view, ccw rotation by 180 degrees around X
619
799
  case StandardViewIndex.Bottom:
620
800
  result = Matrix3d.createRowValues(1, 0, 0, 0, -1, 0, 0, 0, -1);
621
801
  break;
802
+ // start with TOP view, ccw rotation by -90 degrees around X and by 90 degrees around Z
622
803
  case StandardViewIndex.Left:
623
804
  result = Matrix3d.createRowValues(0, -1, 0, 0, 0, 1, -1, 0, 0);
624
805
  break;
806
+ // start with TOP view, ccw rotation by -90 degrees around X and by -90 degrees around Z
625
807
  case StandardViewIndex.Right:
626
808
  result = Matrix3d.createRowValues(0, 1, 0, 0, 0, 1, 1, 0, 0);
627
809
  break;
628
- case StandardViewIndex.Front: // 0-based 4
810
+ // start with TOP view, ccw rotation by -90 degrees around X
811
+ case StandardViewIndex.Front:
629
812
  result = Matrix3d.createRowValues(1, 0, 0, 0, 0, 1, 0, -1, 0);
630
813
  break;
631
- case StandardViewIndex.Back: // 0-based 5
814
+ // start with TOP view, ccw rotation by -90 degrees around X and by 180 degrees around Z
815
+ case StandardViewIndex.Back:
632
816
  result = Matrix3d.createRowValues(-1, 0, 0, 0, 0, 1, 0, 1, 0);
633
817
  break;
634
818
  case StandardViewIndex.Iso:
819
+ // start with FRONT view, ccw rotation by -45 degrees around Y and by 35.264 degrees around X
635
820
  result = Matrix3d.createRowValues(0.707106781186548, -0.70710678118654757, 0.00000000000000000, 0.408248290463863, 0.40824829046386302, 0.81649658092772603, -0.577350269189626, -0.57735026918962573, 0.57735026918962573);
636
821
  break;
637
822
  case StandardViewIndex.RightIso:
638
823
  result = Matrix3d.createRowValues(0.707106781186548, 0.70710678118654757, 0.00000000000000000, -0.408248290463863, 0.40824829046386302, 0.81649658092772603, 0.577350269189626, -0.57735026918962573, 0.57735026918962573);
639
824
  break;
640
- case StandardViewIndex.Top:
825
+ case StandardViewIndex.Top: // no rotation
641
826
  default:
642
827
  result = Matrix3d.createIdentity(result);
643
828
  }
@@ -714,7 +899,7 @@ export class Matrix3d {
714
899
  */
715
900
  /**
716
901
  * Compute the (unit vector) axis and angle of rotation.
717
- * @returns Returns with result.ok === true when the conversion succeeded.
902
+ * @returns Returns axis and angle of rotation with result.ok === true when the conversion succeeded.
718
903
  */
719
904
  getAxisAndAngleOfRotation() {
720
905
  const trace = this.coffs[0] + this.coffs[4] + this.coffs[8];
@@ -897,7 +1082,7 @@ export class Matrix3d {
897
1082
  columnZCrossVector(vector, result) {
898
1083
  return Geometry.crossProductXYZXYZ(this.coffs[2], this.coffs[5], this.coffs[8], vector.x, vector.y, vector.z, result);
899
1084
  }
900
- /**
1085
+ /*
901
1086
  * Replace current rows Ui Uj with (c*Ui - s*Uj) and (c*Uj + s*Ui).
902
1087
  * @param i first row index. must be 0,1,2 (unchecked)
903
1088
  * @param j second row index. must be 0,1,2 (unchecked)
@@ -915,23 +1100,6 @@ export class Matrix3d {
915
1100
  this.coffs[jj] = -a * s + b * c;
916
1101
  }
917
1102
  }
918
- /**
919
- * Replace current columns Ui Uj with (c*Ui - s*Uj) and (c*Uj + s*Ui).
920
- * * This is used in compute intensive inner loops -- there is no checking for i,j being 0,1,2.
921
- * @param i first row index. must be 0,1,2 (unchecked)
922
- * @param j second row index. must be 0,1,2 (unchecked)
923
- * @param c fist coefficient
924
- * @param s second coefficient
925
- */
926
- applyGivensColumnOp(i, j, c, s) {
927
- const limit = i + 9;
928
- for (; i < limit; i += 3, j += 3) {
929
- const a = this.coffs[i];
930
- const b = this.coffs[j];
931
- this.coffs[i] = a * c + b * s;
932
- this.coffs[j] = -a * s + b * c;
933
- }
934
- }
935
1103
  /**
936
1104
  * create a rigid coordinate frame column z parallel to (_x_,_y_,_z_) and column x in the xy plane.
937
1105
  * * column z points from origin to x,y,z
@@ -1164,33 +1332,14 @@ export class Matrix3d {
1164
1332
  }
1165
1333
  return false;
1166
1334
  }
1167
- /**
1168
- * Create a matrix from column vectors.
1169
- * ```
1170
- * equation
1171
- * \begin{bmatrix}U_x & V_x & W_x \\ U_y & V_y & W_y \\ U_z & V_z & W_z \end{bmatrix}
1172
- * ```
1173
- */
1174
- static createColumns(vectorU, vectorV, vectorW, result) {
1175
- return Matrix3d.createRowValues(vectorU.x, vectorV.x, vectorW.x, vectorU.y, vectorV.y, vectorW.y, vectorU.z, vectorV.z, vectorW.z, result);
1176
- }
1177
- /** Create a matrix with each column's _x,y_ parts given `XAndY` and separate numeric z values.
1178
- * ```
1179
- * equation
1180
- * \begin{bmatrix}U_x & V_x & W_x \\ U_y & V_y & W_y \\ u & v & w \end{bmatrix}
1181
- * ```
1182
- */
1183
- static createColumnsXYW(vectorU, u, vectorV, v, vectorW, w, result) {
1184
- return Matrix3d.createRowValues(vectorU.x, vectorV.x, vectorW.x, vectorU.y, vectorV.y, vectorW.y, u, v, w, result);
1185
- }
1186
1335
  /** Install data from xyz parts of Point4d (w part of Point4d ignored) */
1187
1336
  setColumnsPoint4dXYZ(vectorU, vectorV, vectorW) {
1188
1337
  this.inverseState = InverseMatrixState.unknown;
1189
1338
  this.setRowValues(vectorU.x, vectorV.x, vectorW.x, vectorU.y, vectorV.y, vectorW.y, vectorU.z, vectorV.z, vectorW.z);
1190
1339
  }
1191
1340
  /**
1192
- * set entries in one column of the matrix.
1193
- * @param columnIndex column index. this is interpreted cyclically.
1341
+ * Set entries in one column of the matrix.
1342
+ * @param columnIndex column index (this is interpreted cyclically. See Geometry.cyclic3dAxis for more info).
1194
1343
  * @param value x,yz, values for column. If undefined, zeros are installed.
1195
1344
  */
1196
1345
  setColumn(columnIndex, value) {
@@ -1239,14 +1388,6 @@ export class Matrix3d {
1239
1388
  const index = 3 * Geometry.cyclic3dAxis(columnIndex);
1240
1389
  return Vector3d.create(this.coffs[index], this.coffs[index + 1], this.coffs[index + 2], result);
1241
1390
  }
1242
- /** Create a matrix from column vectors, shuffled into place per AxisTriple */
1243
- static createShuffledColumns(vectorU, vectorV, vectorW, axisOrder, result) {
1244
- const target = Matrix3d._create(result);
1245
- target.setColumn(Geometry.axisOrderToAxis(axisOrder, 0), vectorU);
1246
- target.setColumn(Geometry.axisOrderToAxis(axisOrder, 1), vectorV);
1247
- target.setColumn(Geometry.axisOrderToAxis(axisOrder, 2), vectorW);
1248
- return target;
1249
- }
1250
1391
  /** Create a matrix from row vectors.
1251
1392
  * ```
1252
1393
  * equation
@@ -1678,7 +1819,11 @@ export class Matrix3d {
1678
1819
  this.multiplyMatrixMatrix(other.matrix, result.matrix);
1679
1820
  return result;
1680
1821
  }
1681
- /** return a transposed matrix. `this` is not changed unless also passed as the result. */
1822
+ /**
1823
+ * Return the transpose of `this` matrix.
1824
+ * If `result` is passed as argument, then the function copies the transpose of `this` into `result`
1825
+ * `this` is not changed unless also passed as the result, i.e., this.transpose(this) transposes `this` in place
1826
+ */
1682
1827
  transpose(result) {
1683
1828
  if (!result)
1684
1829
  result = new Matrix3d();
@@ -1693,8 +1838,8 @@ export class Matrix3d {
1693
1838
  }
1694
1839
  return result;
1695
1840
  }
1696
- /** transpose this matrix in place.
1697
- *
1841
+ /**
1842
+ * Transpose this matrix in place.
1698
1843
  */
1699
1844
  transposeInPlace() {
1700
1845
  PackedMatrix3dOps.transposeInPlace(this.coffs);
@@ -1725,18 +1870,6 @@ export class Matrix3d {
1725
1870
  result.inverseState = this.inverseState;
1726
1871
  return result;
1727
1872
  }
1728
- /** copy the transpose of the coffs to the inverseCoffs.
1729
- * * mark the matrix as inverseStored.
1730
- */
1731
- setupInverseTranspose() {
1732
- const coffs = this.coffs;
1733
- this.inverseState = InverseMatrixState.inverseStored;
1734
- this.inverseCoffs = Float64Array.from([
1735
- coffs[0], coffs[3], coffs[6],
1736
- coffs[1], coffs[4], coffs[7],
1737
- coffs[2], coffs[5], coffs[8]
1738
- ]);
1739
- }
1740
1873
  /* Alternate implementation of computedCachedInverse - more direct addressing of arrays.
1741
1874
  This is indeed 10% faster than using static work areas. */
1742
1875
  // take the cross product of two rows of source.
@@ -1844,8 +1977,10 @@ export class Matrix3d {
1844
1977
  markSingular() {
1845
1978
  this.inverseState = InverseMatrixState.singular;
1846
1979
  }
1847
- /** Create the inverseCoffs member (filled with zeros)
1848
- * This is for use by matrix * matrix multiplications which need to be sure the member is there to be filled with method-specific content.
1980
+ /**
1981
+ * Create the inverseCoffs member (filled with zeros)
1982
+ * This is for use by matrix * matrix multiplications which need to be sure the member is there to be
1983
+ * filled with method-specific content.
1849
1984
  */
1850
1985
  createInverseCoffsWithZeros() {
1851
1986
  if (!this.inverseCoffs) {
@@ -1994,7 +2129,7 @@ export class Matrix3d {
1994
2129
  /**
1995
2130
  * add scaled values from other Matrix3d to this Matrix3d
1996
2131
  * @param other Matrix3d with values to be added
1997
- * @param scale scale factor to apply to th eadded values.
2132
+ * @param scale scale factor to apply to the added values.
1998
2133
  */
1999
2134
  addScaledInPlace(other, scale) {
2000
2135
  for (let i = 0; i < 9; i++)
@@ -2057,18 +2192,18 @@ export class Matrix3d {
2057
2192
  /** Return the sum of squares of all entries */
2058
2193
  sumSquares() {
2059
2194
  let i = 0;
2060
- let a = 0;
2195
+ let sum = 0;
2061
2196
  for (i = 0; i < 9; i++)
2062
- a += this.coffs[i] * this.coffs[i];
2063
- return a;
2197
+ sum += this.coffs[i] * this.coffs[i];
2198
+ return sum;
2064
2199
  }
2065
2200
  /** Return the sum of squares of diagonal entries */
2066
2201
  sumDiagonalSquares() {
2067
2202
  let i = 0;
2068
- let a = 0;
2203
+ let sum = 0;
2069
2204
  for (i = 0; i < 9; i += 4)
2070
- a += this.coffs[i] * this.coffs[i];
2071
- return a;
2205
+ sum += this.coffs[i] * this.coffs[i];
2206
+ return sum;
2072
2207
  }
2073
2208
  /** Return the sum of diagonal entries (also known as the trace) */
2074
2209
  sumDiagonal() {
@@ -2077,18 +2212,18 @@ export class Matrix3d {
2077
2212
  /** Return the Maximum absolute value of any single entry */
2078
2213
  maxAbs() {
2079
2214
  let i = 0;
2080
- let a = 0;
2215
+ let max = 0;
2081
2216
  for (i = 0; i < 9; i++)
2082
- a = Math.max(a, Math.abs(this.coffs[i]));
2083
- return a;
2217
+ max = Math.max(max, Math.abs(this.coffs[i]));
2218
+ return max;
2084
2219
  }
2085
- /** Return the maximum absolute difference between corresponding entries */
2220
+ /** Return the maximum absolute difference between corresponding entries of `this` and `other` */
2086
2221
  maxDiff(other) {
2087
2222
  let i = 0;
2088
- let a = 0;
2223
+ let max = 0;
2089
2224
  for (i = 0; i < 9; i++)
2090
- a = Math.max(a, Math.abs(this.coffs[i] - other.coffs[i]));
2091
- return a;
2225
+ max = Math.max(max, Math.abs(this.coffs[i] - other.coffs[i]));
2226
+ return max;
2092
2227
  }
2093
2228
  /** Test if the matrix is (very near to) an identity */
2094
2229
  get isIdentity() {
@@ -2179,25 +2314,6 @@ export class Matrix3d {
2179
2314
  const product = this.multiplyMatrixMatrixTranspose(this);
2180
2315
  return product.isIdentity;
2181
2316
  }
2182
- /** create a new orthogonal matrix (perpendicular columns, unit length, transpose is inverse).
2183
- * vectorA is placed in the first column of the axis order.
2184
- * vectorB is projected perpendicular to vectorA within their plane and placed in the second column.
2185
- */
2186
- static createRigidFromColumns(vectorA, vectorB, axisOrder, result) {
2187
- const vectorA1 = vectorA.normalize();
2188
- if (vectorA1) {
2189
- const vectorC1 = vectorA1.unitCrossProduct(vectorB);
2190
- if (vectorC1) {
2191
- const vectorB1 = vectorC1.unitCrossProduct(vectorA);
2192
- if (vectorB1) {
2193
- const retVal = Matrix3d.createShuffledColumns(vectorA1, vectorB1, vectorC1, axisOrder, result);
2194
- retVal.setupInverseTranspose();
2195
- return retVal;
2196
- }
2197
- }
2198
- }
2199
- return undefined;
2200
- }
2201
2317
  /** Adjust the matrix in place so that:
2202
2318
  * * columns are perpendicular and have unit length
2203
2319
  * * transpose equals inverse
@@ -2238,8 +2354,8 @@ export class Matrix3d {
2238
2354
  return coff;
2239
2355
  }
2240
2356
  /** create a matrix from a quaternion.
2241
- * WARNING: There is frequent confusion over whether a "from quaternion" matrix is organized by rows and columns.
2242
- * WARNING: If you find that the matrix seems to rotate by the opposite angle expect it, transpose it.
2357
+ * **WARNING:** There is frequent confusion over whether a "from quaternion" matrix is organized by rows and columns.
2358
+ * **WARNING:** If you find that the matrix seems to rotate by the opposite angle expect it, transpose it.
2243
2359
  */
2244
2360
  static createFromQuaternion(quat) {
2245
2361
  const qqx = quat.x * quat.x;
@@ -2258,8 +2374,8 @@ export class Matrix3d {
2258
2374
  }
2259
2375
  /** convert the matrix to a quaternion.
2260
2376
  * @note This calculation requires the matrix to have unit length rows and columns.
2261
- * WARNING: There is frequent confusion over whether a "from quaternion" matrix is organized by rows and columns.
2262
- * WARNING: If you find that the matrix seems to rotate by the opposite angle expect it, transpose it.
2377
+ * **WARNING:** There is frequent confusion over whether a "from quaternion" matrix is organized by rows and columns.
2378
+ * **WARNING:** If you find that the matrix seems to rotate by the opposite angle expect it, transpose it.
2263
2379
  */
2264
2380
  toQuaternion() {
2265
2381
  const result = Point4d.createZero();
@@ -2313,9 +2429,9 @@ export class Matrix3d {
2313
2429
  }
2314
2430
  /** Control flag for whether this class uses cached inverse of matrices. */
2315
2431
  Matrix3d.useCachedInverse = true; // cached inverse can be suppressed for testing.
2316
- /** total number of times a cached inverse was used to avoid recompute */
2432
+ /** Total number of times a cached inverse was used to avoid recompute */
2317
2433
  Matrix3d.numUseCache = 0;
2318
- /** total number of times a cached inverse was computed. */
2434
+ /** Total number of times a cached inverse was computed. */
2319
2435
  Matrix3d.numComputeCache = 0;
2320
2436
  Matrix3d._productBuffer = new Float64Array(9);
2321
2437
  //# sourceMappingURL=Matrix3d.js.map