@itwin/core-geometry 4.0.0-dev.10 → 4.0.0-dev.11

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 (34) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/lib/cjs/geometry3d/Angle.d.ts +1 -0
  3. package/lib/cjs/geometry3d/Angle.d.ts.map +1 -1
  4. package/lib/cjs/geometry3d/Angle.js +1 -0
  5. package/lib/cjs/geometry3d/Angle.js.map +1 -1
  6. package/lib/cjs/geometry3d/AngleSweep.d.ts +1 -0
  7. package/lib/cjs/geometry3d/AngleSweep.d.ts.map +1 -1
  8. package/lib/cjs/geometry3d/AngleSweep.js +1 -0
  9. package/lib/cjs/geometry3d/AngleSweep.js.map +1 -1
  10. package/lib/cjs/geometry3d/Matrix3d.d.ts +161 -96
  11. package/lib/cjs/geometry3d/Matrix3d.d.ts.map +1 -1
  12. package/lib/cjs/geometry3d/Matrix3d.js +245 -206
  13. package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
  14. package/lib/cjs/geometry3d/Point3dVector3d.d.ts +3 -0
  15. package/lib/cjs/geometry3d/Point3dVector3d.d.ts.map +1 -1
  16. package/lib/cjs/geometry3d/Point3dVector3d.js +3 -0
  17. package/lib/cjs/geometry3d/Point3dVector3d.js.map +1 -1
  18. package/lib/esm/geometry3d/Angle.d.ts +1 -0
  19. package/lib/esm/geometry3d/Angle.d.ts.map +1 -1
  20. package/lib/esm/geometry3d/Angle.js +1 -0
  21. package/lib/esm/geometry3d/Angle.js.map +1 -1
  22. package/lib/esm/geometry3d/AngleSweep.d.ts +1 -0
  23. package/lib/esm/geometry3d/AngleSweep.d.ts.map +1 -1
  24. package/lib/esm/geometry3d/AngleSweep.js +1 -0
  25. package/lib/esm/geometry3d/AngleSweep.js.map +1 -1
  26. package/lib/esm/geometry3d/Matrix3d.d.ts +161 -96
  27. package/lib/esm/geometry3d/Matrix3d.d.ts.map +1 -1
  28. package/lib/esm/geometry3d/Matrix3d.js +245 -206
  29. package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
  30. package/lib/esm/geometry3d/Point3dVector3d.d.ts +3 -0
  31. package/lib/esm/geometry3d/Point3dVector3d.d.ts.map +1 -1
  32. package/lib/esm/geometry3d/Point3dVector3d.js +3 -0
  33. package/lib/esm/geometry3d/Point3dVector3d.js.map +1 -1
  34. package/package.json +4 -4
@@ -15,7 +15,7 @@ const Point2dVector2d_1 = require("./Point2dVector2d");
15
15
  const Point3dVector3d_1 = require("./Point3dVector3d");
16
16
  const Transform_1 = require("./Transform");
17
17
  /* eslint-disable @itwin/prefer-get */
