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