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