18
- // cSpell:words XXYZ YXYZ ZXYZ
18
+ // cSpell:words XXYZ YXYZ ZXYZ SaeedTorabi
19
19
  /**
20
20
  * PackedMatrix3dOps contains static methods for matrix operations where the matrix is a Float64Array.
21
21
  * * The Float64Array contains the matrix entries in row-major order
@@ -426,9 +426,20 @@ class Matrix3d {
426
426
  return result;
427
427
  }
428
428
  /**
429
- * Copy the transpose of the coffs to the inverseCoffs.
430
- * * Mark the matrix as inverseStored.
431
- */
429
+ * Create the inverseCoffs member (filled with zeros)
430
+ * This is for use by matrix * matrix multiplications which need to be sure the member is there to be
431
+ * filled with method-specific content.
432
+ */
433
+ createInverseCoffsWithZeros() {
434
+ if (!this.inverseCoffs) {
435
+ this.inverseState = InverseMatrixState.unknown;
436
+ this.inverseCoffs = new Float64Array(9);
437
+ }
438
+ }
439
+ /**
440
+ * Copy the transpose of the coffs to the inverseCoffs.
441
+ * * Mark the matrix as inverseStored.
442
+ */
432
443
  setupInverseTranspose() {
433
444
  const coffs = this.coffs;
434
445
  this.inverseState = InverseMatrixState.inverseStored;
@@ -647,6 +658,7 @@ class Matrix3d {
647
658
  * Construct a rigid matrix (orthogonal matrix with +1 determinant) using vectorA and its 2 perpendicular.
648
659
  * * If axisOrder is not passed then `AxisOrder = AxisOrder.ZXY` is used as default.
649
660
  * * This function internally uses createPerpendicularVectorFavorXYPlane and createRigidFromColumns.
661
+ * * Visualization can be found at https://www.itwinjs.org/sandbox/SaeedTorabi/2PerpendicularVectorsTo1Vector
650
662
  */
651
663
  static createRigidHeadsUp(vectorA, axisOrder = Geometry_1.AxisOrder.ZXY, result) {
652
664
  const vectorB = Matrix3d.createPerpendicularVectorFavorXYPlane(vectorA);
@@ -696,7 +708,7 @@ class Matrix3d {
696
708
  /**
697
709
  * Replace current rows Ui and Uj with (c*Ui + s*Uj) and (c*Uj - s*Ui).
698
710
  * * There is no checking for i,j being 0,1,2.
699
- * @param i first row index. **must be 0,1,2** (unchecked)
711
+ * @param i first row index. **must be 0,1,2** (unchecked)
700
712
  * @param j second row index. **must be 0,1,2** (unchecked)
701
713
  * @param c fist coefficient
702
714
  * @param s second coefficient
@@ -1396,6 +1408,7 @@ class Matrix3d {
1396
1408
  * \text{The matrix is } I + (s-1) D D^T
1397
1409
  * \\ \text{with }D\text{ being the normalized direction vector and }s\text{ being the scale.}
1398
1410
  * ```
1411
+ * * Visualization can be found at itwinjs.org/sandbox/SaeedTorabi/DirectionalScale
1399
1412
  */
1400
1413
  static createDirectionalScale(direction, scale, result) {
1401
1414
  const unit = direction.normalize();
@@ -1529,7 +1542,7 @@ class Matrix3d {
1529
1542
  return result;
1530
1543
  }
1531
1544
  /**
1532
- * Multiply transpose of this matrix times a vector.
1545
+ * Multiply the transpose matrix times a vector.
1533
1546
  * * This produces the same x,y,z as treating the vector as a row on the left of the (un-transposed) matrix.
1534
1547
  * ```
1535
1548
  * equation
@@ -1538,7 +1551,7 @@ class Matrix3d {
1538
1551
  * \text{Treating U as a row to the left of untransposed matrix\: return row}&\rowSubXYZ{V}&=&\rowSubXYZ{U}\matrixXY{A}
1539
1552
  * \end{matrix}
1540
1553
  * ```
1541
- * @return the vector result
1554
+ * @return the vector result (optional)
1542
1555
  */
1543
1556
  multiplyTransposeVector(vector, result) {
1544
1557
  result = result ? result : new Point3dVector3d_1.Vector3d();
@@ -1550,87 +1563,100 @@ class Matrix3d {
1550
1563
  result.z = this.coffs[2] * x + this.coffs[5] * y + this.coffs[8] * z;
1551
1564
  return result;
1552
1565
  }
1553
- /** Multiply the matrix * (x,y,z), i.e. the vector (x,y,z) is a column vector on the right.
1554
- * @return the vector result
1566
+ /**
1567
+ * Multiply the matrix * [x,y,z], i.e. the vector [x,y,z] is a column vector on the right.
1568
+ * @return the vector result (optional)
1555
1569
  */
1556
1570
  multiplyXYZ(x, y, z, result) {
1557
1571
  result = result ? result : new Point3dVector3d_1.Vector3d();
1558
- result.x = (this.coffs[0] * x + this.coffs[1] * y + this.coffs[2] * z);
1559
- result.y = (this.coffs[3] * x + this.coffs[4] * y + this.coffs[5] * z);
1560
- result.z = (this.coffs[6] * x + this.coffs[7] * y + this.coffs[8] * z);
1572
+ result.x = this.coffs[0] * x + this.coffs[1] * y + this.coffs[2] * z;
1573
+ result.y = this.coffs[3] * x + this.coffs[4] * y + this.coffs[5] * z;
1574
+ result.z = this.coffs[6] * x + this.coffs[7] * y + this.coffs[8] * z;
1561
1575
  return result;
1562
1576
  }
1563
- /** Multiply the matrix * xyz, place result in (required) return value.
1564
- * @param xyz right side
1565
- * @param result result.
1577
+ /**
1578
+ * Multiply the matrix * xyz, place result in (required) return value.
1579
+ * @param xyz right side
1580
+ * @param result the result.
1566
1581
  */
1567
1582
  multiplyXYZtoXYZ(xyz, result) {
1568
1583
  const x = xyz.x;
1569
1584
  const y = xyz.y;
1570
1585
  const z = xyz.z;
1571
- result.x = (this.coffs[0] * x + this.coffs[1] * y + this.coffs[2] * z);
1572
- result.y = (this.coffs[3] * x + this.coffs[4] * y + this.coffs[5] * z);
1573
- result.z = (this.coffs[6] * x + this.coffs[7] * y + this.coffs[8] * z);
1586
+ result.x = this.coffs[0] * x + this.coffs[1] * y + this.coffs[2] * z;
1587
+ result.y = this.coffs[3] * x + this.coffs[4] * y + this.coffs[5] * z;
1588
+ result.z = this.coffs[6] * x + this.coffs[7] * y + this.coffs[8] * z;
1574
1589
  return result;
1575
1590
  }
1576
- /** Multiply the matrix * (x,y,0), i.e. the vector (x,y,z) is a column vector on the right.
1577
- * @return the vector result
1591
+ /**
1592
+ * Multiply the matrix * [x,y,0], i.e. the vector [x,y,0] is a column vector on the right.
1593
+ * @return the vector result (optional)
1578
1594
  */
1579
1595
  multiplyXY(x, y, result) {
1580
1596
  result = result ? result : new Point3dVector3d_1.Vector3d();
1581
- result.x = (this.coffs[0] * x + this.coffs[1] * y);
1582
- result.y = (this.coffs[3] * x + this.coffs[4] * y);
1583
- result.z = (this.coffs[6] * x + this.coffs[7] * y);
1597
+ result.x = this.coffs[0] * x + this.coffs[1] * y;
1598
+ result.y = this.coffs[3] * x + this.coffs[4] * y;
1599
+ result.z = this.coffs[6] * x + this.coffs[7] * y;
1584
1600
  return result;
1585
1601
  }
1586
- /** compute `origin + this*[x,y,0]` */
1602
+ /**
1603
+ * Compute origin + the matrix * [x,y,0].
1604
+ * @return the vector result (optional)
1605
+ */
1587
1606
  originPlusMatrixTimesXY(origin, x, y, result) {
1588
1607
  return Point3dVector3d_1.Point3d.create(origin.x + this.coffs[0] * x + this.coffs[1] * y, origin.y + this.coffs[3] * x + this.coffs[4] * y, origin.z + this.coffs[6] * x + this.coffs[7] * y, result);
1589
1608
  }
1590
- /** Multiply matrix * (x, y, z) using any 3d object given containing those members */
1609
+ /**
1610
+ * Multiply the matrix * (x,y,z) in place, i.e. the vector (x,y,z) is a column vector on the right and
1611
+ * the multiplication updates the vector values.
1612
+ * @param xyzData the vector data
1613
+ */
1591
1614
  multiplyVectorInPlace(xyzData) {
1592
1615
  const x = xyzData.x;
1593
1616
  const y = xyzData.y;
1594
1617
  const z = xyzData.z;
1595
- const coffs = this.coffs;
1596
- xyzData.x = (coffs[0] * x + coffs[1] * y + coffs[2] * z);
1597
- xyzData.y = (coffs[3] * x + coffs[4] * y + coffs[5] * z);
1598
- xyzData.z = (coffs[6] * x + coffs[7] * y + coffs[8] * z);
1618
+ xyzData.x = this.coffs[0] * x + this.coffs[1] * y + this.coffs[2] * z;
1619
+ xyzData.y = this.coffs[3] * x + this.coffs[4] * y + this.coffs[5] * z;
1620
+ xyzData.z = this.coffs[6] * x + this.coffs[7] * y + this.coffs[8] * z;
1599
1621
  }
1600
- /** Multiply the transpose matrix times column using any 3d object with x,y,z members.
1601
- * This is equivalent to `multiplyTransposeVector` but always returns the result directly in the input.
1622
+ /**
1623
+ * Multiply the transpose matrix times [x,y,z] in place, i.e. the vector [x,y,z] is a column vector on
1624
+ * the right and the multiplication updates the vector values.
1625
+ * * This is equivalent to `multiplyTransposeVector` but always returns the result directly in the input.
1626
+ * @param xyzData the vector data
1602
1627
  */
1603
1628
  multiplyTransposeVectorInPlace(vectorU) {
1604
1629
  const x = vectorU.x;
1605
1630
  const y = vectorU.y;
1606
1631
  const z = vectorU.z;
1607
- const coffs = this.coffs;
1608
- vectorU.x = (coffs[0] * x + coffs[3] * y + coffs[6] * z);
1609
- vectorU.y = (coffs[1] * x + coffs[4] * y + coffs[7] * z);
1610
- vectorU.z = (coffs[2] * x + coffs[5] * y + coffs[8] * z);
1632
+ vectorU.x = this.coffs[0] * x + this.coffs[3] * y + this.coffs[6] * z;
1633
+ vectorU.y = this.coffs[1] * x + this.coffs[4] * y + this.coffs[7] * z;
1634
+ vectorU.z = this.coffs[2] * x + this.coffs[5] * y + this.coffs[8] * z;
1611
1635
  }
1612
- /** Multiply the transpose matrix times column using individual numeric inputs.
1613
- * * This is equivalent to multiplying with the vector as a row to the left of the plain matrix.
1636
+ /**
1637
+ * Multiply the transpose matrix times column using individual numeric inputs.
1638
+ * * This produces the same x,y,z as treating the vector as a row on the left of the (un-transposed) matrix.
1614
1639
  * ```
1615
1640
  * equation
1616
1641
  * \begin{matrix}
1617
- * \text{treating the input as a column } \columnXYZ{x}{y}{z}\text{ compute }&\columnSubXYZ{V} &= &A^T \columnXYZ{x}{y}{z} \\
1618
- * \text{or row vector } \rowXYZ{x}{y}{z} \text{ compute }&\rowSubXYZ{V} &= &\rowXYZ{x}{y}{z} A \\
1642
+ * \text{treating the input as a column vector } \columnXYZ{x}{y}{z}\text{ compute }&\columnSubXYZ{V} &= &A^T \columnXYZ{x}{y}{z} \\
1643
+ * \text{or as a row vector } \rowXYZ{x}{y}{z} \text{ compute }&\rowSubXYZ{V} &= &\rowXYZ{x}{y}{z} A \\
1619
1644
  * \phantom{8888}\text{and return V as a Vector3d} & & &
1620
1645
  * \end{matrix}
1621
1646
  * ````
1622
- * @return the vector result
1647
+ * @return the vector result (optional)
1623
1648
  */
1624
1649
  multiplyTransposeXYZ(x, y, z, result) {
1625
1650
  result = result ? result : new Point3dVector3d_1.Vector3d();
1626
- result.x = (this.coffs[0] * x + this.coffs[3] * y + this.coffs[6] * z);
1627
- result.y = (this.coffs[1] * x + this.coffs[4] * y + this.coffs[7] * z);
1628
- result.z = (this.coffs[2] * x + this.coffs[5] * y + this.coffs[8] * z);
1651
+ result.x = this.coffs[0] * x + this.coffs[3] * y + this.coffs[6] * z;
1652
+ result.y = this.coffs[1] * x + this.coffs[4] * y + this.coffs[7] * z;
1653
+ result.z = this.coffs[2] * x + this.coffs[5] * y + this.coffs[8] * z;
1629
1654
  return result;
1630
1655
  }
1631
- /** Solve `matrix * result = vector`.
1632
- * * This is equivalent to multiplication `result = matrixInverse * vector`.
1633
- * * Result is undefined if the matrix is singular (e.g. has parallel or zero length columns)
1656
+ /**
1657
+ * Solve `matrix * result = vector` for an unknown `result`.
1658
+ * * This is equivalent to multiplication `result = inverse matrix * vector`.
1659
+ * * Result is undefined if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
1634
1660
  */
1635
1661
  multiplyInverse(vector, result) {
1636
1662
  this.computeCachedInverse(true);
@@ -1638,13 +1664,14 @@ class Matrix3d {
1638
1664
  const x = vector.x;
1639
1665
  const y = vector.y;
1640
1666
  const z = vector.z;
1641
- return Point3dVector3d_1.Vector3d.create((this.inverseCoffs[0] * x + this.inverseCoffs[1] * y + this.inverseCoffs[2] * z), (this.inverseCoffs[3] * x + this.inverseCoffs[4] * y + this.inverseCoffs[5] * z), (this.inverseCoffs[6] * x + this.inverseCoffs[7] * y + this.inverseCoffs[8] * z), result);
1667
+ return Point3dVector3d_1.Vector3d.create(this.inverseCoffs[0] * x + this.inverseCoffs[1] * y + this.inverseCoffs[2] * z, this.inverseCoffs[3] * x + this.inverseCoffs[4] * y + this.inverseCoffs[5] * z, this.inverseCoffs[6] * x + this.inverseCoffs[7] * y + this.inverseCoffs[8] * z, result);
1642
1668
  }
1643
1669
  return undefined;
1644
1670
  }
1645
- /** Solve `matrixTranspose * result = vector`.
1671
+ /**
1672
+ * Solve `matrixTranspose * result = vector` for an unknown `result`.
1646
1673
  * * This is equivalent to multiplication `result = matrixInverseTranspose * vector`.
1647
- * * Result is undefined if the matrix is singular (e.g. has parallel or zero length columns)
1674
+ * * Result is undefined if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
1648
1675
  */
1649
1676
  multiplyInverseTranspose(vector, result) {
1650
1677
  this.computeCachedInverse(true);
@@ -1652,87 +1679,91 @@ class Matrix3d {
1652
1679
  const x = vector.x;
1653
1680
  const y = vector.y;
1654
1681
  const z = vector.z;
1655
- return Point3dVector3d_1.Vector3d.create((this.inverseCoffs[0] * x + this.inverseCoffs[3] * y + this.inverseCoffs[6] * z), (this.inverseCoffs[1] * x + this.inverseCoffs[4] * y + this.inverseCoffs[7] * z), (this.inverseCoffs[2] * x + this.inverseCoffs[5] * y + this.inverseCoffs[8] * z), result);
1682
+ return Point3dVector3d_1.Vector3d.create(this.inverseCoffs[0] * x + this.inverseCoffs[3] * y + this.inverseCoffs[6] * z, this.inverseCoffs[1] * x + this.inverseCoffs[4] * y + this.inverseCoffs[7] * z, this.inverseCoffs[2] * x + this.inverseCoffs[5] * y + this.inverseCoffs[8] * z, result);
1656
1683
  }
1657
1684
  return undefined;
1658
1685
  }
1659
1686
  /**
1660
- * multiply `matrixInverse * [x,y,z]`.
1661
- * * This is equivalent to solving `matrix * result = [x,y,z]`
1662
- * * return as a Vector3d, or undefined if the matrix is singular.
1687
+ * Multiply `matrixInverse * [x,y,z]`.
1688
+ * * This is equivalent to solving `matrix * result = [x,y,z]` for an unknown `result`.
1689
+ * * Result is undefined if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
1690
+ * @return result as a Vector3d or undefined (if the matrix is singular).
1663
1691
  */
1664
1692
  multiplyInverseXYZAsVector3d(x, y, z, result) {
1665
1693
  this.computeCachedInverse(true);
1666
1694
  if (this.inverseCoffs) {
1667
- return Point3dVector3d_1.Vector3d.create((this.inverseCoffs[0] * x + this.inverseCoffs[1] * y + this.inverseCoffs[2] * z), (this.inverseCoffs[3] * x + this.inverseCoffs[4] * y + this.inverseCoffs[5] * z), (this.inverseCoffs[6] * x + this.inverseCoffs[7] * y + this.inverseCoffs[8] * z), result);
1695
+ return Point3dVector3d_1.Vector3d.create(this.inverseCoffs[0] * x + this.inverseCoffs[1] * y + this.inverseCoffs[2] * z, this.inverseCoffs[3] * x + this.inverseCoffs[4] * y + this.inverseCoffs[5] * z, this.inverseCoffs[6] * x + this.inverseCoffs[7] * y + this.inverseCoffs[8] * z, result);
1668
1696
  }
1669
1697
  return undefined;
1670
1698
  }
1671
1699
  /**
1672
- * multiply `matrixInverse * [x,y,z]` and return packaged as `Point4d` with given weight.
1673
- * * Equivalent to solving matrix * result = [x,y,z]
1674
- * * return as a Point4d with the same weight.
1675
- * * Called by Transform with x,y,z adjusted by subtraction ((xw) - w * origin.x, etc) where xw is the pre-weighted space point.
1700
+ * Multiply `matrixInverse * [x,y,z]` and return result as `Point4d` with given weight.
1701
+ * * Equivalent to solving `matrix * result = [x,y,z]` for an unknown `result`.
1702
+ * * Result is undefined if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
1703
+ * @return result as a Point4d with the same weight.
1676
1704
  */
1677
1705
  multiplyInverseXYZW(x, y, z, w, result) {
1678
1706
  this.computeCachedInverse(true);
1679
1707
  if (this.inverseCoffs) {
1680
- return Point4d_1.Point4d.create((this.inverseCoffs[0] * x + this.inverseCoffs[1] * y + this.inverseCoffs[2] * z), (this.inverseCoffs[3] * x + this.inverseCoffs[4] * y + this.inverseCoffs[5] * z), (this.inverseCoffs[6] * x + this.inverseCoffs[7] * y + this.inverseCoffs[8] * z), w, result);
1708
+ return Point4d_1.Point4d.create(this.inverseCoffs[0] * x + this.inverseCoffs[1] * y + this.inverseCoffs[2] * z, this.inverseCoffs[3] * x + this.inverseCoffs[4] * y + this.inverseCoffs[5] * z, this.inverseCoffs[6] * x + this.inverseCoffs[7] * y + this.inverseCoffs[8] * z, w, result);
1681
1709
  }
1682
1710
  return undefined;
1683
1711
  }
1684
1712
  /**
1685
- * multiply `matrixInverse * [x,y,z]` and return packaged as `Point3d`.
1686
- * * multiply matrixInverse * [x,y,z]
1687
- * * Equivalent to solving matrix * result = [x,y,z]
1688
- * * return as a Point3d.
1713
+ * Multiply `matrixInverse * [x,y,z]` and return result as `Point3d`.
1714
+ * * Equivalent to solving `matrix * result = [x,y,z]` for an unknown `result`.
1715
+ * @return result as a Point3d or undefined (if the matrix is singular).
1689
1716
  */
1690
1717
  multiplyInverseXYZAsPoint3d(x, y, z, result) {
1691
1718
  this.computeCachedInverse(true);
1692
1719
  if (this.inverseCoffs) {
1693
- return Point3dVector3d_1.Point3d.create((this.inverseCoffs[0] * x + this.inverseCoffs[1] * y + this.inverseCoffs[2] * z), (this.inverseCoffs[3] * x + this.inverseCoffs[4] * y + this.inverseCoffs[5] * z), (this.inverseCoffs[6] * x + this.inverseCoffs[7] * y + this.inverseCoffs[8] * z), result);
1720
+ return Point3dVector3d_1.Point3d.create(this.inverseCoffs[0] * x + this.inverseCoffs[1] * y + this.inverseCoffs[2] * z, this.inverseCoffs[3] * x + this.inverseCoffs[4] * y + this.inverseCoffs[5] * z, this.inverseCoffs[6] * x + this.inverseCoffs[7] * y + this.inverseCoffs[8] * z, result);
1694
1721
  }
1695
1722
  return undefined;
1696
1723
  }
1697
1724
  /**
1698
- * * invoke a given matrix-matrix operation (product function) to compute this.inverseCOffs
1699
- * * set this.inverseCoffs
1700
- * * if either input cffA or coffB is undefined, set state to `InverseMatrixState.unknown` (but leave the inverseCoffs untouched)
1725
+ * Invoke a given matrix*matrix operation to compute the inverse matrix and set this.inverseCoffs
1726
+ * * If either input coffA or coffB is undefined, set state to `InverseMatrixState.unknown` but
1727
+ * leave the inverseCoffs untouched.
1728
+ * @param f the given matrix*matrix operation that is called by this function to compute the inverse.
1729
+ * `f` must be a matrix*matrix operation. Otherwise, the function does not generate the inverse properly.
1701
1730
  */
1702
1731
  finishInverseCoffs(f, coffA, coffB) {
1703
1732
  if (coffA && coffB) {
1704
1733
  this.createInverseCoffsWithZeros();
1705
1734
  this.inverseState = InverseMatrixState.inverseStored;
1706
- f(coffA, coffB, this.inverseCoffs);
1735
+ f(coffA, coffB, this.inverseCoffs); // call function f (which is provided by user) to compute the inverse.
1707
1736
  }
1708
1737
  else {
1709
1738
  this.inverseState = InverseMatrixState.unknown;
1710
1739
  }
1711
1740
  }
1712
- /*
1713
- Notes on inverses of products
1714
- * 1) M = A * B MInverse = BInverse * AInverse
1715
- * 2) M = A * BInverse MInverse = B * AInverse
1716
- * 3) M = AInverse * B MInverse = BInverse * A
1717
- * 4) M = ATranspose * B MInverse = BInverse * AInverseTranspose
1718
- * 5) M = A * BTranspose MInverse = BInverseTranspose * AInverse
1719
- */
1720
- /** Multiply the instance matrix A by the input matrix B.
1721
- * @return the matrix product A * B
1741
+ // Notes on inverse of matrix products:
1742
+ // 1) M = A * B ===> MInverse = BInverse * AInverse
1743
+ // 2) M = A * BInverse ===> MInverse = B * AInverse
1744
+ // 3) M = AInverse * B ===> MInverse = BInverse * A
1745
+ // 4) M = A * BTranspose ===> MInverse = BInverseTranspose * AInverse
1746
+ // 5) M = ATranspose * B ===> MInverse = BInverse * AInverseTranspose
1747
+ /**
1748
+ * Multiply `this` matrix times `other` matrix
1749
+ * @return the matrix result: this*other
1722
1750
  */
1723
1751
  multiplyMatrixMatrix(other, result) {
1724
1752
  result = result ? result : new Matrix3d();
1725
1753
  PackedMatrix3dOps.multiplyMatrixMatrix(this.coffs, other.coffs, result.coffs);
1726
- if (this.inverseState === InverseMatrixState.inverseStored && other.inverseState === InverseMatrixState.inverseStored)
1754
+ if (this.inverseState === InverseMatrixState.inverseStored
1755
+ && other.inverseState === InverseMatrixState.inverseStored)
1727
1756
  result.finishInverseCoffs(PackedMatrix3dOps.multiplyMatrixMatrix, other.inverseCoffs, this.inverseCoffs);
1728
- else if (this.inverseState === InverseMatrixState.singular || other.inverseState === InverseMatrixState.singular)
1757
+ else if (this.inverseState === InverseMatrixState.singular
1758
+ || other.inverseState === InverseMatrixState.singular)
1729
1759
  result.inverseState = InverseMatrixState.singular;
1730
1760
  else
1731
1761
  result.inverseState = InverseMatrixState.unknown;
1732
1762
  return result;
1733
1763
  }
1734
- /** Multiply this matrix times inverse of other
1735
- * @return the matrix result
1764
+ /**
1765
+ * Multiply `this` matrix times `inverse of other` matrix
1766
+ * @return the matrix result: this*otherInverse
1736
1767
  */
1737
1768
  multiplyMatrixMatrixInverse(other, result) {
1738
1769
  if (!other.computeCachedInverse(true))
@@ -1746,8 +1777,9 @@ class Matrix3d {
1746
1777
  PackedMatrix3dOps.copy(Matrix3d._productBuffer, result.coffs);
1747
1778
  return result;
1748
1779
  }
1749
- /** Multiply this matrix times inverse of other
1750
- * @return the matrix result
1780
+ /**
1781
+ * Multiply `inverse of this` matrix times `other` matrix
1782
+ * @return the matrix result: thisInverse*other
1751
1783
  */
1752
1784
  multiplyMatrixInverseMatrix(other, result) {
1753
1785
  if (!this.computeCachedInverse(true))
@@ -1761,30 +1793,32 @@ class Matrix3d {
1761
1793
  PackedMatrix3dOps.copy(Matrix3d._productBuffer, result.coffs);
1762
1794
  return result;
1763
1795
  }
1764
- /** Multiply `this` matrix times the transpose of `matrixB`.
1796
+ /**
1797
+ * Multiply `this` matrix times the transpose of `other` matrix
1765
1798
  * ```
1766
1799
  * equation
1767
- * \text{for instance matrix }A\text{ and other matrix }B\text{ return matrix }C{\text where }\\\matrixXY{C}=\matrixXY{A}\matrixTransposeSubXY{B}
1800
+ * \text{for instance matrix }A\text{ and matrix }B\text{ return matrix }C{\text where }\\\matrixXY{C}=\matrixXY{A}\matrixTransposeSubXY{B}
1768
1801
  * ```
1769
- * @return the matrix result
1802
+ * @return the matrix result: this*otherTranspose
1770
1803
  */
1771
- multiplyMatrixMatrixTranspose(matrixB, result) {
1804
+ multiplyMatrixMatrixTranspose(other, result) {
1772
1805
  result = result ? result : new Matrix3d();
1773
- PackedMatrix3dOps.multiplyMatrixMatrixTranspose(this.coffs, matrixB.coffs, result.coffs);
1774
- if (this.inverseState === InverseMatrixState.inverseStored && matrixB.inverseState === InverseMatrixState.inverseStored)
1775
- result.finishInverseCoffs(PackedMatrix3dOps.multiplyMatrixTransposeMatrix, matrixB.inverseCoffs, this.inverseCoffs);
1776
- else if (this.inverseState === InverseMatrixState.singular || matrixB.inverseState === InverseMatrixState.singular)
1806
+ PackedMatrix3dOps.multiplyMatrixMatrixTranspose(this.coffs, other.coffs, result.coffs);
1807
+ if (this.inverseState === InverseMatrixState.inverseStored && other.inverseState === InverseMatrixState.inverseStored)
1808
+ result.finishInverseCoffs(PackedMatrix3dOps.multiplyMatrixTransposeMatrix, other.inverseCoffs, this.inverseCoffs);
1809
+ else if (this.inverseState === InverseMatrixState.singular || other.inverseState === InverseMatrixState.singular)
1777
1810
  result.inverseState = InverseMatrixState.singular;
1778
1811
  else
1779
1812
  result.inverseState = InverseMatrixState.unknown;
1780
1813
  return result;
1781
1814
  }
1782
- /** Matrix multiplication `thisTranspose * other`.
1815
+ /**
1816
+ * Multiply the transpose of `this` matrix times `other` matrix
1783
1817
  * ```
1784
1818
  * equation
1785
1819
  * \matrixXY{result}=\matrixXY{\text{this}}\matrixTransposeSubXY{\text{other}}
1786
1820
  * ```
1787
- * @return the matrix result
1821
+ * @return the matrix result: thisTranspose*other
1788
1822
  */
1789
1823
  multiplyMatrixTransposeMatrix(other, result) {
1790
1824
  result = result ? result : new Matrix3d();
@@ -1797,30 +1831,31 @@ class Matrix3d {
1797
1831
  result.inverseState = InverseMatrixState.unknown;
1798
1832
  return result;
1799
1833
  }
1800
- /** multiply this Matrix3d (considered as a transform with 0 translation) times other Transform.
1834
+ /**
1835
+ * Multiply `this` Matrix3d (considered as a Transform with 0 translation) times `other` Transform.
1801
1836
  * ```
1802
1837
  * equation
1803
1838
  * \begin{matrix}
1804
- * \text{This matrix }\bold{A}\text{ promoted to block transform} & \blockTransform{A}{0} \\
1805
- * \text{other transform with matrix part }\bold{B}\text{ and translation }\bold{b} & \blockTransform{B}{b}\\
1839
+ * \text{This matrix }\bold{A}\text{ promoted to block transform} & \blockTransform{A}{0} \\
1840
+ * \text{other transform with matrix part }\bold{B}\text{ and translation }\bold{b} & \blockTransform{B}{b}\\
1806
1841
  * \text{product}& \blockTransform{A}{0}\blockTransform{B}{b}=\blockTransform{AB}{Ab}
1807
1842
  * \end{matrix}
1808
1843
  * ```
1809
- * @param other right hand Matrix3d for multiplication.
1810
- * @param result optional preallocated result to reuse.
1844
+ * @param other Right hand Matrix3d for multiplication.
1845
+ * @param result the Transform result (optional)
1811
1846
  */
1812
1847
  multiplyMatrixTransform(other, result) {
1813
1848
  if (!result)
1814
1849
  return Transform_1.Transform.createRefs(this.multiplyXYZ(other.origin.x, other.origin.y, other.origin.z), this.multiplyMatrixMatrix(other.matrix));
1815
- // be sure to do the point multiplication first before aliasing changes the matrix ..
1850
+ // be sure to do the point multiplication first before aliasing changes the matrix
1816
1851
  this.multiplyXYZtoXYZ(other.origin, result.origin);
1817
1852
  this.multiplyMatrixMatrix(other.matrix, result.matrix);
1818
1853
  return result;
1819
1854
  }
1820
1855
  /**
1821
1856
  * Return the transpose of `this` matrix.
1822
- * If `result` is passed as argument, then the function copies the transpose of `this` into `result`
1823
- * `this` is not changed unless also passed as the result, i.e., this.transpose(this) transposes `this` in place
1857
+ * * If `result` is passed as argument, then the function copies the transpose of `this` into `result`.
1858
+ * * `this` is not changed unless also passed as the result, i.e., `this.transpose(this)` transposes `this` in place.
1824
1859
  */
1825
1860
  transpose(result) {
1826
1861
  if (!result)
@@ -1842,18 +1877,22 @@ class Matrix3d {
1842
1877
  transposeInPlace() {
1843
1878
  PackedMatrix3dOps.transposeInPlace(this.coffs);
1844
1879
  if (this.inverseCoffs)
1845
- PackedMatrix3dOps.transposeInPlace(this.inverseCoffs);
1880
+ PackedMatrix3dOps.transposeInPlace(this.inverseCoffs); // inverse of transpose is equal to transpose of inverse
1846
1881
  }
1847
- /** return the inverse matrix.
1848
- * The return is undefined if the matrix is singular (has columns that are coplanar or colinear)
1849
- * * Note that each Matrix3d object caches its own inverse, and has methods to multiply the inverse times matrices and vectors.
1850
- * * Hence explicitly constructing this new inverse object is rarely necessary.
1882
+ /**
1883
+ * Return the inverse matrix.
1884
+ * The return is undefined if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
1885
+ * * If `result == this`, then content of inverse of `this` matrix is copied into `this`. Otherwise, inverse
1886
+ * of `this` is stored in `result`.
1887
+ * * **Note:** Each Matrix3d object caches its own inverse (`this.inverseCoffs`) and has methods to multiply
1888
+ * the inverse times matrices and vectors (e.g., `multiplyMatrixInverseMatrix`, `multiplyMatrixMatrixInverse`,
1889
+ * `multiplyInverse`). Hence explicitly constructing this new inverse object is rarely necessary.
1851
1890
  */
1852
1891
  inverse(result) {
1853
1892
  if (!this.computeCachedInverse(true))
1854
1893
  return undefined;
1855
1894
  if (result === this) {
1856
- // swap the contents (preserve pointers .. caller better know what they are doing)
1895
+ // swap the contents of this.coffs and this.inverseCoffs
1857
1896
  PackedMatrix3dOps.copy(this.coffs, Matrix3d._productBuffer);
1858
1897
  PackedMatrix3dOps.copy(this.inverseCoffs, this.coffs);
1859
1898
  PackedMatrix3dOps.copy(Matrix3d._productBuffer, this.inverseCoffs);
@@ -1868,33 +1907,48 @@ class Matrix3d {
1868
1907
  result.inverseState = this.inverseState;
1869
1908
  return result;
1870
1909
  }
1871
- /* Alternate implementation of computedCachedInverse - more direct addressing of arrays.
1872
- This is indeed 10% faster than using static work areas. */
1873
- // take the cross product of two rows of source.
1874
- // store as a column of dest.
1910
+ /**
1911
+ * Take the dot product of a row (specified by `rowStartA`) of `coffA` and `columnStartB` of `coffB`.
1912
+ * * **Note:** We don't validate row/column numbers. Pass 0/3/6 for row 0/1/2 and pass 0/1/2 for column 0/1/2.
1913
+ */
1914
+ static rowColumnDot(coffA, rowStartA, coffB, columnStartB) {
1915
+ return coffA[rowStartA] * coffB[columnStartB] +
1916
+ coffA[rowStartA + 1] * coffB[columnStartB + 3] +
1917
+ coffA[rowStartA + 2] * coffB[columnStartB + 6];
1918
+ }
1919
+ /**
1920
+ * Take the cross product of 2 rows (specified by `rowStart0` and `rowStart1`) of `source` and store the result
1921
+ * in `columnStart` of `dest`.
1922
+ * * **Note:** We don't validate row/column numbers. Pass 0/3/6 for row 0/1/2 and pass 0/1/2 for column 0/1/2.
1923
+ */
1875
1924
  static indexedRowCrossProduct(source, rowStart0, rowStart1, dest, columnStart) {
1876
1925
  dest[columnStart] = source[rowStart0 + 1] * source[rowStart1 + 2] - source[rowStart0 + 2] * source[rowStart1 + 1];
1877
1926
  dest[columnStart + 3] = source[rowStart0 + 2] * source[rowStart1] - source[rowStart0] * source[rowStart1 + 2];
1878
1927
  dest[columnStart + 6] = source[rowStart0] * source[rowStart1 + 1] - source[rowStart0 + 1] * source[rowStart1];
1879
1928
  }
1880
- // take the cross product of two columns of source.
1881
- // store as third column in same Matrix3d.
1882
- // This is private because the columnStart values are unchecked raw indices into the coffs
1929
+ /**
1930
+ * Take the cross product of 2 columns (i.e., `colStart0` and `colStart1`) of `this` matrix and store the
1931
+ * result in `colStart2` of the same matrix.
1932
+ * * **Note:** We don't validate column numbers. Pass 0/1/2 for column 0/1/2.
1933
+ */
1883
1934
  indexedColumnCrossProductInPlace(colStart0, colStart1, colStart2) {
1884
1935
  const coffs = this.coffs;
1885
1936
  coffs[colStart2] = coffs[colStart0 + 3] * coffs[colStart1 + 6] - coffs[colStart0 + 6] * coffs[colStart1 + 3];
1886
1937
  coffs[colStart2 + 3] = coffs[colStart0 + 6] * coffs[colStart1] - coffs[colStart0] * coffs[colStart1 + 6];
1887
1938
  coffs[colStart2 + 6] = coffs[colStart0] * coffs[colStart1 + 3] - coffs[colStart0 + 3] * coffs[colStart1];
1888
1939
  }
1889
- /** Form cross products among columns in axisOrder.
1890
- * For axis order ABC,
1891
- * * form cross product of column A and B, store in C
1940
+ /**
1941
+ * Form cross products among columns in axisOrder.
1942
+ * For axis order ABC:
1943
+ * * form cross product of column A and B, store in C.
1892
1944
  * * form cross product of column C and A, store in B.
1945
+ * * [A B C] ===> [A B AxB] ===> [A (AxB)xA AxB]
1946
+ *
1893
1947
  * This means that in the final matrix:
1894
- * * column A is strictly parallel to original column A
1895
- * * column B is linear combination of only original A and B
1948
+ * * column A is same as original column A.
1949
+ * * column B is linear combination of original A and B (i.e., is in the plane of original A and B).
1896
1950
  * * column C is perpendicular to A and B of both the original and final.
1897
- * * original column C does not participate in the result.
1951
+ * * original column C is overwritten and does not participate in the result.
1898
1952
  */
1899
1953
  axisOrderCrossProductsInPlace(axisOrder) {
1900
1954
  switch (axisOrder) {
@@ -1930,41 +1984,44 @@ class Matrix3d {
1930
1984
  }
1931
1985
  }
1932
1986
  }
1933
- /** Normalize each column in place.
1934
- * * For false return the magnitudes are stored in the originalMagnitudes vector but no columns are altered.
1935
- * @returns Return true if all columns had nonzero lengths.
1936
- * @param originalMagnitudes optional vector to receive original column magnitudes.
1987
+ /**
1988
+ * Normalize each column in place.
1989
+ * @param originalRowMagnitudes optional vector to store original column magnitudes.
1990
+ * @returns Return true if all columns have non-zero lengths. Otherwise, return false.
1991
+ * * If false is returned, the magnitudes are stored in the `originalRowMagnitudes` vector but no columns
1992
+ * are altered.
1937
1993
  */
1938
- normalizeColumnsInPlace(originalMagnitudes) {
1994
+ normalizeColumnsInPlace(originalRowMagnitudes) {
1939
1995
  const ax = this.columnXMagnitude();
1940
1996
  const ay = this.columnYMagnitude();
1941
1997
  const az = this.columnZMagnitude();
1942
- if (originalMagnitudes)
1943
- originalMagnitudes.set(ax, ay, az);
1998
+ if (originalRowMagnitudes)
1999
+ originalRowMagnitudes.set(ax, ay, az);
1944
2000
  if (Geometry_1.Geometry.isSmallMetricDistance(ax) || Geometry_1.Geometry.isSmallMetricDistance(ay) || Geometry_1.Geometry.isSmallMetricDistance(az))
1945
2001
  return false;
1946
2002
  this.scaleColumns(1.0 / ax, 1.0 / ay, 1.0 / az, this);
1947
2003
  return true;
1948
2004
  }
1949
- /** Normalize each row in place */
1950
- normalizeRowsInPlace(originalMagnitudes) {
2005
+ /**
2006
+ * Normalize each row in place.
2007
+ * @param originalColumnMagnitudes optional vector to store original row magnitudes.
2008
+ * @returns Return true if all rows have non-zero lengths. Otherwise, return false.
2009
+ * * If false is returned, the magnitudes are stored in the `originalColumnMagnitudes` vector but no rows
2010
+ * are altered.
2011
+ */
2012
+ normalizeRowsInPlace(originalColumnMagnitudes) {
1951
2013
  const ax = this.rowXMagnitude();
1952
2014
  const ay = this.rowYMagnitude();
1953
2015
  const az = this.rowZMagnitude();
1954
- if (originalMagnitudes)
1955
- originalMagnitudes.set(ax, ay, az);
2016
+ if (originalColumnMagnitudes)
2017
+ originalColumnMagnitudes.set(ax, ay, az);
1956
2018
  if (Geometry_1.Geometry.isSmallMetricDistance(ax) || Geometry_1.Geometry.isSmallMetricDistance(ay) || Geometry_1.Geometry.isSmallMetricDistance(az))
1957
2019
  return false;
1958
2020
  this.scaleRows(1.0 / ax, 1.0 / ay, 1.0 / az, this);
1959
2021
  return true;
1960
2022
  }
1961
- // take the cross product of two rows of source.
1962
- // store as a column of dest.
1963
- static rowColumnDot(coffA, rowStartA, coffB, columnStartB) {
1964
- return coffA[rowStartA] * coffB[columnStartB] + coffA[rowStartA + 1] * coffB[columnStartB + 3] + coffA[rowStartA + 2] * coffB[columnStartB + 6];
1965
- }
1966
2023
  /**
1967
- * Returns true if the matrix is singular (i.e. collapses data to a plane, line, or point)
2024
+ * Returns true if the matrix is singular.
1968
2025
  */
1969
2026
  isSingular() {
1970
2027
  return !this.computeCachedInverse(true);
@@ -1976,18 +2033,10 @@ class Matrix3d {
1976
2033
  this.inverseState = InverseMatrixState.singular;
1977
2034
  }
1978
2035
  /**
1979
- * Create the inverseCoffs member (filled with zeros)
1980
- * This is for use by matrix * matrix multiplications which need to be sure the member is there to be
1981
- * filled with method-specific content.
1982
- */
1983
- createInverseCoffsWithZeros() {
1984
- if (!this.inverseCoffs) {
1985
- this.inverseState = InverseMatrixState.unknown;
1986
- this.inverseCoffs = new Float64Array(9);
1987
- }
1988
- }
1989
- /** compute the inverse of this Matrix3d. The inverse is stored for later use.
1990
- * @returns Return true if the inverse computed. (False if the columns collapse to a point, line or plane.)
2036
+ * Compute the inverse of `this` Matrix3d. The inverse is stored in `this.inverseCoffs` for later use.
2037
+ * @param useCacheIfAvailable if `true`, use the previously computed inverse if available. If `false`,
2038
+ * recompute the inverse.
2039
+ * @returns Return `true` if the inverse is computed. Return `false` if matrix is singular.
1991
2040
  */
1992
2041
  computeCachedInverse(useCacheIfAvailable) {
1993
2042
  if (useCacheIfAvailable && Matrix3d.useCachedInverse && this.inverseState !== InverseMatrixState.unknown) {
@@ -1998,71 +2047,45 @@ class Matrix3d {
1998
2047
  this.createInverseCoffsWithZeros();
1999
2048
  const coffs = this.coffs;
2000
2049
  const inverseCoffs = this.inverseCoffs;
2001
- Matrix3d.indexedRowCrossProduct(coffs, 3, 6, inverseCoffs, 0);
2002
- Matrix3d.indexedRowCrossProduct(coffs, 6, 0, inverseCoffs, 1);
2003
- Matrix3d.indexedRowCrossProduct(coffs, 0, 3, inverseCoffs, 2);
2050
+ /**
2051
+ * We calculate the inverse using cross products.
2052
+ * Math details can be found at
2053
+ * https://www.chilimath.com/lessons/advanced-algebra/determinant-3x3-matrix/
2054
+ * In summary, if M = [A B C] then inverse of M = (1/det)[BxC CxA AxB] where det is the
2055
+ * determinant of matrix M and can be calculated by "A dot BxC".
2056
+ */
2057
+ Matrix3d.indexedRowCrossProduct(coffs, 3, 6, inverseCoffs, 0); // BxC
2058
+ Matrix3d.indexedRowCrossProduct(coffs, 6, 0, inverseCoffs, 1); // CxA
2059
+ Matrix3d.indexedRowCrossProduct(coffs, 0, 3, inverseCoffs, 2); // AxB
2004
2060
  Matrix3d.numComputeCache++;
2005
- const d = Matrix3d.rowColumnDot(coffs, 0, inverseCoffs, 0);
2006
- if (d === 0.0) { // better test?
2061
+ const det = Matrix3d.rowColumnDot(coffs, 0, inverseCoffs, 0); // A dot BxC
2062
+ if (det === 0.0) {
2007
2063
  this.inverseState = InverseMatrixState.singular;
2008
2064
  this.inverseCoffs = undefined;
2009
2065
  return false;
2010
2066
  }
2011
- const f = 1.0 / d;
2067
+ const f = 1.0 / det;
2012
2068
  for (let i = 0; i < 9; i++)
2013
2069
  inverseCoffs[i] *= f;
2014
2070
  this.inverseState = InverseMatrixState.inverseStored;
2015
- // verify inverse
2016
- // const p = new Float64Array(9);
2017
- // for (let i = 0; i < 9; i += 3)
2018
- // for (let j = 0; j < 3; j++)
2019
- // p[i + j] = Matrix3d.rowColumnDot (coffs, i, inverseCoffs, j);
2020
2071
  return true;
2021
2072
  }
2022
- /* "Classic" inverse implementation with temporary vectors.
2023
- private static rowX: Vector3d = Vector3d.create();
2024
- private static rowY: Vector3d = Vector3d.create();
2025
- private static rowZ: Vector3d = Vector3d.create();
2026
- private static crossXY: Vector3d = Vector3d.create();
2027
- private static crossZX: Vector3d = Vector3d.create();
2028
- private static crossYZ: Vector3d = Vector3d.create();
2029
- private computeCachedInverse(useCacheIfAvailable: boolean) {
2030
- if (useCacheIfAvailable && Matrix3d.useCachedInverse && this.inverseState !== InverseMatrixState.unknown) {
2031
- Matrix3d.numUseCache++;
2032
- return this.inverseState === InverseMatrixState.inverseStored;
2033
- }
2034
- this.inverseState = InverseMatrixState.unknown;
2035
- Matrix3d.numComputeCache++;
2036
- const rowX = this.rowX(Matrix3d.rowX);
2037
- const rowY = this.rowY(Matrix3d.rowY);
2038
- const rowZ = this.rowZ(Matrix3d.rowZ);
2039
- const crossXY = rowX.crossProduct(rowY, Matrix3d.crossXY);
2040
- const crossYZ = rowY.crossProduct(rowZ, Matrix3d.crossYZ);
2041
- const crossZX = rowZ.crossProduct(rowX, Matrix3d.crossZX);
2042
- const d = rowX.dotProduct(crossYZ); // that's the determinant
2043
- if (d === 0.0) { // better test?
2044
- this.inverseState = InverseMatrixState.singular;
2045
- this.inverseCoffs = undefined;
2046
- return false;
2047
- }
2048
- const f = 1.0 / d;
2049
- this.inverseState = InverseMatrixState.inverseStored; // Currently just lists that the inverse has been stored... singular case not handled
2050
- this.inverseCoffs = Float64Array.from([crossYZ.x * f, crossZX.x * f, crossXY.x * f,
2051
- crossYZ.y * f, crossZX.y * f, crossXY.y * f,
2052
- crossYZ.z * f, crossZX.z * f, crossXY.z * f]);
2053
- return true;
2054
- }
2055
- */
2056
- /** convert a (row,column) index pair to the single index within flattened array of 9 numbers in row-major-order */
2073
+ /**
2074
+ * Convert a (row,column) index pair to the single index within flattened array of 9 numbers in row-major-order
2075
+ * * **Note:** Out of range row/column is interpreted cyclically.
2076
+ */
2057
2077
  static flatIndexOf(row, column) {
2058
2078
  return 3 * Geometry_1.Geometry.cyclic3dAxis(row) + Geometry_1.Geometry.cyclic3dAxis(column);
2059
2079
  }
2060
- /** Get a column by index (0,1,2), packaged as a Point4d with given weight. Out of range index is interpreted cyclically. */
2080
+ /**
2081
+ * Get elements of column `index` packaged as a Point4d with given `weight`.
2082
+ * * **Note:** Out of range index is interpreted cyclically.
2083
+ */
2061
2084
  indexedColumnWithWeight(index, weight, result) {
2062
2085
  index = Geometry_1.Geometry.cyclic3dAxis(index);
2063
2086
  return Point4d_1.Point4d.create(this.coffs[index], this.coffs[index + 3], this.coffs[index + 6], weight, result);
2064
2087
  }
2065
- /** return the entry at specific row and column */
2088
+ /** Return the entry at specific row and column */
2066
2089
  at(row, column) {
2067
2090
  return this.coffs[Matrix3d.flatIndexOf(row, column)];
2068
2091
  }
@@ -2096,7 +2119,7 @@ class Matrix3d {
2096
2119
  this.coffs[7] *= scaleY;
2097
2120
  this.coffs[8] *= scaleZ;
2098
2121
  if (this.inverseState === InverseMatrixState.inverseStored && this.inverseCoffs !== undefined) {
2099
- // apply reverse scales to the ROWS of the inverse
2122
+ // apply reciprocal scales to the ROWS of the inverse
2100
2123
  const divX = Geometry_1.Geometry.conditionalDivideFraction(1.0, scaleX);
2101
2124
  const divY = Geometry_1.Geometry.conditionalDivideFraction(1.0, scaleY);
2102
2125
  const divZ = Geometry_1.Geometry.conditionalDivideFraction(1.0, scaleZ);
@@ -2172,12 +2195,11 @@ class Matrix3d {
2172
2195
  /**
2173
2196
  * Create a rigid matrix (columns and rows are unit length and pairwise perpendicular) for
2174
2197
  * the given eye coordinate.
2175
- * * column z is parallel to x,y,z
2176
- * * column x is perpendicular to column z and is in the xy plane
2177
- * * column y is perpendicular to both. It is the "up" vector on the view plane.
2198
+ * * column 2 is parallel to (x,y,z).
2199
+ * * column 0 is perpendicular to column 2 and is in the xy plane.
2200
+ * * column 1 is perpendicular to both. It is the "up" vector on the view plane.
2178
2201
  * * Multiplying the returned matrix times a local (view) vector gives the world vector.
2179
- * * Multiplying transpose of the returned matrix times a world vector gives the local
2180
- * (view) vector.
2202
+ * * Multiplying transpose of the returned matrix times a world vector gives the local (view) vector.
2181
2203
  * @param x eye x coordinate
2182
2204
  * @param y eye y coordinate
2183
2205
  * @param z eye z coordinate
@@ -2192,11 +2214,27 @@ class Matrix3d {
2192
2214
  result.scaleColumnsInPlace(1.0, -1.0, -1.0);
2193
2215
  }
2194
2216
  else {
2217
+ // if coordinate is (x,y,0), i.e., Front or Back or Left or Right view
2218
+ /**
2219
+ * The matrix that the "else" statement creates is
2220
+ * [-s -s1*c c1*c]
2221
+ * [c -s1*s c1*s]
2222
+ * [0 c1 s1 ]
2223
+ * where
2224
+ * c = x / sqrt(x*x + y*y)
2225
+ * s = y / sqrt(x*x + y*y)
2226
+ * c1 = sqrt(x*x + y*y) / sqrt(x*x + y*y + z*z)
2227
+ * s1 = z / sqrt(x*x + y*y + z*z)
2228
+ *
2229
+ * This is an orthogonal matrix meaning it rotates the standard XYZ axis to ABC axis system
2230
+ * (if matrix is [A B C]). The matrix rotates (0,0,1), i.e., the default Top view or Z axis,
2231
+ * to the eye point (x/r,y/r,z/r). The matrix also rotates (1,0,0) to a point on XY plane.
2232
+ */
2195
2233
  const c = x / rxy;
2196
2234
  const s = y / rxy;
2197
- // if coordinate is (x,y,0), i.e., Front or Back or Left or Right view
2235
+ // if coordinate is (x,y,0), e.g., Front or Back or Left or Right view (for those 4 views x or y is 0 not both)
2198
2236
  result.setRowValues(-s, 0, c, c, 0, s, 0, 1, 0);
2199
- // if coordinate is (x,y,z), i.e., other views such as Iso or RightIso
2237
+ // if coordinate is (x,y,z) and z is not 0, i.e., other views such as Iso or RightIso
2200
2238
  if (z !== 0.0) {
2201
2239
  const r = Geometry_1.Geometry.hypotenuseXYZ(x, y, z);
2202
2240
  const s1 = z / r;
@@ -2469,5 +2507,6 @@ Matrix3d.useCachedInverse = true; // cached inverse can be suppressed for testin
2469
2507
  Matrix3d.numUseCache = 0;
2470
2508
  /** Total number of times a cached inverse was computed. */
2471
2509
  Matrix3d.numComputeCache = 0;
2510
+ /** temporary buffer to store a matrix as a Float64Array (array of 9 floats) */
2472
2511
  Matrix3d._productBuffer = new Float64Array(9);
2473
2512
  //# sourceMappingURL=Matrix3d.js.map