@itwin/core-geometry 4.0.0-dev.46 → 4.0.0-dev.50

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 (79) hide show
  1. package/lib/cjs/clipping/ClipPrimitive.d.ts +0 -1
  2. package/lib/cjs/clipping/ClipPrimitive.d.ts.map +1 -1
  3. package/lib/cjs/clipping/ClipPrimitive.js +0 -1
  4. package/lib/cjs/clipping/ClipPrimitive.js.map +1 -1
  5. package/lib/cjs/clipping/ClipUtils.d.ts +19 -5
  6. package/lib/cjs/clipping/ClipUtils.d.ts.map +1 -1
  7. package/lib/cjs/clipping/ClipUtils.js +32 -5
  8. package/lib/cjs/clipping/ClipUtils.js.map +1 -1
  9. package/lib/cjs/curve/CurveCurve.d.ts +2 -5
  10. package/lib/cjs/curve/CurveCurve.d.ts.map +1 -1
  11. package/lib/cjs/curve/CurveCurve.js +2 -5
  12. package/lib/cjs/curve/CurveCurve.js.map +1 -1
  13. package/lib/cjs/curve/CurveCurveIntersectXY.js +1 -1
  14. package/lib/cjs/curve/CurveCurveIntersectXY.js.map +1 -1
  15. package/lib/cjs/curve/CurveCurveIntersectXYZ.js +1 -1
  16. package/lib/cjs/curve/CurveCurveIntersectXYZ.js.map +1 -1
  17. package/lib/cjs/geometry3d/Matrix3d.d.ts +17 -4
  18. package/lib/cjs/geometry3d/Matrix3d.d.ts.map +1 -1
  19. package/lib/cjs/geometry3d/Matrix3d.js +18 -6
  20. package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
  21. package/lib/cjs/geometry3d/Plane3dByOriginAndUnitNormal.d.ts +0 -1
  22. package/lib/cjs/geometry3d/Plane3dByOriginAndUnitNormal.d.ts.map +1 -1
  23. package/lib/cjs/geometry3d/Plane3dByOriginAndUnitNormal.js +0 -1
  24. package/lib/cjs/geometry3d/Plane3dByOriginAndUnitNormal.js.map +1 -1
  25. package/lib/cjs/geometry3d/Plane3dByOriginAndVectors.d.ts +1 -1
  26. package/lib/cjs/geometry3d/Plane3dByOriginAndVectors.js +1 -1
  27. package/lib/cjs/geometry3d/Plane3dByOriginAndVectors.js.map +1 -1
  28. package/lib/cjs/geometry3d/Transform.d.ts +159 -107
  29. package/lib/cjs/geometry3d/Transform.d.ts.map +1 -1
  30. package/lib/cjs/geometry3d/Transform.js +238 -137
  31. package/lib/cjs/geometry3d/Transform.js.map +1 -1
  32. package/lib/cjs/geometry3d/XYZProps.d.ts +22 -21
  33. package/lib/cjs/geometry3d/XYZProps.d.ts.map +1 -1
  34. package/lib/cjs/geometry3d/XYZProps.js +2 -1
  35. package/lib/cjs/geometry3d/XYZProps.js.map +1 -1
  36. package/lib/cjs/polyface/PolyfaceBuilder.d.ts +7 -5
  37. package/lib/cjs/polyface/PolyfaceBuilder.d.ts.map +1 -1
  38. package/lib/cjs/polyface/PolyfaceBuilder.js +17 -7
  39. package/lib/cjs/polyface/PolyfaceBuilder.js.map +1 -1
  40. package/lib/esm/clipping/ClipPrimitive.d.ts +0 -1
  41. package/lib/esm/clipping/ClipPrimitive.d.ts.map +1 -1
  42. package/lib/esm/clipping/ClipPrimitive.js +0 -1
  43. package/lib/esm/clipping/ClipPrimitive.js.map +1 -1
  44. package/lib/esm/clipping/ClipUtils.d.ts +19 -5
  45. package/lib/esm/clipping/ClipUtils.d.ts.map +1 -1
  46. package/lib/esm/clipping/ClipUtils.js +32 -5
  47. package/lib/esm/clipping/ClipUtils.js.map +1 -1
  48. package/lib/esm/curve/CurveCurve.d.ts +2 -5
  49. package/lib/esm/curve/CurveCurve.d.ts.map +1 -1
  50. package/lib/esm/curve/CurveCurve.js +2 -5
  51. package/lib/esm/curve/CurveCurve.js.map +1 -1
  52. package/lib/esm/curve/CurveCurveIntersectXY.js +1 -1
  53. package/lib/esm/curve/CurveCurveIntersectXY.js.map +1 -1
  54. package/lib/esm/curve/CurveCurveIntersectXYZ.js +1 -1
  55. package/lib/esm/curve/CurveCurveIntersectXYZ.js.map +1 -1
  56. package/lib/esm/geometry3d/Matrix3d.d.ts +17 -4
  57. package/lib/esm/geometry3d/Matrix3d.d.ts.map +1 -1
  58. package/lib/esm/geometry3d/Matrix3d.js +18 -6
  59. package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
  60. package/lib/esm/geometry3d/Plane3dByOriginAndUnitNormal.d.ts +0 -1
  61. package/lib/esm/geometry3d/Plane3dByOriginAndUnitNormal.d.ts.map +1 -1
  62. package/lib/esm/geometry3d/Plane3dByOriginAndUnitNormal.js +0 -1
  63. package/lib/esm/geometry3d/Plane3dByOriginAndUnitNormal.js.map +1 -1
  64. package/lib/esm/geometry3d/Plane3dByOriginAndVectors.d.ts +1 -1
  65. package/lib/esm/geometry3d/Plane3dByOriginAndVectors.js +1 -1
  66. package/lib/esm/geometry3d/Plane3dByOriginAndVectors.js.map +1 -1
  67. package/lib/esm/geometry3d/Transform.d.ts +159 -107
  68. package/lib/esm/geometry3d/Transform.d.ts.map +1 -1
  69. package/lib/esm/geometry3d/Transform.js +238 -137
  70. package/lib/esm/geometry3d/Transform.js.map +1 -1
  71. package/lib/esm/geometry3d/XYZProps.d.ts +22 -21
  72. package/lib/esm/geometry3d/XYZProps.d.ts.map +1 -1
  73. package/lib/esm/geometry3d/XYZProps.js +2 -1
  74. package/lib/esm/geometry3d/XYZProps.js.map +1 -1
  75. package/lib/esm/polyface/PolyfaceBuilder.d.ts +7 -5
  76. package/lib/esm/polyface/PolyfaceBuilder.d.ts.map +1 -1
  77. package/lib/esm/polyface/PolyfaceBuilder.js +17 -7
  78. package/lib/esm/polyface/PolyfaceBuilder.js.map +1 -1
  79. package/package.json +3 -3
