@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.
- package/CHANGELOG.md +10 -1
- package/lib/cjs/geometry3d/Angle.d.ts +1 -0
- package/lib/cjs/geometry3d/Angle.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Angle.js +1 -0
- package/lib/cjs/geometry3d/Angle.js.map +1 -1
- package/lib/cjs/geometry3d/AngleSweep.d.ts +1 -0
- package/lib/cjs/geometry3d/AngleSweep.d.ts.map +1 -1
- package/lib/cjs/geometry3d/AngleSweep.js +1 -0
- package/lib/cjs/geometry3d/AngleSweep.js.map +1 -1
- package/lib/cjs/geometry3d/Matrix3d.d.ts +161 -96
- package/lib/cjs/geometry3d/Matrix3d.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Matrix3d.js +245 -206
- package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
- package/lib/cjs/geometry3d/Point3dVector3d.d.ts +3 -0
- package/lib/cjs/geometry3d/Point3dVector3d.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Point3dVector3d.js +3 -0
- package/lib/cjs/geometry3d/Point3dVector3d.js.map +1 -1
- package/lib/esm/geometry3d/Angle.d.ts +1 -0
- package/lib/esm/geometry3d/Angle.d.ts.map +1 -1
- package/lib/esm/geometry3d/Angle.js +1 -0
- package/lib/esm/geometry3d/Angle.js.map +1 -1
- package/lib/esm/geometry3d/AngleSweep.d.ts +1 -0
- package/lib/esm/geometry3d/AngleSweep.d.ts.map +1 -1
- package/lib/esm/geometry3d/AngleSweep.js +1 -0
- package/lib/esm/geometry3d/AngleSweep.js.map +1 -1
- package/lib/esm/geometry3d/Matrix3d.d.ts +161 -96
- package/lib/esm/geometry3d/Matrix3d.d.ts.map +1 -1
- package/lib/esm/geometry3d/Matrix3d.js +245 -206
- package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
- package/lib/esm/geometry3d/Point3dVector3d.d.ts +3 -0
- package/lib/esm/geometry3d/Point3dVector3d.d.ts.map +1 -1
- package/lib/esm/geometry3d/Point3dVector3d.js +3 -0
- package/lib/esm/geometry3d/Point3dVector3d.js.map +1 -1
- 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
|
-
|
|
430
|
-
|
|
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.
|
|
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
|
|
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
|
-
/**
|
|
1554
|
-
*
|
|
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 =
|
|
1559
|
-
result.y =
|
|
1560
|
-
result.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
|
-
/**
|
|
1564
|
-
*
|
|
1565
|
-
*
|
|
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 =
|
|
1572
|
-
result.y =
|
|
1573
|
-
result.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
|
-
/**
|
|
1577
|
-
*
|
|
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 =
|
|
1582
|
-
result.y =
|
|
1583
|
-
result.z =
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
|
|
1596
|
-
xyzData.
|
|
1597
|
-
xyzData.
|
|
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
|
-
/**
|
|
1601
|
-
*
|
|
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
|
-
|
|
1608
|
-
vectorU.
|
|
1609
|
-
vectorU.
|
|
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
|
-
/**
|
|
1613
|
-
*
|
|
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 =
|
|
1627
|
-
result.y =
|
|
1628
|
-
result.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
|
-
/**
|
|
1632
|
-
*
|
|
1633
|
-
* *
|
|
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(
|
|
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
|
-
/**
|
|
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
|
|
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(
|
|
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
|
-
*
|
|
1661
|
-
* *
|
|
1662
|
-
* *
|
|
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(
|
|
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
|
-
*
|
|
1673
|
-
* *
|
|
1674
|
-
* *
|
|
1675
|
-
*
|
|
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(
|
|
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
|
-
*
|
|
1686
|
-
* *
|
|
1687
|
-
*
|
|
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(
|
|
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
|
-
*
|
|
1699
|
-
* * set
|
|
1700
|
-
*
|
|
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
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
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
|
|
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
|
|
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
|
-
/**
|
|
1735
|
-
*
|
|
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
|
-
/**
|
|
1750
|
-
*
|
|
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
|
-
/**
|
|
1796
|
+
/**
|
|
1797
|
+
* Multiply `this` matrix times the transpose of `other` matrix
|
|
1765
1798
|
* ```
|
|
1766
1799
|
* equation
|
|
1767
|
-
* \text{for instance matrix }A\text{ and
|
|
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(
|
|
1804
|
+
multiplyMatrixMatrixTranspose(other, result) {
|
|
1772
1805
|
result = result ? result : new Matrix3d();
|
|
1773
|
-
PackedMatrix3dOps.multiplyMatrixMatrixTranspose(this.coffs,
|
|
1774
|
-
if (this.inverseState === InverseMatrixState.inverseStored &&
|
|
1775
|
-
result.finishInverseCoffs(PackedMatrix3dOps.multiplyMatrixTransposeMatrix,
|
|
1776
|
-
else if (this.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
|
-
/**
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
1805
|
-
*
|
|
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
|
|
1810
|
-
* @param result
|
|
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
|
-
/**
|
|
1848
|
-
*
|
|
1849
|
-
*
|
|
1850
|
-
* *
|
|
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
|
|
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
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
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
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
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
|
-
/**
|
|
1890
|
-
*
|
|
1891
|
-
*
|
|
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
|
|
1895
|
-
* * column B is linear combination of
|
|
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
|
-
/**
|
|
1934
|
-
*
|
|
1935
|
-
* @
|
|
1936
|
-
* @
|
|
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(
|
|
1994
|
+
normalizeColumnsInPlace(originalRowMagnitudes) {
|
|
1939
1995
|
const ax = this.columnXMagnitude();
|
|
1940
1996
|
const ay = this.columnYMagnitude();
|
|
1941
1997
|
const az = this.columnZMagnitude();
|
|
1942
|
-
if (
|
|
1943
|
-
|
|
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
|
-
/**
|
|
1950
|
-
|
|
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 (
|
|
1955
|
-
|
|
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
|
|
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
|
-
*
|
|
1980
|
-
*
|
|
1981
|
-
*
|
|
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
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
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
|
|
2006
|
-
if (
|
|
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 /
|
|
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
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
|
2176
|
-
* * column
|
|
2177
|
-
* * column
|
|
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),
|
|
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
|