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