@@ -11,21 +11,25 @@ import { Matrix3d } from "./Matrix3d";
11
11
  import { Point2d } from "./Point2dVector2d";
12
12
  import { Point3d, Vector3d } from "./Point3dVector3d";
13
13
  import { Range3d } from "./Range";
14
- /** A transform is an origin and a Matrix3d.
15
- *
16
- * * This describes a coordinate frame with
17
- * this origin, with the columns of the Matrix3d being the
18
- * local x,y,z axis directions.
19
- * * Beware that for common transformations (e.g. scale about point,
20
- * rotate around line, mirror across a plane) the "fixed point" that is used
21
- * when describing the transform is NOT the "origin" stored in the transform.
22
- * Setup methods (e.g createFixedPointAndMatrix, createScaleAboutPoint)
23
- * take care of determining the appropriate origin coordinates.
14
+ /**
15
+ * A Transform consists of an origin and a Matrix3d. This describes a coordinate frame with this origin, with
16
+ * the columns of the Matrix3d being the local x,y,z axis directions.
17
+ * * The math for a Transform `T` consisting of a Matrix3d `M` and a Point3d `o` on a Vector3d `p` is: `Tp = M*p + o`.
18
+ * In other words, `T` is a combination of two operations on `p`: the action of matrix multiplication, followed by a
19
+ * translation. `Origin` is a traditional term for `o`, because `T` can be interpreted as a change of basis from the
20
+ * global axes centered at the global origin, to a new set of axes centered at `o`.
21
+ * * Beware that for common transformations (e.g. scale about point, rotate around an axis, mirror across a
22
+ * plane) the "fixed point" that is used when describing the transform is NOT the "origin" stored in the
23
+ * transform. Setup methods (e.g createFixedPointAndMatrix, createScaleAboutPoint) take care of determining
24
+ * the appropriate origin coordinates.
24
25
  * @public
25
26
  */
