@itwin/core-geometry 4.0.0-dev.51 → 4.0.0-dev.52
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/lib/cjs/geometry3d/Matrix3d.d.ts +9 -5
- package/lib/cjs/geometry3d/Matrix3d.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Matrix3d.js +9 -6
- package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
- package/lib/cjs/geometry3d/Transform.d.ts +112 -75
- package/lib/cjs/geometry3d/Transform.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Transform.js +159 -119
- package/lib/cjs/geometry3d/Transform.js.map +1 -1
- package/lib/esm/geometry3d/Matrix3d.d.ts +9 -5
- package/lib/esm/geometry3d/Matrix3d.d.ts.map +1 -1
- package/lib/esm/geometry3d/Matrix3d.js +9 -6
- package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
- package/lib/esm/geometry3d/Transform.d.ts +112 -75
- package/lib/esm/geometry3d/Transform.d.ts.map +1 -1
- package/lib/esm/geometry3d/Transform.js +159 -119
- package/lib/esm/geometry3d/Transform.js.map +1 -1
- package/package.json +3 -3
|
@@ -17,11 +17,15 @@ import { Range3d } from "./Range";
|
|
|
17
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
18
|
* In other words, `T` is a combination of two operations on `p`: the action of matrix multiplication, followed by a
|
|
19
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
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
20
|
+
* global axes centered at the global origin, to a new set of axes specified by matrix M columns centered at `o`.
|
|
21
|
+
* * Beware that for common transformations (e.g. scale about point, rotate around an axis) the `fixed point` that
|
|
22
|
+
* is used when describing the transform is NOT the `origin` stored in the transform. Setup methods (e.g
|
|
23
|
+
* createFixedPointAndMatrix, createScaleAboutPoint) take care of determining the appropriate origin coordinates.
|
|
24
|
+
* * If `T` is a translation, no point is fixed by `T`.
|
|
25
|
+
* * If `T` is the identity, all points are fixed by `T`.
|
|
26
|
+
* * If `T` is a scale about a point, one point is fixed by `T`.
|
|
27
|
+
* * If `T` is a rotation about an axis, a line is fixed by `T`.
|
|
28
|
+
* * If `T` is a projection to the plane, a plane is fixed by `T`.
|
|
25
29
|
* @public
|
|
26
30
|
*/
|
|
27
31
|
export class Transform {
|
|
@@ -314,22 +318,32 @@ export class Transform {
|
|
|
314
318
|
const origin = Matrix3d.xyzMinusMatrixTimesXYZ(fixedPoint, matrix, fixedPoint);
|
|
315
319
|
return Transform.createRefs(origin, matrix, result);
|
|
316
320
|
}
|
|
317
|
-
/**
|
|
321
|
+
/**
|
|
322
|
+
* Transform the input 2d point (using `Tp = M*p + o`).
|
|
323
|
+
* Return as a new point or in the pre-allocated result (if result is given).
|
|
324
|
+
*/
|
|
318
325
|
multiplyPoint2d(point, result) {
|
|
319
|
-
// Tx = Mx + o so we return Mx + o
|
|
320
326
|
return Matrix3d.xyPlusMatrixTimesXY(this._origin, this._matrix, point, result);
|
|
321
327
|
}
|
|
322
|
-
/**
|
|
328
|
+
/**
|
|
329
|
+
* Transform the input 3d point (using `Tp = M*p + o`).
|
|
330
|
+
* Return as a new point or in the pre-allocated result (if result is given).
|
|
331
|
+
*/
|
|
323
332
|
multiplyPoint3d(point, result) {
|
|
324
333
|
// Tx = Mx + o so we return Mx + o
|
|
325
334
|
return Matrix3d.xyzPlusMatrixTimesXYZ(this._origin, this._matrix, point, result);
|
|
326
335
|
}
|
|
327
|
-
/**
|
|
336
|
+
/**
|
|
337
|
+
* Transform the input 3d point in place (using `Tp = M*p + o`).
|
|
338
|
+
* Return as a new point or in the pre-allocated result (if result is given).
|
|
339
|
+
*/
|
|
328
340
|
multiplyXYAndZInPlace(point) {
|
|
329
|
-
// Tx = Mx + o so we override x by Mx + o
|
|
330
341
|
return Matrix3d.xyzPlusMatrixTimesXYZInPlace(this._origin, this._matrix, point);
|
|
331
342
|
}
|
|
332
|
-
/**
|
|
343
|
+
/**
|
|
344
|
+
* Transform the input 3d point (using `Tp = M*p + o`).
|
|
345
|
+
* Return as a new point or in the pre-allocated result (if result is given).
|
|
346
|
+
*/
|
|
333
347
|
multiplyXYZ(x, y, z = 0, result) {
|
|
334
348
|
// Tx = Mx + o so we return Mx + o
|
|
335
349
|
return Matrix3d.xyzPlusMatrixTimesCoordinates(this._origin, this._matrix, x, y, z, result);
|
|
@@ -375,7 +389,7 @@ export class Transform {
|
|
|
375
389
|
return Matrix3d.xyzPlusMatrixTimesCoordinatesToFloat64Array(this._origin, this._matrix, x, y, z, result);
|
|
376
390
|
}
|
|
377
391
|
/**
|
|
378
|
-
* Treat the 3x3 matrix and origin as upper 3x4 part of a 4x4 matrix, with 0001 as the final row. Now multiply
|
|
392
|
+
* Treat the 3x3 `matrix` and `origin` as upper 3x4 part of a 4x4 matrix, with 0001 as the final row. Now multiply
|
|
379
393
|
* the transposed of this 4x4 matrix by Point4d given as xyzw. Return as a new point4d (`M*p` as first 3 elements
|
|
380
394
|
* and `o*p + w` as last element where `p = (x,y,z)`) or in the pre-allocated result (if result is given).
|
|
381
395
|
*/
|
|
@@ -384,13 +398,13 @@ export class Transform {
|
|
|
384
398
|
const origin = this._origin;
|
|
385
399
|
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);
|
|
386
400
|
}
|
|
387
|
-
/** For each point in the array, replace point by the transformed point (
|
|
401
|
+
/** For each point in the array, replace point by the transformed point (using `Tp = M*p + o`) */
|
|
388
402
|
multiplyPoint3dArrayInPlace(points) {
|
|
389
403
|
let point;
|
|
390
404
|
for (point of points)
|
|
391
405
|
Matrix3d.xyzPlusMatrixTimesXYZ(this._origin, this._matrix, point, point);
|
|
392
406
|
}
|
|
393
|
-
/** For each point in the 2d array, replace point by the transformed point (
|
|
407
|
+
/** For each point in the 2d array, replace point by the transformed point (using `Tp = M*p + o`) */
|
|
394
408
|
multiplyPoint3dArrayArrayInPlace(chains) {
|
|
395
409
|
for (const chain of chains)
|
|
396
410
|
this.multiplyPoint3dArrayInPlace(chain);
|
|
@@ -427,58 +441,23 @@ export class Transform {
|
|
|
427
441
|
return this._matrix.multiplyInverseXYZAsPoint3d(x - this._origin.x, y - this._origin.y, z - this._origin.z, result);
|
|
428
442
|
}
|
|
429
443
|
/**
|
|
430
|
-
* *
|
|
431
|
-
*
|
|
432
|
-
* * if result is not given, return a new array.
|
|
433
|
-
*/
|
|
434
|
-
multiplyInversePoint3dArray(source, result) {
|
|
435
|
-
if (!this._matrix.computeCachedInverse(true))
|
|
436
|
-
return undefined;
|
|
437
|
-
const originX = this.origin.x;
|
|
438
|
-
const originY = this.origin.y;
|
|
439
|
-
const originZ = this.origin.z;
|
|
440
|
-
if (result) {
|
|
441
|
-
const n = Transform.matchArrayLengths(source, result, Point3d.createZero);
|
|
442
|
-
for (let i = 0; i < n; i++)
|
|
443
|
-
this._matrix.multiplyInverseXYZAsPoint3d(source[i].x - originX, source[i].y - originY, source[i].z - originZ, result[i]);
|
|
444
|
-
}
|
|
445
|
-
result = [];
|
|
446
|
-
for (const p of source)
|
|
447
|
-
result.push(this._matrix.multiplyInverseXYZAsPoint3d(p.x - originX, p.y - originY, p.z - originZ));
|
|
448
|
-
return result;
|
|
449
|
-
}
|
|
450
|
-
/**
|
|
451
|
-
* * For each point in source: multiply transformInverse * point in place in the point.
|
|
452
|
-
* * Return false if not invertible.
|
|
453
|
-
*/
|
|
454
|
-
multiplyInversePoint3dArrayInPlace(source) {
|
|
455
|
-
if (!this._matrix.computeCachedInverse(true))
|
|
456
|
-
return false;
|
|
457
|
-
const originX = this.origin.x;
|
|
458
|
-
const originY = this.origin.y;
|
|
459
|
-
const originZ = this.origin.z;
|
|
460
|
-
const n = source.length;
|
|
461
|
-
for (let i = 0; i < n; i++)
|
|
462
|
-
this._matrix.multiplyInverseXYZAsPoint3d(source[i].x - originX, source[i].y - originY, source[i].z - originZ, source[i]);
|
|
463
|
-
return true;
|
|
464
|
-
}
|
|
465
|
-
/**
|
|
466
|
-
* * Compute (if needed) the inverse of the matrix part, thereby ensuring inverse operations can complete.
|
|
467
|
-
* * Return true if matrix inverse completes.
|
|
444
|
+
* * Compute (if needed) the inverse of the `matrix` part of the Transform, thereby ensuring inverse
|
|
445
|
+
* operations can complete.
|
|
468
446
|
* @param useCached If true, accept prior cached inverse if available.
|
|
447
|
+
* @returns `true` if matrix inverse completes, `false` otherwise.
|
|
469
448
|
*/
|
|
470
449
|
computeCachedInverse(useCached = true) {
|
|
471
450
|
return this._matrix.computeCachedInverse(useCached);
|
|
472
451
|
}
|
|
473
452
|
/**
|
|
474
|
-
*
|
|
475
|
-
* * If destination has
|
|
476
|
-
*
|
|
477
|
-
*
|
|
478
|
-
* @param
|
|
453
|
+
* Match the length of destination array with the length of source array
|
|
454
|
+
* * If destination has more elements than source, remove the extra elements.
|
|
455
|
+
* * If destination has fewer elements than source, use `constructionFunction` to create new elements.
|
|
456
|
+
* *
|
|
457
|
+
* @param source the source array
|
|
458
|
+
* @param dest the destination array
|
|
459
|
+
* @param constructionFunction function to call to create new elements.
|
|
479
460
|
*/
|
|
480
|
-
// modify destination so it has non-null points for the same length as the source.
|
|
481
|
-
// (ASSUME existing elements of dest are non-null, and that parameters are given as either Point2d or Point3d arrays)
|
|
482
461
|
static matchArrayLengths(source, dest, constructionFunction) {
|
|
483
462
|
const numSource = source.length;
|
|
484
463
|
const numDest = dest.length;
|
|
@@ -493,72 +472,125 @@ export class Transform {
|
|
|
493
472
|
return numSource;
|
|
494
473
|
}
|
|
495
474
|
/**
|
|
496
|
-
*
|
|
497
|
-
* *
|
|
498
|
-
*
|
|
475
|
+
* If for each point `p` we have `Tp = M*p + o = point` (where `point` is the transformed point), then
|
|
476
|
+
* `p = MInverse * (point - o)`. This function returns the array of original points `p[]` if `points`
|
|
477
|
+
* is the array of transformed point (`Tp = point` for each `p` and `point`).
|
|
478
|
+
* * If `results` is given, resize it to match the input `points` array and update it with original points `p[]`.
|
|
479
|
+
* * If `results` is not given, return a new array.
|
|
480
|
+
* * Returns `undefined` if the `matrix` part if this Transform is singular.
|
|
499
481
|
*/
|
|
500
|
-
|
|
482
|
+
multiplyInversePoint3dArray(points, results) {
|
|
483
|
+
if (!this._matrix.computeCachedInverse(true))
|
|
484
|
+
return undefined;
|
|
485
|
+
const originX = this.origin.x;
|
|
486
|
+
const originY = this.origin.y;
|
|
487
|
+
const originZ = this.origin.z;
|
|
488
|
+
if (results) {
|
|
489
|
+
const n = Transform.matchArrayLengths(points, results, Point3d.createZero);
|
|
490
|
+
for (let i = 0; i < n; i++)
|
|
491
|
+
this._matrix.multiplyInverseXYZAsPoint3d(points[i].x - originX, points[i].y - originY, points[i].z - originZ, results[i]);
|
|
492
|
+
}
|
|
493
|
+
results = [];
|
|
494
|
+
for (const point of points)
|
|
495
|
+
results.push(this._matrix.multiplyInverseXYZAsPoint3d(point.x - originX, point.y - originY, point.z - originZ));
|
|
496
|
+
return results;
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* If for each point `p` we have `Tp = M*p + o = point` (where `point` is the transformed point), then
|
|
500
|
+
* `p = MInverse * (point - o)`. This function calculates the array of original points `p[]` if `points`
|
|
501
|
+
* is the array of transformed point (`Tp = point` for each `p` and `point`) and replaces `points`
|
|
502
|
+
* with the array of original points.
|
|
503
|
+
* * Returns `true` if the `matrix` part if this Transform is invertible and `false if singular.
|
|
504
|
+
*/
|
|
505
|
+
multiplyInversePoint3dArrayInPlace(points) {
|
|
506
|
+
if (!this._matrix.computeCachedInverse(true))
|
|
507
|
+
return false;
|
|
508
|
+
for (const point of points)
|
|
509
|
+
this._matrix.multiplyInverseXYZAsPoint3d(point.x - this.origin.x, point.y - this.origin.y, point.z - this.origin.z, point);
|
|
510
|
+
return true;
|
|
511
|
+
}
|
|
512
|
+
/**
|
|
513
|
+
* Transform the input 2d point array (using `Tp = M*p + o`).
|
|
514
|
+
* * If `result` is given, resize it to match the input `points` array and update it with transformed points.
|
|
515
|
+
* * If `result` is not given, return a new array.
|
|
516
|
+
*/
|
|
517
|
+
multiplyPoint2dArray(points, result) {
|
|
501
518
|
if (result) {
|
|
502
|
-
const n = Transform.matchArrayLengths(
|
|
519
|
+
const n = Transform.matchArrayLengths(points, result, Point2d.createZero);
|
|
503
520
|
for (let i = 0; i < n; i++)
|
|
504
|
-
Matrix3d.xyPlusMatrixTimesXY(this._origin, this._matrix,
|
|
521
|
+
Matrix3d.xyPlusMatrixTimesXY(this._origin, this._matrix, points[i], result[i]);
|
|
505
522
|
return result;
|
|
506
523
|
}
|
|
507
524
|
result = [];
|
|
508
|
-
for (const p of
|
|
525
|
+
for (const p of points)
|
|
509
526
|
result.push(Matrix3d.xyPlusMatrixTimesXY(this._origin, this._matrix, p));
|
|
510
527
|
return result;
|
|
511
528
|
}
|
|
512
529
|
/**
|
|
513
|
-
*
|
|
514
|
-
* * If result is given, resize to match
|
|
515
|
-
* * If result is not given, return a new array.
|
|
530
|
+
* Transform the input 3d point array (using `Tp = M*p + o`).
|
|
531
|
+
* * If `result` is given, resize it to match the input `points` array and update it with transformed points.
|
|
532
|
+
* * If `result` is not given, return a new array.
|
|
516
533
|
*/
|
|
517
|
-
multiplyPoint3dArray(
|
|
534
|
+
multiplyPoint3dArray(points, result) {
|
|
518
535
|
if (result) {
|
|
519
|
-
const n = Transform.matchArrayLengths(
|
|
536
|
+
const n = Transform.matchArrayLengths(points, result, Point3d.createZero);
|
|
520
537
|
for (let i = 0; i < n; i++)
|
|
521
|
-
Matrix3d.xyzPlusMatrixTimesXYZ(this._origin, this._matrix,
|
|
538
|
+
Matrix3d.xyzPlusMatrixTimesXYZ(this._origin, this._matrix, points[i], result[i]);
|
|
522
539
|
return result;
|
|
523
540
|
}
|
|
524
541
|
result = [];
|
|
525
|
-
for (const p of
|
|
542
|
+
for (const p of points)
|
|
526
543
|
result.push(Matrix3d.xyzPlusMatrixTimesXYZ(this._origin, this._matrix, p));
|
|
527
544
|
return result;
|
|
528
545
|
}
|
|
529
546
|
/**
|
|
530
|
-
* Multiply the vector by the
|
|
531
|
-
* * The
|
|
532
|
-
* *
|
|
547
|
+
* Multiply the vector by the `matrix` part of the Transform.
|
|
548
|
+
* * The `origin` part of Transform is not used.
|
|
549
|
+
* * If `result` is given, update it with the multiplication. Otherwise, create a new Vector3d.
|
|
533
550
|
*/
|
|
534
551
|
multiplyVector(vector, result) {
|
|
535
552
|
return this._matrix.multiplyVector(vector, result);
|
|
536
553
|
}
|
|
537
554
|
/**
|
|
538
|
-
* Multiply the vector
|
|
539
|
-
* * The
|
|
555
|
+
* Multiply the vector by the `matrix` part of the Transform in place.
|
|
556
|
+
* * The `origin` part of Transform is not used.
|
|
540
557
|
*/
|
|
541
558
|
multiplyVectorInPlace(vector) {
|
|
542
559
|
this._matrix.multiplyVectorInPlace(vector);
|
|
543
560
|
}
|
|
544
561
|
/**
|
|
545
|
-
* Multiply the vector (x,y,z) by the
|
|
546
|
-
* * The
|
|
547
|
-
* *
|
|
562
|
+
* Multiply the vector (x,y,z) by the `matrix` part of the Transform.
|
|
563
|
+
* * The `origin` part of Transform is not used.
|
|
564
|
+
* * If `result` is given, update it with the multiplication. Otherwise, create a new Vector3d.
|
|
548
565
|
*/
|
|
549
566
|
multiplyVectorXYZ(x, y, z, result) {
|
|
550
567
|
return this._matrix.multiplyXYZ(x, y, z, result);
|
|
551
568
|
}
|
|
552
|
-
/**
|
|
569
|
+
/**
|
|
570
|
+
* Calculate `transformA * transformB` and store it into the calling instance (`this`).
|
|
571
|
+
* * **Note:** If `transformA = [A a]` and `transformB = [B b]` then `transformA * transformB` is defined as
|
|
572
|
+
* `[A*B Ab+a]`. See `multiplyTransformTransform` doc for math details.
|
|
573
|
+
* @param transformA first operand
|
|
574
|
+
* @param transformB second operand
|
|
575
|
+
*/
|
|
576
|
+
setMultiplyTransformTransform(transformA, transformB) {
|
|
577
|
+
Matrix3d.xyzPlusMatrixTimesXYZ(transformA._origin, transformA._matrix, transformB._origin, this._origin);
|
|
578
|
+
transformA._matrix.multiplyMatrixMatrix(transformB._matrix, this._matrix);
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Multiply `this` Transform times `other` Transform.
|
|
582
|
+
* **Note:** If `this = [A a]` and `other = [B b]` then `this * other` is defined as [A*B Ab+a].
|
|
583
|
+
* That's because we create a 4x4 matrix for each Transform with the 3x3 `matrix` and `origin`
|
|
584
|
+
* as upper 3x4 part of a 4x4 matrix and 0001 as the final row. Then we multiply those two 4x4 matrixes:
|
|
553
585
|
* ```
|
|
554
586
|
* equation
|
|
555
587
|
* \begin{matrix}
|
|
556
|
-
* \text{`this`
|
|
557
|
-
* \text{`other`
|
|
588
|
+
* \text{`this` Transform with `matrix` part }\bold{A}\text{ and `origin` part }\bold{a} & \blockTransform{A}{a}\\
|
|
589
|
+
* \text{`other` Transform with `matrix` part }\bold{B}\text{ and `origin` part }\bold{b} & \blockTransform{B}{b} \\
|
|
558
590
|
* \text{product}& \blockTransform{A}{a}\blockTransform{B}{b}=\blockTransform{AB}{Ab + a}
|
|
559
591
|
* \end{matrix}
|
|
560
592
|
* ```
|
|
561
|
-
* @param other
|
|
593
|
+
* @param other the 'other` Transform to be multiplied to `this` Transform.
|
|
562
594
|
* @param result optional preallocated result to reuse.
|
|
563
595
|
*/
|
|
564
596
|
multiplyTransformTransform(other, result) {
|
|
@@ -568,30 +600,20 @@ export class Transform {
|
|
|
568
600
|
return result;
|
|
569
601
|
}
|
|
570
602
|
/**
|
|
571
|
-
* Multiply
|
|
572
|
-
*
|
|
573
|
-
*
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
if (Transform._scratchPoint === undefined)
|
|
577
|
-
Transform._scratchPoint = Point3d.create();
|
|
578
|
-
Matrix3d.xyzPlusMatrixTimesXYZ(transformA._origin, transformA._matrix, transformB._origin, Transform._scratchPoint);
|
|
579
|
-
this._origin.setFrom(Transform._scratchPoint);
|
|
580
|
-
transformA._matrix.multiplyMatrixMatrix(transformB._matrix, this._matrix);
|
|
581
|
-
}
|
|
582
|
-
// [Q A][R 0] = [QR A]
|
|
583
|
-
// [0 1][0 1] [0 1]
|
|
584
|
-
/**
|
|
585
|
-
* Multiply this Transform times other Matrix3d, with other considered to be a Transform with 0 translation.
|
|
603
|
+
* Multiply `this` Transform times `other` Matrix3d (considered to be a Transform with 0 `origin`).
|
|
604
|
+
* **Note:** If `this = [A a]`, then we promote `other` matrix to be a Transform [B 0].
|
|
605
|
+
* Then `this * other` is defined as [A*B a]. That's because we create a 4x4 matrix for each Transform
|
|
606
|
+
* with the 3x3 `matrix` and `origin` as upper 3x4 part of a 4x4 matrix and 0001 as the final row. Then we
|
|
607
|
+
* multiply those two 4x4 matrixes:
|
|
586
608
|
* ```
|
|
587
609
|
* equation
|
|
588
610
|
* \begin{matrix}
|
|
589
|
-
* \text{`this`
|
|
590
|
-
* \text{`other` matrix }\bold{B}\text{ promoted to block
|
|
611
|
+
* \text{`this` Transform with `matrix` part }\bold{A}\text{ and `origin` part }\bold{a} & \blockTransform{A}{a}\\
|
|
612
|
+
* \text{`other` matrix }\bold{B}\text{ promoted to block Transform} & \blockTransform{B}{0} \\
|
|
591
613
|
* \text{product}& \blockTransform{A}{a}\blockTransform{B}{0}=\blockTransform{AB}{a}
|
|
592
614
|
* \end{matrix}
|
|
593
615
|
* ```
|
|
594
|
-
* @param other
|
|
616
|
+
* @param other the `other` Matrix3d to be multiplied to `this` Transform.
|
|
595
617
|
* @param result optional preallocated result to reuse.
|
|
596
618
|
*/
|
|
597
619
|
multiplyTransformMatrix3d(other, result) {
|
|
@@ -602,15 +624,17 @@ export class Transform {
|
|
|
602
624
|
return result;
|
|
603
625
|
}
|
|
604
626
|
/**
|
|
605
|
-
* Return the
|
|
627
|
+
* Return the Range of the transformed corners.
|
|
606
628
|
* * The 8 corners are transformed individually.
|
|
607
|
-
* * Note
|
|
608
|
-
*
|
|
629
|
+
* * **Note:** Suppose you have a geometry, a range box around that geometry, and your Transform is a rotation.
|
|
630
|
+
* If you rotate the range box and recompute a new range box around the rotated range box, then the new range
|
|
631
|
+
* box will have a larger volume than the original range box. However, if you rotate the geometry itself and
|
|
632
|
+
* then recompute the range box, it will be a tighter range box around the rotated geometry. `multiplyRange`
|
|
633
|
+
* function creates the larger range box because it only has access to the range box and the geometry itself.
|
|
609
634
|
*/
|
|
610
635
|
multiplyRange(range, result) {
|
|
611
636
|
if (range.isNull)
|
|
612
637
|
return range.clone(result);
|
|
613
|
-
// snag current values to allow aliasing.
|
|
614
638
|
const lowX = range.low.x;
|
|
615
639
|
const lowY = range.low.y;
|
|
616
640
|
const lowZ = range.low.z;
|
|
@@ -629,9 +653,9 @@ export class Transform {
|
|
|
629
653
|
return result;
|
|
630
654
|
}
|
|
631
655
|
/**
|
|
632
|
-
*
|
|
633
|
-
*
|
|
634
|
-
*
|
|
656
|
+
* Return a Transform which is the inverse of `this` Transform.
|
|
657
|
+
* * If `transform = [M o]` then `transformInverse = [MInverse MInverse*-o]`
|
|
658
|
+
* * Return `undefined` if this Transform's matrix is singular.
|
|
635
659
|
*/
|
|
636
660
|
inverse(result) {
|
|
637
661
|
const matrixInverse = this._matrix.inverse(result ? result._matrix : undefined);
|
|
@@ -645,15 +669,15 @@ export class Transform {
|
|
|
645
669
|
return Transform.createRefs(matrixInverse.multiplyXYZ(-this._origin.x, -this._origin.y, -this._origin.z), matrixInverse);
|
|
646
670
|
}
|
|
647
671
|
/**
|
|
648
|
-
* Initialize
|
|
649
|
-
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
653
|
-
*
|
|
654
|
-
* @param
|
|
655
|
-
*
|
|
656
|
-
*
|
|
672
|
+
* Initialize 2 Transforms: First Transform maps a box (axis aligned) specified by `min` and `max` to
|
|
673
|
+
* the unit box specified by 000 and 111 and inverse of it. Second Transform is the reverse of first.
|
|
674
|
+
* @param min the min corner of the box
|
|
675
|
+
* @param max the max corner of the box
|
|
676
|
+
* @param npcToGlobal maps global (the unit box specified by 000 and 111) to NPC (a box specified by `min`
|
|
677
|
+
* and `max`). Object created by caller, re-initialized here.
|
|
678
|
+
* @param globalToNpc maps NPC (a box specified by `min` and `max`) to global (the unit box specified by
|
|
679
|
+
* 000 and 111). Object created by caller, re-initialized here.
|
|
680
|
+
* * NPC stands for `Normalized Projection Coordinate`
|
|
657
681
|
*/
|
|
658
682
|
static initFromRange(min, max, npcToGlobal, globalToNpc) {
|
|
659
683
|
const diag = max.minus(min);
|
|
@@ -664,10 +688,26 @@ export class Transform {
|
|
|
664
688
|
if (diag.z === 0.0)
|
|
665
689
|
diag.z = 1.0;
|
|
666
690
|
const rMatrix = new Matrix3d();
|
|
691
|
+
/**
|
|
692
|
+
* [diag.x 0 0 min.x]
|
|
693
|
+
* npcToGlobal = [ 0 diag.y 0 min.y]
|
|
694
|
+
* [ 0 0 diag.y min.z]
|
|
695
|
+
*
|
|
696
|
+
* npcToGlobal * 0 = min
|
|
697
|
+
* npcToGlobal * 1 = diag + min = max
|
|
698
|
+
*/
|
|
667
699
|
if (npcToGlobal) {
|
|
668
700
|
Matrix3d.createScale(diag.x, diag.y, diag.z, rMatrix);
|
|
669
701
|
Transform.createOriginAndMatrix(min, rMatrix, npcToGlobal);
|
|
670
702
|
}
|
|
703
|
+
/**
|
|
704
|
+
* [1/diag.x 0 0 -min.x/diag.x]
|
|
705
|
+
* globalToNpc = [ 0 1/diag.y 0 -min.y/diag.y]
|
|
706
|
+
* [ 0 0 1/diag.y -min.z/diag.z]
|
|
707
|
+
*
|
|
708
|
+
* globalToNpc * min = min/diag - min/diag = 0
|
|
709
|
+
* globalToNpc * max = max/diag - min/diag = diag/diag = 1
|
|
710
|
+
*/
|
|
671
711
|
if (globalToNpc) {
|
|
672
712
|
const origin = new Point3d(-min.x / diag.x, -min.y / diag.y, -min.z / diag.z);
|
|
673
713
|
Matrix3d.createScale(1.0 / diag.x, 1.0 / diag.y, 1.0 / diag.z, rMatrix);
|