26
27
  export class Transform {
27
- // Constructor accepts and uses POINTER to content .. no copy here.
28
- constructor(origin, matrix) { this._origin = origin; this._matrix = matrix; }
28
+ // Constructor accepts and uses pointer to content (no copy is done here).
29
+ constructor(origin, matrix) {
30
+ this._origin = origin;
31
+ this._matrix = matrix;
32
+ }
29
33
  /** The identity Transform. Value is frozen and cannot be modified. */
30
34
  static get identity() {
31
35
  if (undefined === this._identity) {
@@ -35,18 +39,31 @@ export class Transform {
35
39
  return this._identity;
36
40
  }
37
41
  /** Freeze this instance (and its members) so it is read-only */
38
- freeze() { this._origin.freeze(); this._matrix.freeze(); return Object.freeze(this); }
42
+ freeze() {
43
+ this._origin.freeze();
44
+ this._matrix.freeze();
45
+ return Object.freeze(this);
46
+ }
39
47
  /**
40
48
  * Copy contents from other Transform into this Transform
41
49
  * @param other source transform
42
50
  */
43
- setFrom(other) { this._origin.setFrom(other._origin), this._matrix.setFrom(other._matrix); }
51
+ setFrom(other) {
52
+ this._origin.setFrom(other._origin);
53
+ this._matrix.setFrom(other._matrix);
54
+ }
44
55
  /** Set this Transform to be an identity. */
45
- setIdentity() { this._origin.setZero(); this._matrix.setIdentity(); }
46
- /** Set this Transform instance from flexible inputs:
47
- * * Any object (such as another Transform) that has `origin` and `matrix` members accepted by Point3d.setFromJSON and Matrix3d.setFromJSON
56
+ setIdentity() {
57
+ this._origin.setZero();
58
+ this._matrix.setIdentity();
59
+ }
60
+ /**
61
+ * Set this Transform instance from flexible inputs:
62
+ * * Any object (such as another Transform or TransformProps) that has `origin` and `matrix` members
63
+ * accepted by `Point3d.setFromJSON` and `Matrix3d.setFromJSON`
48
64
  * * An array of 3 number arrays, each with 4 entries which are rows in a 3x4 matrix.
49
65
  * * An array of 12 numbers, each block of 4 entries as a row 3x4 matrix.
66
+ * * If no input is provided, the identity Transform is returned.
50
67
  */
51
68
  setFromJSON(json) {
52
69
  if (json) {
@@ -71,25 +88,24 @@ export class Transform {
71
88
  this.setIdentity();
72
89
  }
73
90
  /**
74
- * Test for near equality with other Transform. Comparison uses the isAlmostEqual methods on
75
- * the origin and matrix parts.
91
+ * Test for near equality with `other` Transform. Comparison uses the `isAlmostEqual` methods on the `origin` and
92
+ * `matrix` parts.
76
93
  * @param other Transform to compare to.
77
94
  */
78
- isAlmostEqual(other) { return this.origin.isAlmostEqual(other.origin) && this.matrix.isAlmostEqual(other.matrix); }
95
+ isAlmostEqual(other) {
96
+ return this.origin.isAlmostEqual(other.origin) && this.matrix.isAlmostEqual(other.matrix);
97
+ }
79
98
  /**
80
- * Test for near equality with other Transform. Comparison uses the isAlmostEqualAllowZRotation method of Matrix3d
81
- * the origin and matrix parts.
99
+ * Test for near equality with `other` Transform. Comparison uses the `isAlmostEqual` methods on the `origin` part
100
+ * and the `isAlmostEqualAllowZRotation` method on the `matrix` part.
82
101
  * @param other Transform to compare to.
83
102
  */
84
- isAlmostEqualAllowZRotation(other) { return this._origin.isAlmostEqual(other._origin) && this._matrix.isAlmostEqualAllowZRotation(other._matrix); }
85
- /** Return a 3 by 4 matrix containing the rows of this Transform
86
- * * This transform's origin is the [3] entry of the json arrays
87
- */
88
- toJSON() {
89
- return this.toRows();
103
+ isAlmostEqualAllowZRotation(other) {
104
+ return this._origin.isAlmostEqual(other._origin) && this._matrix.isAlmostEqualAllowZRotation(other._matrix);
90
105
  }
91
- /** Return a 3 by 4 matrix containing the rows of this Transform
92
- * * This transform's origin is the [3] entry of the json arrays
106
+ /**
107
+ * Return a 3 by 4 matrix containing the rows of this Transform.
108
+ * * The transform's origin coordinates are the last entries of the 3 json arrays
93
109
  */
94
110
  toRows() {
95
111
  return [
@@ -98,13 +114,20 @@ export class Transform {
98
114
  [this._matrix.coffs[6], this._matrix.coffs[7], this._matrix.coffs[8], this._origin.z],
99
115
  ];
100
116
  }
101
- /** Return a new Transform initialized by `setFromJSON (json)` */
117
+ /**
118
+ * Return a 3 by 4 matrix containing the rows of this Transform.
119
+ * * The transform's origin coordinates are the last entries of the 3 json arrays
120
+ */
121
+ toJSON() {
122
+ return this.toRows();
123
+ }
124
+ /** Return a new Transform initialized by `Transform.setFromJSON` */
102
125
  static fromJSON(json) {
103
126
  const result = Transform.createIdentity();
104
127
  result.setFromJSON(json);
105
128
  return result;
106
129
  }
107
- /** Copy the contents of this transform into a new Transform (or to the result, if specified). */
130
+ /** Copy the contents of `this` transform into a new Transform (or to the result, if specified). */
108
131
  clone(result) {
109
132
  if (result) {
110
133
  result._matrix.setFrom(this._matrix);
@@ -113,18 +136,17 @@ export class Transform {
113
136
  }
114
137
  return new Transform(Point3d.createFrom(this._origin), this._matrix.clone());
115
138
  }
116
- /** Return a copy of this Transform, modified so that its axes are rigid
117
- * * The first axis direction named in axisOrder is preserved
118
- * * The plane of the first and second directions is preserved, and its vector in the rigid matrix has positive dot product with the corresponding vector if the instance
119
- * * The third named column is the cross product of the first and second.
139
+ /**
140
+ * Return a modified copy of `this` Transform so that its `matrix` part is rigid (`origin` part is untouched).
141
+ * * For details of how the matrix is modified to rigid, see documentation of `Matrix3d.axisOrderCrossProductsInPlace`
120
142
  */
121
143
  cloneRigid(axisOrder = AxisOrder.XYZ) {
122
- const axes0 = Matrix3d.createRigidFromMatrix3d(this.matrix, axisOrder);
123
- if (!axes0)
144
+ const modifiedMatrix = Matrix3d.createRigidFromMatrix3d(this.matrix, axisOrder);
145
+ if (!modifiedMatrix)
124
146
  return undefined;
125
- return new Transform(this.origin.cloneAsPoint3d(), axes0);
147
+ return new Transform(this.origin.cloneAsPoint3d(), modifiedMatrix);
126
148
  }
127
- /** Create a copy with the given origin and matrix captured as the Transform origin and Matrix3d. */
149
+ /** Create a Transform with the given `origin` and `matrix`. */
128
150
  static createRefs(origin, matrix, result) {
129
151
  if (!origin)
130
152
  origin = Point3d.createZero();
@@ -135,7 +157,7 @@ export class Transform {
135
157
  }
136
158
  return new Transform(origin, matrix);
137
159
  }
138
- /** Create a transform with complete contents given */
160
+ /** Create a Transform with complete contents given */
139
161
  static createRowValues(qxx, qxy, qxz, ax, qyx, qyy, qyz, ay, qzx, qzy, qzz, az, result) {
140
162
  if (result) {
141
163
  result._origin.set(ax, ay, az);
@@ -144,42 +166,55 @@ export class Transform {
144
166
  }
145
167
  return new Transform(Point3d.create(ax, ay, az), Matrix3d.createRowValues(qxx, qxy, qxz, qyx, qyy, qyz, qzx, qzy, qzz));
146
168
  }
147
- /** Create a transform with all zeros.
148
- */
169
+ /** Create a Transform with all zeros */
149
170
  static createZero(result) {
150
171
  return Transform.createRowValues(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, result);
151
172
  }
152
173
  /**
153
- * create a Transform with translation provided by x,y,z parts.
174
+ * Create a Transform with translation provided by x,y,z parts.
154
175
  * @param x x part of translation
155
176
  * @param y y part of translation
156
177
  * @param z z part of translation
157
- * @param result optional result
158
- * @returns new or updated transform.
178
+ * @param result optional pre-allocated Transform
179
+ * @returns new or updated transform
159
180
  */
160
181
  static createTranslationXYZ(x = 0, y = 0, z = 0, result) {
161
182
  return Transform.createRefs(Vector3d.create(x, y, z), Matrix3d.createIdentity(), result);
162
183
  }
163
- /** Create a matrix with specified translation part.
164
- * @param XYZ x,y,z parts of the translation.
165
- * @returns new or updated transform.
184
+ /**
185
+ * Create a Transform with specified `translation` part.
186
+ * @param translation x,y,z parts of the translation
187
+ * @param result optional pre-allocated Transform
188
+ * @returns new or updated transform
166
189
  */
167
190
  static createTranslation(translation, result) {
168
191
  return Transform.createRefs(translation, Matrix3d.createIdentity(), result);
169
192
  }
170
- /** Return a reference to the matrix within the transform. (NOT a copy) */
171
- get matrix() { return this._matrix; }
172
- /** Return a reference to the origin within the transform. (NOT a copy) */
173
- get origin() { return this._origin; }
174
- /** return a (clone of) the origin part of the transform, as a Point3d */
175
- getOrigin() { return Point3d.createFrom(this._origin); }
176
- /** return a (clone of) the origin part of the transform, as a Vector3d */
177
- getTranslation() { return Vector3d.createFrom(this._origin); }
178
- /** test if the transform has 000 origin and identity Matrix3d */
193
+ /** Return a reference (and NOT a copy) to the `matrix` part of the Transform. */
194
+ get matrix() {
195
+ return this._matrix;
196
+ }
197
+ /** Return a reference (and NOT a copy) to the `origin` part of the Transform. */
198
+ get origin() {
199
+ return this._origin;
200
+ }
201
+ /** return a (clone of) the `origin` part of the Transform, as a `Point3d` */
202
+ getOrigin() {
203
+ return Point3d.createFrom(this._origin);
204
+ }
205
+ /** return a (clone of) the `origin` part of the Transform, as a `Vector3d` */
206
+ getTranslation() {
207
+ return Vector3d.createFrom(this._origin);
208
+ }
209
+ /** return a (clone of) the `matrix` part of the Transform, as a `Matrix3d` */
210
+ getMatrix() {
211
+ return this._matrix.clone();
212
+ }
213
+ /** test if the transform has `origin` = (0,0,0) and identity `matrix` */
179
214
  get isIdentity() {
180
215
  return this._matrix.isIdentity && this._origin.isAlmostZero;
181
216
  }
182
- /** Return an identity transform, optionally filling existing transform. */
217
+ /** Create an identity transform */
183
218
  static createIdentity(result) {
184
219
  if (result) {
185
220
  result._origin.setZero();
@@ -188,9 +223,12 @@ export class Transform {
188
223
  }
189
224
  return Transform.createRefs(Point3d.createZero(), Matrix3d.createIdentity());
190
225
  }
191
- /** Create by directly installing origin and matrix
192
- * this is a the appropriate construction when the columns of the matrix are coordinate axes of a local-to-global mapping
193
- * Note there is a closely related createFixedPointAndMatrix whose point input is the fixed point of the global-to-global transformation.
226
+ /**
227
+ * Create a Transform using the given `origin` and `matrix`.
228
+ * * This is a the appropriate construction when the columns of the matrix are coordinate axes of a
229
+ * local-to-world mapping.
230
+ * * This function is a closely related to `createFixedPointAndMatrix` whose point input is the fixed point
231
+ * of the world-to-world transformation.
194
232
  */
195
233
  static createOriginAndMatrix(origin, matrix, result) {
196
234
  if (result) {
@@ -200,8 +238,13 @@ export class Transform {
200
238
  }
201
239
  return Transform.createRefs(origin ? origin.cloneAsPoint3d() : Point3d.createZero(), matrix === undefined ? Matrix3d.createIdentity() : matrix.clone(), result);
202
240
  }
203
- /** Create by directly installing origin and columns of the matrix
204
- */
241
+ /** Create a Transform using the given `origin` and columns of the `matrix`. If `undefined` zero is used. */
242
+ setOriginAndMatrixColumns(origin, vectorX, vectorY, vectorZ) {
243
+ if (origin !== undefined)
244
+ this._origin.setFrom(origin);
245
+ this._matrix.setColumns(vectorX, vectorY, vectorZ);
246
+ }
247
+ /** Create a Transform using the given `origin` and columns of the `matrix` */
205
248
  static createOriginAndMatrixColumns(origin, vectorX, vectorY, vectorZ, result) {
206
249
  if (result)
207
250
  result.setOriginAndMatrixColumns(origin, vectorX, vectorY, vectorZ);
@@ -209,127 +252,177 @@ export class Transform {
209
252
  result = Transform.createRefs(Vector3d.createFrom(origin), Matrix3d.createColumns(vectorX, vectorY, vectorZ));
210
253
  return result;
211
254
  }
212
- /** Create by with matrix from Matrix3d.createRigidFromColumns.
213
- * * Has careful logic for building up optional result without allocations.
255
+ /**
256
+ * Create a Transform such that its `matrix` part is rigid.
257
+ * * For details of how the matrix is created to be rigid, see documentation of `Matrix3d.createRigidFromColumns`
214
258
  */
215
259
  static createRigidFromOriginAndColumns(origin, vectorX, vectorY, axisOrder, result) {
216
260
  const matrix = Matrix3d.createRigidFromColumns(vectorX, vectorY, axisOrder, result ? result._matrix : undefined);
217
261
  if (!matrix)
218
262
  return undefined;
219
263
  if (result) {
220
- // The matrix was already defined !!!
264
+ // result._matrix was already modified to become rigid via createRigidFromColumns
221
265
  result._origin.setFrom(origin);
222
266
  return result;
223
267
  }
224
- // cleanly capture the matrix and then the point ..
268
+ /**
269
+ * We don't want to pass "origin" to createRefs because createRefs does not clone "origin" and use its reference.
270
+ * That means if "origin" is changed via Transform at any point, the initial "origin" passed by the user is also
271
+ * changed. To avoid that, we pass undefined to createRefs. This would cause createRefs to create a new "origin"
272
+ * equals (0,0,0) which then we set it to the "origin" passed by user in the next line.
273
+ */
225
274
  result = Transform.createRefs(undefined, matrix);
226
275
  result._origin.setFromPoint3d(origin);
227
276
  return result;
228
277
  }
229
- /** Reinitialize by directly installing origin and columns of the matrix
230
- */
231
- setOriginAndMatrixColumns(origin, vectorX, vectorY, vectorZ) {
232
- if (origin !== undefined)
233
- this._origin.setFrom(origin);
234
- this._matrix.setColumns(vectorX, vectorY, vectorZ);
235
- }
236
- /** Create a transform with the specified matrix. Compute an origin (different from the given fixedPoint)
237
- * so that the fixedPoint maps back to itself.
278
+ /**
279
+ * Create a Transform with the specified `matrix`. Compute an `origin` (different from the given `fixedPoint`)
280
+ * so that the `fixedPoint` maps back to itself. The returned Transform, transforms a point `p` to `M*p + (f - M*f)`
281
+ * where `f` is the fixedPoint (i.e., `Tp = M*(p-f) + f`).
238
282
  */
239
283
  static createFixedPointAndMatrix(fixedPoint, matrix, result) {
240
284
  if (fixedPoint) {
285
+ /**
286
+ * if f is a fixed point, then Tf = M*f + o = f where M is the matrix and o is the origin.
287
+ * we define the origin o = f - M*f. Therefore, Tf = Mf + o = M*f + (f - M*f) = f.
288
+ */
241
289
  const origin = Matrix3d.xyzMinusMatrixTimesXYZ(fixedPoint, matrix, fixedPoint);
242
290
  return Transform.createRefs(origin, matrix.clone(), result);
243
291
  }
244
292
  return Transform.createRefs(undefined, matrix.clone());
245
293
  }
246
- /** Create a transform with the specified matrix, acting on any `pointX `via
247
- * `pointY = matrix * (pointX - pointA) + pointB`
248
- * so that the fixedPoint maps back to itself.
294
+ /**
295
+ * Create a transform with the specified `matrix` and points `a` and `b`. The returned Transform, transforms
296
+ * point `p` to `M*(p-a) + b` (i.e., `Tp = M*(p-a) + b`) so transforms point `a` to 'b'.
249
297
  */
250
- static createMatrixPickupPutdown(matrix, pointA, pointB, result) {
251
- const origin = Matrix3d.xyzMinusMatrixTimesXYZ(pointB, matrix, pointA);
298
+ static createMatrixPickupPutdown(matrix, a, b, result) {
299
+ // we define the origin o = b - M*a so Tp = M*p + o = M*p + (b - M*a) = M*(x-a) + b
300
+ const origin = Matrix3d.xyzMinusMatrixTimesXYZ(b, matrix, a);
252
301
  return Transform.createRefs(origin, matrix.clone(), result);
253
302
  }
254
- /** Create a Transform which leaves the fixedPoint unchanged and
255
- * scales everything else around it by a single scale factor.
303
+ /**
304
+ * Create a Transform which leaves the fixedPoint unchanged and scales everything else around it by
305
+ * a single scale factor. The returned Transform, transforms a point `p` to `M*p + (f - M*f)`
306
+ * where `f` is the fixedPoint and M is the scale matrix (i.e., `Tp = M*(p-f) + f`).
256
307
  */
257
308
  static createScaleAboutPoint(fixedPoint, scale, result) {
258
309
  const matrix = Matrix3d.createScale(scale, scale, scale);
310
+ /**
311
+ * if f is a fixed point, then Tf = M*f + o = f where M is the matrix and o is the origin.
312
+ * we define the origin o = f - M*f. Therefore, Tf = M*f + o = M*f + (f - M*f) = f.
313
+ */
259
314
  const origin = Matrix3d.xyzMinusMatrixTimesXYZ(fixedPoint, matrix, fixedPoint);
260
315
  return Transform.createRefs(origin, matrix, result);
261
316
  }
262
- /** Transform the input 2d point. Return as a new point or in the pre-allocated result (if result is given) */
263
- multiplyPoint2d(source, result) {
264
- return Matrix3d.xyPlusMatrixTimesXY(this._origin, this._matrix, source, result);
317
+ /** Transform the input 2d point. Return as a new point or in the pre-allocated result (if result is given). */
318
+ multiplyPoint2d(point, result) {
319
+ // Tx = Mx + o so we return Mx + o
320
+ return Matrix3d.xyPlusMatrixTimesXY(this._origin, this._matrix, point, result);
265
321
  }
266
- /** Transform the input 3d point. Return as a new point or in the pre-allocated result (if result is given) */
322
+ /** Transform the input 3d point. Return as a new point or in the pre-allocated result (if result is given). */
267
323
  multiplyPoint3d(point, result) {
324
+ // Tx = Mx + o so we return Mx + o
268
325
  return Matrix3d.xyzPlusMatrixTimesXYZ(this._origin, this._matrix, point, result);
269
326
  }
270
- /** Transform the input object with x,y,z members */
327
+ /** Transform the input 3d point in place (override the input point by the transformed point). */
271
328
  multiplyXYAndZInPlace(point) {
329
+ // Tx = Mx + o so we override x by Mx + o
272
330
  return Matrix3d.xyzPlusMatrixTimesXYZInPlace(this._origin, this._matrix, point);
273
331
  }
274
- /** Transform the input point. Return as a new point or in the pre-allocated result (if result is given) */
332
+ /** Transform the input point. Return as a new point or in the pre-allocated result (if result is given). */
275
333
  multiplyXYZ(x, y, z = 0, result) {
334
+ // Tx = Mx + o so we return Mx + o
276
335
  return Matrix3d.xyzPlusMatrixTimesCoordinates(this._origin, this._matrix, x, y, z, result);
277
336
  }
278
- /** Multiply a specific row of the transform times xyz. Return the (number). */
337
+ /**
338
+ * Multiply a specific row (component) of the transform matrix times xyz and add it to the origin element
339
+ * at the same row. Return the result.
340
+ */
279
341
  multiplyComponentXYZ(componentIndex, x, y, z = 0) {
280
342
  const coffs = this._matrix.coffs;
281
- const i0 = 3 * componentIndex;
282
- return this.origin.at(componentIndex) + coffs[i0] * x + coffs[i0 + 1] * y + coffs[i0 + 2] * z;
343
+ const idx = 3 * componentIndex;
344
+ return this.origin.at(componentIndex) + (coffs[idx] * x) + (coffs[idx + 1] * y) + (coffs[idx + 2] * z);
283
345
  }
284
- /** Multiply a specific row of the transform times (weighted!) xyzw. Return the (number). */
346
+ /**
347
+ * Multiply a specific row (component) of the transform matrix times xyz and add it to the origin element
348
+ * at the same row times w. Return the result.
349
+ */
285
350
  multiplyComponentXYZW(componentIndex, x, y, z, w) {
286
351
  const coffs = this._matrix.coffs;
287
- const i0 = 3 * componentIndex;
288
- return this.origin.at(componentIndex) * w +
289
- coffs[i0] * x + coffs[i0 + 1] * y + coffs[i0 + 2] * z;
352
+ const idx = 3 * componentIndex;
353
+ return (this.origin.at(componentIndex) * w) + (coffs[idx] * x) + (coffs[idx + 1] * y) + (coffs[idx + 2] * z);
290
354
  }
291
- /** Transform the input homogeneous point. Return as a new point or in the pre-allocated result (if result is given) */
355
+ /**
356
+ * If `p = (x,y,z)` then transform is `Tp = M*p + o*w`. This function returns the transformed point as a new
357
+ * point4d (`Tp` as first 3 elements and `w` as last element) or in the pre-allocated result (if result is given).
358
+ */
292
359
  multiplyXYZW(x, y, z, w, result) {
293
360
  return Matrix3d.xyzPlusMatrixTimesWeightedCoordinates(this._origin, this._matrix, x, y, z, w, result);
294
361
  }
295
- /** Transform the input homogeneous point. Return as a new point or in the pre-allocated result (if result is given) */
362
+ /**
363
+ * If `p = (x,y,z)` then transform is `Tp = M*p + o*w`. This function returns the transformed point as a new
364
+ * Float64Array with size 4 (`Tp` as first 3 elements and `w` as last element) or in the pre-allocated result
365
+ * (if result is given).
366
+ */
296
367
  multiplyXYZWToFloat64Array(x, y, z, w, result) {
297
368
  return Matrix3d.xyzPlusMatrixTimesWeightedCoordinatesToFloat64Array(this._origin, this._matrix, x, y, z, w, result);
298
369
  }
299
- /** Transform the input homogeneous point. Return as a new point or in the pre-allocated result (if result is given) */
370
+ /**
371
+ * If `p = (x,y,z)` then transform is `Tp = M*p + o`. This function returns the transformed point as a new
372
+ * Float64Array with size 3 (`Tp` as 3 elements) or in the pre-allocated result (if result is given).
373
+ */
300
374
  multiplyXYZToFloat64Array(x, y, z, result) {
301
375
  return Matrix3d.xyzPlusMatrixTimesCoordinatesToFloat64Array(this._origin, this._matrix, x, y, z, result);
302
376
  }
303
- /** Multiply the transposed transform (as 4x4 with 0001 row) by Point4d given as xyzw.. Return as a new point or in the pre-allocated result (if result is given) */
377
+ /**
378
+ * Treat the 3x3 matrix and origin as upper 3x4 part of a 4x4 matrix, with 0001 as the final row. Now multiply
379
+ * the transposed of this 4x4 matrix by Point4d given as xyzw. Return as a new point4d (`M*p` as first 3 elements
380
+ * and `o*p + w` as last element where `p = (x,y,z)`) or in the pre-allocated result (if result is given).
381
+ */
304
382
  multiplyTransposeXYZW(x, y, z, w, result) {
305
383
  const coffs = this._matrix.coffs;
306
384
  const origin = this._origin;
307
- return Point4d.create(x * coffs[0] + y * coffs[3] + z * coffs[6], x * coffs[1] + y * coffs[4] + z * coffs[7], x * coffs[2] + y * coffs[5] + z * coffs[8], x * origin.x + y * origin.y + z * origin.z + w, result);
385
+ return Point4d.create((x * coffs[0]) + (y * coffs[3]) + (z * coffs[6]), (x * coffs[1]) + (y * coffs[4]) + (z * coffs[7]), (x * coffs[2]) + (y * coffs[5]) + (z * coffs[8]), (x * origin.x) + (y * origin.y) + (z * origin.z) + w, result);
308
386
  }
309
- /** for each point: replace point by Transform*point */
387
+ /** For each point in the array, replace point by the transformed point (by `Tp = M*p + o`) */
310
388
  multiplyPoint3dArrayInPlace(points) {
311
389
  let point;
312
390
  for (point of points)
313
391
  Matrix3d.xyzPlusMatrixTimesXYZ(this._origin, this._matrix, point, point);
314
392
  }
315
- /** for each point: replace point by Transform*point */
393
+ /** For each point in the 2d array, replace point by the transformed point (by `Tp = M*p + o`) */
316
394
  multiplyPoint3dArrayArrayInPlace(chains) {
317
395
  for (const chain of chains)
318
396
  this.multiplyPoint3dArrayInPlace(chain);
319
397
  }
320
- /** Return product of the transform's inverse times a point. */
398
+ /**
399
+ * If for a point `p` we have `Tp = M*p + o = point` (where `point` is the transformed point), then
400
+ * `p = MInverse * (point - o)`. This function returns the original point `p` if `point` is the
401
+ * transformed point (`Tp = point`).
402
+ * * Return as a new point or in the optional `result`.
403
+ * * Returns `undefined` if the `matrix` part if this Transform is singular.
404
+ */
321
405
  multiplyInversePoint3d(point, result) {
322
406
  return this._matrix.multiplyInverseXYZAsPoint3d(point.x - this._origin.x, point.y - this._origin.y, point.z - this._origin.z, result);
323
407
  }
324
- /** Inverse transform the input homogeneous point.
325
- * * Return as a new point or in the optional result.
326
- * * returns undefined if the matrix part if this Transform is singular.
408
+ /**
409
+ * If for a point `p` we have `Tp = M*p + w*o = weightedPoint` (where `weightedPoint` is the transformed point), then
410
+ * `p = MInverse * (weightedPoint - w*o)`. This function returns a Point4d where first 3 elements are the original
411
+ * point `p` if `weightedPoint` is the transformed point (`Tp = weightedPoint`) and the last element is `w`.
412
+ * * Return as a new point or in the optional `result`.
413
+ * * Returns `undefined` if the `matrix` part if this Transform is singular.
327
414
  */
328
415
  multiplyInversePoint4d(weightedPoint, result) {
329
416
  const w = weightedPoint.w;
330
417
  return this._matrix.multiplyInverseXYZW(weightedPoint.x - w * this.origin.x, weightedPoint.y - w * this.origin.y, weightedPoint.z - w * this.origin.z, w, result);
331
418
  }
332
- /** Return product of the transform's inverse times a point (point given as x,y,z) */
419
+ /**
420
+ * If for a point `p = (x,y,z)` we have `Tp = M*p + o = point` (where `point` is the transformed point), then
421
+ * `p = MInverse * (point - o)`. This function returns the original point `p` if `point` is the transformed
422
+ * point (`Tp = point`).
423
+ * * Return as a new point or in the optional `result`.
424
+ * * Returns `undefined` if the `matrix` part if this Transform is singular.
425
+ */
333
426
  multiplyInverseXYZ(x, y, z, result) {
334
427
  return this._matrix.multiplyInverseXYZAsPoint3d(x - this._origin.x, y - this._origin.y, z - this._origin.z, result);
335
428
  }
@@ -355,8 +448,8 @@ export class Transform {
355
448
  return result;
356
449
  }
357
450
  /**
358
- * * for each point in source: multiply transformInverse * point in place in the point.
359
- * * return false if not invertible.
451
+ * * For each point in source: multiply transformInverse * point in place in the point.
452
+ * * Return false if not invertible.
360
453
  */
361
454
  multiplyInversePoint3dArrayInPlace(source) {
362
455
  if (!this._matrix.computeCachedInverse(true))
@@ -400,9 +493,9 @@ export class Transform {
400
493
  return numSource;
401
494
  }
402
495
  /**
403
- * * for each point: multiply transform * point
404
- * * if result is given, resize to match source and replace each corresponding pi
405
- * * if result is not given, return a new array.
496
+ * * For each point: multiply transform * point
497
+ * * If result is given, resize to match source and replace each corresponding pi
498
+ * * If result is not given, return a new array.
406
499
  */
407
500
  multiplyPoint2dArray(source, result) {
408
501
  if (result) {
@@ -417,9 +510,9 @@ export class Transform {
417
510
  return result;
418
511
  }
419
512
  /**
420
- * * for each point: multiply transform * point
421
- * * if result is given, resize to match source and replace each corresponding pi
422
- * * if result is not given, return a new array.
513
+ * * For each point: multiply transform * point
514
+ * * If result is given, resize to match source and replace each corresponding pi
515
+ * * If result is not given, return a new array.
423
516
  */
424
517
  multiplyPoint3dArray(source, result) {
425
518
  if (result) {
@@ -433,30 +526,30 @@ export class Transform {
433
526
  result.push(Matrix3d.xyzPlusMatrixTimesXYZ(this._origin, this._matrix, p));
434
527
  return result;
435
528
  }
436
- /** Multiply the vector by the Matrix3d part of the transform.
437
- *
438
- * * The transform's origin is not used.
439
- * * Return as new or result by usual optional result convention
529
+ /**
530
+ * Multiply the vector by the Matrix3d part of the transform.
531
+ * * The transform's origin is not used.
532
+ * * Return as new or result by usual optional result convention
440
533
  */
441
534
  multiplyVector(vector, result) {
442
535
  return this._matrix.multiplyVector(vector, result);
443
536
  }
444
- /** Multiply the vector in place by the Matrix3d part of the transform.
445
- *
446
- * * The transform's origin is not used.
447
- */
537
+ /**
538
+ * Multiply the vector in place by the Matrix3d part of the transform.
539
+ * * The transform's origin is not used.
540
+ */
448
541
  multiplyVectorInPlace(vector) {
449
542
  this._matrix.multiplyVectorInPlace(vector);
450
543
  }
451
- /** Multiply the vector (x,y,z) by the Matrix3d part of the transform.
452
- *
453
- * * The transform's origin is not used.
454
- * * Return as new or result by usual optional result convention
544
+ /**
545
+ * Multiply the vector (x,y,z) by the Matrix3d part of the transform.
546
+ * * The transform's origin is not used.
547
+ * * Return as new or result by usual optional result convention
455
548
  */
456
549
  multiplyVectorXYZ(x, y, z, result) {
457
550
  return this._matrix.multiplyXYZ(x, y, z, result);
458
551
  }
459
- /** multiply this Transform times other Transform.
552
+ /** Multiply this Transform times other Transform.
460
553
  * ```
461
554
  * equation
462
555
  * \begin{matrix}
@@ -475,7 +568,7 @@ export class Transform {
475
568
  return result;
476
569
  }
477
570
  /**
478
- * multiply transformA * transformB, store to calling instance.
571
+ * Multiply transformA * transformB, store to calling instance.
479
572
  * @param transformA left operand
480
573
  * @param transformB right operand
481
574
  */
@@ -488,7 +581,8 @@ export class Transform {
488
581
  }
489
582
  // [Q A][R 0] = [QR A]
490
583
  // [0 1][0 1] [0 1]
491
- /** multiply this Transform times other Matrix3d, with other considered to be a Transform with 0 translation.
584
+ /**
585
+ * Multiply this Transform times other Matrix3d, with other considered to be a Transform with 0 translation.
492
586
  * ```
493
587
  * equation
494
588
  * \begin{matrix}
@@ -511,7 +605,7 @@ export class Transform {
511
605
  * Return the range of the transformed corners.
512
606
  * * The 8 corners are transformed individually.
513
607
  * * Note that if there is anything other than translation and principal axis scaling in the transform, the volume of the range rotation will increase.
514
- * * Hence to get a "tight" range on rotated geometry, a range computation must be made on the rotated geometry itself.
608
+ * * Hence to get a "tight" range on rotated geometry, a range computation must be made on the rotated geometry itself.
515
609
  */
516
610
  multiplyRange(range, result) {
517
611
  if (range.isNull)
@@ -536,15 +630,22 @@ export class Transform {
536
630
  }
537
631
  /**
538
632
  * * Return a Transform which is the inverse of this transform.
539
- * * Return undefined if this Transform's matrix is singular.
633
+ * @param result optional pre-allocated result
634
+ * @return the inverse Transform, or undefined if the matrix is singular
540
635
  */
541
- inverse() {
542
- const matrixInverse = this._matrix.inverse();
636
+ inverse(result) {
637
+ const matrixInverse = this._matrix.inverse(result ? result._matrix : undefined);
543
638
  if (!matrixInverse)
544
639
  return undefined;
640
+ if (result) {
641
+ // result._matrix is already defined
642
+ matrixInverse.multiplyXYZ(-this._origin.x, -this._origin.y, -this._origin.z, result._origin);
643
+ return result;
644
+ }
545
645
  return Transform.createRefs(matrixInverse.multiplyXYZ(-this._origin.x, -this._origin.y, -this._origin.z), matrixInverse);
546
646
  }
547
- /** Initialize transforms that map each direction of a box (axis aligned) to `[0,1]`.
647
+ /**
648
+ * Initialize transforms that map each direction of a box (axis aligned) to `[0,1]`.
548
649
  * * The corner coordinates do _not_ need to be in order in any of the x,y,z directions.
549
650
  * * The npcToGlobalTransform (if supplied) maps 000 to the point named point000.
550
651
  * * The npcToGlobalTransform (if supplied) maps 11 to the point named point000.