@itwin/core-geometry 4.0.0-dev.37 → 4.0.0-dev.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/Geometry.d.ts +28 -12
- package/lib/cjs/Geometry.d.ts.map +1 -1
- package/lib/cjs/Geometry.js +33 -17
- package/lib/cjs/Geometry.js.map +1 -1
- package/lib/cjs/curve/Loop.d.ts.map +1 -1
- package/lib/cjs/curve/Loop.js +6 -0
- package/lib/cjs/curve/Loop.js.map +1 -1
- package/lib/cjs/curve/RegionOps.d.ts +8 -9
- package/lib/cjs/curve/RegionOps.d.ts.map +1 -1
- package/lib/cjs/curve/RegionOps.js +8 -9
- package/lib/cjs/curve/RegionOps.js.map +1 -1
- package/lib/cjs/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
- package/lib/cjs/curve/RegionOpsClassificationSweeps.js +2 -0
- package/lib/cjs/curve/RegionOpsClassificationSweeps.js.map +1 -1
- package/lib/cjs/geometry3d/Matrix3d.d.ts +137 -89
- package/lib/cjs/geometry3d/Matrix3d.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Matrix3d.js +244 -155
- package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
- package/lib/cjs/geometry3d/Point3dVector3d.d.ts +15 -15
- package/lib/cjs/geometry3d/Point3dVector3d.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Point3dVector3d.js +16 -19
- package/lib/cjs/geometry3d/Point3dVector3d.js.map +1 -1
- package/lib/cjs/geometry3d/PolygonOps.d.ts +7 -9
- package/lib/cjs/geometry3d/PolygonOps.d.ts.map +1 -1
- package/lib/cjs/geometry3d/PolygonOps.js +7 -9
- package/lib/cjs/geometry3d/PolygonOps.js.map +1 -1
- package/lib/cjs/polyface/PolyfaceBuilder.d.ts +3 -0
- package/lib/cjs/polyface/PolyfaceBuilder.d.ts.map +1 -1
- package/lib/cjs/polyface/PolyfaceBuilder.js +7 -0
- package/lib/cjs/polyface/PolyfaceBuilder.js.map +1 -1
- package/lib/cjs/serialization/GeometrySamples.d.ts +4 -5
- package/lib/cjs/serialization/GeometrySamples.d.ts.map +1 -1
- package/lib/cjs/serialization/GeometrySamples.js +12 -13
- package/lib/cjs/serialization/GeometrySamples.js.map +1 -1
- package/lib/cjs/solid/SweepContour.d.ts.map +1 -1
- package/lib/cjs/solid/SweepContour.js +7 -0
- package/lib/cjs/solid/SweepContour.js.map +1 -1
- package/lib/cjs/topology/HalfEdgeGraphSearch.d.ts +2 -1
- package/lib/cjs/topology/HalfEdgeGraphSearch.d.ts.map +1 -1
- package/lib/cjs/topology/HalfEdgeGraphSearch.js +1 -0
- package/lib/cjs/topology/HalfEdgeGraphSearch.js.map +1 -1
- package/lib/esm/Geometry.d.ts +28 -12
- package/lib/esm/Geometry.d.ts.map +1 -1
- package/lib/esm/Geometry.js +33 -17
- package/lib/esm/Geometry.js.map +1 -1
- package/lib/esm/curve/Loop.d.ts.map +1 -1
- package/lib/esm/curve/Loop.js +6 -0
- package/lib/esm/curve/Loop.js.map +1 -1
- package/lib/esm/curve/RegionOps.d.ts +8 -9
- package/lib/esm/curve/RegionOps.d.ts.map +1 -1
- package/lib/esm/curve/RegionOps.js +8 -9
- package/lib/esm/curve/RegionOps.js.map +1 -1
- package/lib/esm/curve/RegionOpsClassificationSweeps.d.ts.map +1 -1
- package/lib/esm/curve/RegionOpsClassificationSweeps.js +2 -0
- package/lib/esm/curve/RegionOpsClassificationSweeps.js.map +1 -1
- package/lib/esm/geometry3d/Matrix3d.d.ts +137 -89
- package/lib/esm/geometry3d/Matrix3d.d.ts.map +1 -1
- package/lib/esm/geometry3d/Matrix3d.js +244 -155
- package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
- package/lib/esm/geometry3d/Point3dVector3d.d.ts +15 -15
- package/lib/esm/geometry3d/Point3dVector3d.d.ts.map +1 -1
- package/lib/esm/geometry3d/Point3dVector3d.js +16 -19
- package/lib/esm/geometry3d/Point3dVector3d.js.map +1 -1
- package/lib/esm/geometry3d/PolygonOps.d.ts +7 -9
- package/lib/esm/geometry3d/PolygonOps.d.ts.map +1 -1
- package/lib/esm/geometry3d/PolygonOps.js +7 -9
- package/lib/esm/geometry3d/PolygonOps.js.map +1 -1
- package/lib/esm/polyface/PolyfaceBuilder.d.ts +3 -0
- package/lib/esm/polyface/PolyfaceBuilder.d.ts.map +1 -1
- package/lib/esm/polyface/PolyfaceBuilder.js +7 -0
- package/lib/esm/polyface/PolyfaceBuilder.js.map +1 -1
- package/lib/esm/serialization/GeometrySamples.d.ts +4 -5
- package/lib/esm/serialization/GeometrySamples.d.ts.map +1 -1
- package/lib/esm/serialization/GeometrySamples.js +12 -13
- package/lib/esm/serialization/GeometrySamples.js.map +1 -1
- package/lib/esm/solid/SweepContour.d.ts.map +1 -1
- package/lib/esm/solid/SweepContour.js +7 -0
- package/lib/esm/solid/SweepContour.js.map +1 -1
- package/lib/esm/topology/HalfEdgeGraphSearch.d.ts +2 -1
- package/lib/esm/topology/HalfEdgeGraphSearch.d.ts.map +1 -1
- package/lib/esm/topology/HalfEdgeGraphSearch.js +1 -0
- package/lib/esm/topology/HalfEdgeGraphSearch.js.map +1 -1
- package/package.json +3 -3
|
@@ -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 SaeedTorabi
|
|
15
|
+
// cSpell:words XXYZ YXYZ ZXYZ SaeedTorabi arctan newcommand
|
|
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
|
|
@@ -308,7 +308,7 @@ export class Matrix3d {
|
|
|
308
308
|
/**
|
|
309
309
|
* Here we rotate this.columnX() around this.columnZ() by "angle" and expect to get other.columnX().
|
|
310
310
|
* Then we rotate this.columnY() around this.columnZ() by the same "angle" and if we get other.columnY(),
|
|
311
|
-
* that means this` and `other` have X and Y columns differing only by a rotation around
|
|
311
|
+
* that means `this` and `other` have X and Y columns differing only by a rotation around column Z.
|
|
312
312
|
*/
|
|
313
313
|
let column = Vector3d.createRotateVectorAroundVector(columnX, columnZ, angle);
|
|
314
314
|
if (other.isAlmostEqualColumnXYZ(0, column.x, column.y, column.z, tol)) {
|
|
@@ -757,14 +757,16 @@ export class Matrix3d {
|
|
|
757
757
|
static createColumnsXYW(vectorU, u, vectorV, v, vectorW, w, result) {
|
|
758
758
|
return Matrix3d.createRowValues(vectorU.x, vectorV.x, vectorW.x, vectorU.y, vectorV.y, vectorW.y, u, v, w, result);
|
|
759
759
|
}
|
|
760
|
-
/**
|
|
761
|
-
*
|
|
762
|
-
* *
|
|
760
|
+
/**
|
|
761
|
+
* Create a matrix from "as viewed" right and up vectors.
|
|
762
|
+
* * ColumnX points in the rightVector direction.
|
|
763
|
+
* * ColumnY points in the upVector direction.
|
|
763
764
|
* * ColumnZ is a unit cross product of ColumnX and ColumnY.
|
|
764
765
|
* * Optionally rotate by 45 degrees around `upVector` to bring its left or right vertical edge to center.
|
|
765
766
|
* * Optionally rotate by arctan(1/sqrt(2)) ~ 35.264 degrees around `rightVector` to bring the top or bottom
|
|
766
767
|
* horizontal edge of the view to the center (for isometric views).
|
|
767
|
-
*
|
|
768
|
+
*
|
|
769
|
+
* This is expected to be used with various principal unit vectors that are perpendicular to each other.
|
|
768
770
|
* * STANDARD TOP VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitY(), 0, 0)
|
|
769
771
|
* * STANDARD FRONT VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitZ(), 0, 0)
|
|
770
772
|
* * STANDARD BACK VIEW: createViewedAxes(Vector3d.unitX(-1), Vector3d.unitZ(), 0, 0)
|
|
@@ -1253,6 +1255,18 @@ export class Matrix3d {
|
|
|
1253
1255
|
+ this.coffs[3] * this.coffs[4]
|
|
1254
1256
|
+ this.coffs[6] * this.coffs[7];
|
|
1255
1257
|
}
|
|
1258
|
+
/** Return the dot product of column X with column Z */
|
|
1259
|
+
columnXDotColumnZ() {
|
|
1260
|
+
return this.coffs[0] * this.coffs[2]
|
|
1261
|
+
+ this.coffs[3] * this.coffs[5]
|
|
1262
|
+
+ this.coffs[6] * this.coffs[8];
|
|
1263
|
+
}
|
|
1264
|
+
/** Return the dot product of column Y with column Z */
|
|
1265
|
+
columnYDotColumnZ() {
|
|
1266
|
+
return this.coffs[1] * this.coffs[2]
|
|
1267
|
+
+ this.coffs[4] * this.coffs[5]
|
|
1268
|
+
+ this.coffs[7] * this.coffs[8];
|
|
1269
|
+
}
|
|
1256
1270
|
/**
|
|
1257
1271
|
* Dot product of an indexed column with a vector given as x,y,z
|
|
1258
1272
|
* @param columnIndex index of column. Must be 0,1,2.
|
|
@@ -1547,7 +1561,7 @@ export class Matrix3d {
|
|
|
1547
1561
|
* \text{Treating U as a row to the left of untransposed matrix\: return row}&\rowSubXYZ{V}&=&\rowSubXYZ{U}\matrixXY{A}
|
|
1548
1562
|
* \end{matrix}
|
|
1549
1563
|
* ```
|
|
1550
|
-
* @
|
|
1564
|
+
* @param result the vector result (optional)
|
|
1551
1565
|
*/
|
|
1552
1566
|
multiplyTransposeVector(vector, result) {
|
|
1553
1567
|
result = result ? result : new Vector3d();
|
|
@@ -1561,7 +1575,7 @@ export class Matrix3d {
|
|
|
1561
1575
|
}
|
|
1562
1576
|
/**
|
|
1563
1577
|
* Multiply the matrix * [x,y,z], i.e. the vector [x,y,z] is a column vector on the right.
|
|
1564
|
-
* @
|
|
1578
|
+
* @param result the vector result (optional)
|
|
1565
1579
|
*/
|
|
1566
1580
|
multiplyXYZ(x, y, z, result) {
|
|
1567
1581
|
result = result ? result : new Vector3d();
|
|
@@ -1586,7 +1600,7 @@ export class Matrix3d {
|
|
|
1586
1600
|
}
|
|
1587
1601
|
/**
|
|
1588
1602
|
* Multiply the matrix * [x,y,0], i.e. the vector [x,y,0] is a column vector on the right.
|
|
1589
|
-
* @
|
|
1603
|
+
* @param result the vector result (optional)
|
|
1590
1604
|
*/
|
|
1591
1605
|
multiplyXY(x, y, result) {
|
|
1592
1606
|
result = result ? result : new Vector3d();
|
|
@@ -1597,7 +1611,7 @@ export class Matrix3d {
|
|
|
1597
1611
|
}
|
|
1598
1612
|
/**
|
|
1599
1613
|
* Compute origin + the matrix * [x,y,0].
|
|
1600
|
-
* @
|
|
1614
|
+
* @param result the Point3d result (optional)
|
|
1601
1615
|
*/
|
|
1602
1616
|
originPlusMatrixTimesXY(origin, x, y, result) {
|
|
1603
1617
|
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);
|
|
@@ -1605,7 +1619,7 @@ export class Matrix3d {
|
|
|
1605
1619
|
/**
|
|
1606
1620
|
* Multiply the matrix * (x,y,z) in place, i.e. the vector (x,y,z) is a column vector on the right and
|
|
1607
1621
|
* the multiplication updates the vector values.
|
|
1608
|
-
* @param xyzData the vector data
|
|
1622
|
+
* @param xyzData the vector data.
|
|
1609
1623
|
*/
|
|
1610
1624
|
multiplyVectorInPlace(xyzData) {
|
|
1611
1625
|
const x = xyzData.x;
|
|
@@ -1619,7 +1633,7 @@ export class Matrix3d {
|
|
|
1619
1633
|
* Multiply the transpose matrix times [x,y,z] in place, i.e. the vector [x,y,z] is a column vector on
|
|
1620
1634
|
* the right and the multiplication updates the vector values.
|
|
1621
1635
|
* * This is equivalent to `multiplyTransposeVector` but always returns the result directly in the input.
|
|
1622
|
-
* @param
|
|
1636
|
+
* @param vectorU the vector data
|
|
1623
1637
|
*/
|
|
1624
1638
|
multiplyTransposeVectorInPlace(vectorU) {
|
|
1625
1639
|
const x = vectorU.x;
|
|
@@ -1640,7 +1654,7 @@ export class Matrix3d {
|
|
|
1640
1654
|
* \phantom{8888}\text{and return V as a Vector3d} & & &
|
|
1641
1655
|
* \end{matrix}
|
|
1642
1656
|
* ````
|
|
1643
|
-
* @
|
|
1657
|
+
* @param result the vector result (optional)
|
|
1644
1658
|
*/
|
|
1645
1659
|
multiplyTransposeXYZ(x, y, z, result) {
|
|
1646
1660
|
result = result ? result : new Vector3d();
|
|
@@ -1651,8 +1665,8 @@ export class Matrix3d {
|
|
|
1651
1665
|
}
|
|
1652
1666
|
/**
|
|
1653
1667
|
* Solve `matrix * result = vector` for an unknown `result`.
|
|
1654
|
-
* * This is equivalent to multiplication `result =
|
|
1655
|
-
* * Result is undefined if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
|
|
1668
|
+
* * This is equivalent to multiplication `result = matrixInverse * vector`.
|
|
1669
|
+
* * Result is `undefined` if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
|
|
1656
1670
|
*/
|
|
1657
1671
|
multiplyInverse(vector, result) {
|
|
1658
1672
|
this.computeCachedInverse(true);
|
|
@@ -1667,7 +1681,7 @@ export class Matrix3d {
|
|
|
1667
1681
|
/**
|
|
1668
1682
|
* Solve `matrixTranspose * result = vector` for an unknown `result`.
|
|
1669
1683
|
* * This is equivalent to multiplication `result = matrixInverseTranspose * vector`.
|
|
1670
|
-
* * Result is undefined if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
|
|
1684
|
+
* * Result is `undefined` if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
|
|
1671
1685
|
*/
|
|
1672
1686
|
multiplyInverseTranspose(vector, result) {
|
|
1673
1687
|
this.computeCachedInverse(true);
|
|
@@ -1682,7 +1696,7 @@ export class Matrix3d {
|
|
|
1682
1696
|
/**
|
|
1683
1697
|
* Multiply `matrixInverse * [x,y,z]`.
|
|
1684
1698
|
* * 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)
|
|
1699
|
+
* * Result is `undefined` if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
|
|
1686
1700
|
* @return result as a Vector3d or undefined (if the matrix is singular).
|
|
1687
1701
|
*/
|
|
1688
1702
|
multiplyInverseXYZAsVector3d(x, y, z, result) {
|
|
@@ -1695,7 +1709,7 @@ export class Matrix3d {
|
|
|
1695
1709
|
/**
|
|
1696
1710
|
* Multiply `matrixInverse * [x,y,z]` and return result as `Point4d` with given weight.
|
|
1697
1711
|
* * 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)
|
|
1712
|
+
* * Result is `undefined` if the matrix is singular (e.g. has parallel columns or a zero magnitude column)
|
|
1699
1713
|
* @return result as a Point4d with the same weight.
|
|
1700
1714
|
*/
|
|
1701
1715
|
multiplyInverseXYZW(x, y, z, w, result) {
|
|
@@ -1708,7 +1722,7 @@ export class Matrix3d {
|
|
|
1708
1722
|
/**
|
|
1709
1723
|
* Multiply `matrixInverse * [x,y,z]` and return result as `Point3d`.
|
|
1710
1724
|
* * 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).
|
|
1725
|
+
* @return result as a Point3d or `undefined` (if the matrix is singular).
|
|
1712
1726
|
*/
|
|
1713
1727
|
multiplyInverseXYZAsPoint3d(x, y, z, result) {
|
|
1714
1728
|
this.computeCachedInverse(true);
|
|
@@ -1719,7 +1733,7 @@ export class Matrix3d {
|
|
|
1719
1733
|
}
|
|
1720
1734
|
/**
|
|
1721
1735
|
* Invoke a given matrix*matrix operation to compute the inverse matrix and set this.inverseCoffs
|
|
1722
|
-
* * If either input coffA or coffB is undefined
|
|
1736
|
+
* * If either input coffA or coffB is `undefined`, set state to `InverseMatrixState.unknown` but
|
|
1723
1737
|
* leave the inverseCoffs untouched.
|
|
1724
1738
|
* @param f the given matrix*matrix operation that is called by this function to compute the inverse.
|
|
1725
1739
|
* `f` must be a matrix*matrix operation. Otherwise, the function does not generate the inverse properly.
|
|
@@ -1941,10 +1955,12 @@ export class Matrix3d {
|
|
|
1941
1955
|
* * [A B C] ===> [A B AxB] ===> [A (AxB)xA AxB]
|
|
1942
1956
|
*
|
|
1943
1957
|
* This means that in the final matrix:
|
|
1944
|
-
* * column
|
|
1945
|
-
* * column
|
|
1946
|
-
* * column
|
|
1958
|
+
* * first column is same as original column A.
|
|
1959
|
+
* * second column is linear combination of original A and B (i.e., is in the plane of original A and B).
|
|
1960
|
+
* * third column is perpendicular to first and second columns of both the original and final.
|
|
1947
1961
|
* * original column C is overwritten and does not participate in the result.
|
|
1962
|
+
*
|
|
1963
|
+
* The final matrix will have 3 orthogonal columns.
|
|
1948
1964
|
*/
|
|
1949
1965
|
axisOrderCrossProductsInPlace(axisOrder) {
|
|
1950
1966
|
switch (axisOrder) {
|
|
@@ -1982,35 +1998,35 @@ export class Matrix3d {
|
|
|
1982
1998
|
}
|
|
1983
1999
|
/**
|
|
1984
2000
|
* Normalize each column in place.
|
|
1985
|
-
* @param
|
|
1986
|
-
* @returns
|
|
1987
|
-
* * If false is returned, the magnitudes are stored in the `
|
|
2001
|
+
* @param originalColumnMagnitudes optional vector to store original column magnitudes.
|
|
2002
|
+
* @returns return true if all columns have non-zero lengths. Otherwise, return false.
|
|
2003
|
+
* * If false is returned, the magnitudes are stored in the `originalColumnMagnitudes` vector but no columns
|
|
1988
2004
|
* are altered.
|
|
1989
2005
|
*/
|
|
1990
|
-
normalizeColumnsInPlace(
|
|
2006
|
+
normalizeColumnsInPlace(originalColumnMagnitudes) {
|
|
1991
2007
|
const ax = this.columnXMagnitude();
|
|
1992
2008
|
const ay = this.columnYMagnitude();
|
|
1993
2009
|
const az = this.columnZMagnitude();
|
|
1994
|
-
if (
|
|
1995
|
-
|
|
2010
|
+
if (originalColumnMagnitudes)
|
|
2011
|
+
originalColumnMagnitudes.set(ax, ay, az);
|
|
1996
2012
|
if (Geometry.isSmallMetricDistance(ax) || Geometry.isSmallMetricDistance(ay) || Geometry.isSmallMetricDistance(az))
|
|
1997
2013
|
return false;
|
|
1998
2014
|
this.scaleColumns(1.0 / ax, 1.0 / ay, 1.0 / az, this);
|
|
1999
2015
|
return true;
|
|
2000
2016
|
}
|
|
2001
2017
|
/**
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
normalizeRowsInPlace(
|
|
2018
|
+
* Normalize each row in place.
|
|
2019
|
+
* @param originalRowMagnitudes optional vector to store original row magnitudes.
|
|
2020
|
+
* @returns return true if all rows have non-zero lengths. Otherwise, return false.
|
|
2021
|
+
* * If false is returned, the magnitudes are stored in the `originalRowMagnitudes` vector but no rows
|
|
2022
|
+
* are altered.
|
|
2023
|
+
*/
|
|
2024
|
+
normalizeRowsInPlace(originalRowMagnitudes) {
|
|
2009
2025
|
const ax = this.rowXMagnitude();
|
|
2010
2026
|
const ay = this.rowYMagnitude();
|
|
2011
2027
|
const az = this.rowZMagnitude();
|
|
2012
|
-
if (
|
|
2013
|
-
|
|
2028
|
+
if (originalRowMagnitudes)
|
|
2029
|
+
originalRowMagnitudes.set(ax, ay, az);
|
|
2014
2030
|
if (Geometry.isSmallMetricDistance(ax) || Geometry.isSmallMetricDistance(ay) || Geometry.isSmallMetricDistance(az))
|
|
2015
2031
|
return false;
|
|
2016
2032
|
this.scaleRows(1.0 / ax, 1.0 / ay, 1.0 / az, this);
|
|
@@ -2032,7 +2048,7 @@ export class Matrix3d {
|
|
|
2032
2048
|
* Compute the inverse of `this` Matrix3d. The inverse is stored in `this.inverseCoffs` for later use.
|
|
2033
2049
|
* @param useCacheIfAvailable if `true`, use the previously computed inverse if available. If `false`,
|
|
2034
2050
|
* recompute the inverse.
|
|
2035
|
-
* @returns
|
|
2051
|
+
* @returns return `true` if the inverse is computed. Return `false` if matrix is singular.
|
|
2036
2052
|
*/
|
|
2037
2053
|
computeCachedInverse(useCacheIfAvailable) {
|
|
2038
2054
|
if (useCacheIfAvailable && Matrix3d.useCachedInverse && this.inverseState !== InverseMatrixState.unknown) {
|
|
@@ -2045,10 +2061,11 @@ export class Matrix3d {
|
|
|
2045
2061
|
const inverseCoffs = this.inverseCoffs;
|
|
2046
2062
|
/**
|
|
2047
2063
|
* We calculate the inverse using cross products.
|
|
2048
|
-
* Math details can be found at
|
|
2049
|
-
*
|
|
2050
|
-
* In summary, if M = [
|
|
2051
|
-
*
|
|
2064
|
+
* Math details can be found at docs/learning/matrix/Matrix.md
|
|
2065
|
+
* [ A ]
|
|
2066
|
+
* In summary, if M = [ B ] then inverse of M = (1/det)[BxC CxA AxB] where
|
|
2067
|
+
* [ C ]
|
|
2068
|
+
* det is the determinant of matrix M (which is equal to "A dot BxC").
|
|
2052
2069
|
*/
|
|
2053
2070
|
Matrix3d.indexedRowCrossProduct(coffs, 3, 6, inverseCoffs, 0); // BxC
|
|
2054
2071
|
Matrix3d.indexedRowCrossProduct(coffs, 6, 0, inverseCoffs, 1); // CxA
|
|
@@ -2090,19 +2107,30 @@ export class Matrix3d {
|
|
|
2090
2107
|
this.coffs[Matrix3d.flatIndexOf(row, column)] = value;
|
|
2091
2108
|
this.inverseState = InverseMatrixState.unknown;
|
|
2092
2109
|
}
|
|
2093
|
-
/**
|
|
2094
|
-
*
|
|
2095
|
-
* @param
|
|
2096
|
-
* @param
|
|
2097
|
-
* @
|
|
2110
|
+
/**
|
|
2111
|
+
* Create a Matrix3d whose values are uniformly scaled from `this` Matrix3d.
|
|
2112
|
+
* @param scale scale factor to apply.
|
|
2113
|
+
* @param result optional result.
|
|
2114
|
+
* @returns return the scaled matrix.
|
|
2115
|
+
*/
|
|
2116
|
+
scale(scale, result) {
|
|
2117
|
+
return Matrix3d.createRowValues(this.coffs[0] * scale, this.coffs[1] * scale, this.coffs[2] * scale, this.coffs[3] * scale, this.coffs[4] * scale, this.coffs[5] * scale, this.coffs[6] * scale, this.coffs[7] * scale, this.coffs[8] * scale, result);
|
|
2118
|
+
}
|
|
2119
|
+
/**
|
|
2120
|
+
* Create a Matrix3d whose columns are scaled copies of `this` Matrix3d.
|
|
2121
|
+
* @param scaleX scale factor for column 0
|
|
2122
|
+
* @param scaleY scale factor for column 1
|
|
2123
|
+
* @param scaleZ scale factor for column 2
|
|
2124
|
+
* @param result optional result
|
|
2098
2125
|
*/
|
|
2099
2126
|
scaleColumns(scaleX, scaleY, scaleZ, result) {
|
|
2100
2127
|
return Matrix3d.createRowValues(this.coffs[0] * scaleX, this.coffs[1] * scaleY, this.coffs[2] * scaleZ, this.coffs[3] * scaleX, this.coffs[4] * scaleY, this.coffs[5] * scaleZ, this.coffs[6] * scaleX, this.coffs[7] * scaleY, this.coffs[8] * scaleZ, result);
|
|
2101
2128
|
}
|
|
2102
|
-
/**
|
|
2103
|
-
*
|
|
2104
|
-
* @param
|
|
2105
|
-
* @param
|
|
2129
|
+
/**
|
|
2130
|
+
* Scale the columns of `this` Matrix3d in place.
|
|
2131
|
+
* @param scaleX scale factor for column 0
|
|
2132
|
+
* @param scaleY scale factor for column 1
|
|
2133
|
+
* @param scaleZ scale factor for column 2
|
|
2106
2134
|
*/
|
|
2107
2135
|
scaleColumnsInPlace(scaleX, scaleY, scaleZ) {
|
|
2108
2136
|
this.coffs[0] *= scaleX;
|
|
@@ -2134,18 +2162,55 @@ export class Matrix3d {
|
|
|
2134
2162
|
this.inverseState = InverseMatrixState.singular;
|
|
2135
2163
|
}
|
|
2136
2164
|
}
|
|
2137
|
-
/**
|
|
2138
|
-
*
|
|
2139
|
-
* @param
|
|
2140
|
-
* @param
|
|
2141
|
-
* @param
|
|
2165
|
+
/**
|
|
2166
|
+
* Create a Matrix3d whose rows are scaled copies of `this` Matrix3d.
|
|
2167
|
+
* @param scaleX scale factor for row 0
|
|
2168
|
+
* @param scaleY scale factor for row 1
|
|
2169
|
+
* @param scaleZ scale factor for row 2
|
|
2170
|
+
* @param result optional result
|
|
2142
2171
|
*/
|
|
2143
2172
|
scaleRows(scaleX, scaleY, scaleZ, result) {
|
|
2144
2173
|
return Matrix3d.createRowValues(this.coffs[0] * scaleX, this.coffs[1] * scaleX, this.coffs[2] * scaleX, this.coffs[3] * scaleY, this.coffs[4] * scaleY, this.coffs[5] * scaleY, this.coffs[6] * scaleZ, this.coffs[7] * scaleZ, this.coffs[8] * scaleZ, result);
|
|
2145
2174
|
}
|
|
2146
2175
|
/**
|
|
2147
|
-
*
|
|
2148
|
-
* @param
|
|
2176
|
+
* Scale the rows of `this` Matrix3d in place.
|
|
2177
|
+
* @param scaleX scale factor for row 0
|
|
2178
|
+
* @param scaleY scale factor for row 1
|
|
2179
|
+
* @param scaleZ scale factor for row 2
|
|
2180
|
+
*/
|
|
2181
|
+
scaleRowsInPlace(scaleX, scaleY, scaleZ) {
|
|
2182
|
+
this.coffs[0] *= scaleX;
|
|
2183
|
+
this.coffs[1] *= scaleX;
|
|
2184
|
+
this.coffs[2] *= scaleX;
|
|
2185
|
+
this.coffs[3] *= scaleY;
|
|
2186
|
+
this.coffs[4] *= scaleY;
|
|
2187
|
+
this.coffs[5] *= scaleY;
|
|
2188
|
+
this.coffs[6] *= scaleZ;
|
|
2189
|
+
this.coffs[7] *= scaleZ;
|
|
2190
|
+
this.coffs[8] *= scaleZ;
|
|
2191
|
+
if (this.inverseState === InverseMatrixState.inverseStored && this.inverseCoffs !== undefined) {
|
|
2192
|
+
// apply reciprocal scales to the COLUMNs of the inverse
|
|
2193
|
+
const divX = Geometry.conditionalDivideFraction(1.0, scaleX);
|
|
2194
|
+
const divY = Geometry.conditionalDivideFraction(1.0, scaleY);
|
|
2195
|
+
const divZ = Geometry.conditionalDivideFraction(1.0, scaleZ);
|
|
2196
|
+
if (divX !== undefined && divY !== undefined && divZ !== undefined) {
|
|
2197
|
+
this.inverseCoffs[0] *= divX;
|
|
2198
|
+
this.inverseCoffs[1] *= divY;
|
|
2199
|
+
this.inverseCoffs[2] *= divZ;
|
|
2200
|
+
this.inverseCoffs[3] *= divX;
|
|
2201
|
+
this.inverseCoffs[4] *= divY;
|
|
2202
|
+
this.inverseCoffs[5] *= divZ;
|
|
2203
|
+
this.inverseCoffs[6] *= divX;
|
|
2204
|
+
this.inverseCoffs[7] *= divY;
|
|
2205
|
+
this.inverseCoffs[8] *= divZ;
|
|
2206
|
+
}
|
|
2207
|
+
else
|
|
2208
|
+
this.inverseState = InverseMatrixState.singular;
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
/**
|
|
2212
|
+
* Add scaled values from `other` Matrix3d to `this` Matrix3d.
|
|
2213
|
+
* @param other Matrix3d with values to be added.
|
|
2149
2214
|
* @param scale scale factor to apply to the added values.
|
|
2150
2215
|
*/
|
|
2151
2216
|
addScaledInPlace(other, scale) {
|
|
@@ -2154,18 +2219,19 @@ export class Matrix3d {
|
|
|
2154
2219
|
this.inverseState = InverseMatrixState.unknown;
|
|
2155
2220
|
}
|
|
2156
2221
|
/**
|
|
2157
|
-
*
|
|
2158
|
-
* * The scaled outer product is a
|
|
2222
|
+
* Add scaled values from an outer product of vectors U and V.
|
|
2223
|
+
* * The scaled outer product is a matrix with `rank 1` (all columns/rows are linearly dependent).
|
|
2159
2224
|
* * This is useful in constructing mirrors and directional scales.
|
|
2160
2225
|
* ```
|
|
2161
2226
|
* equation
|
|
2162
2227
|
* A += s \columnSubXYZ{U}\rowSubXYZ{V}
|
|
2163
2228
|
* \\ \matrixXY{A} += s \begin{bmatrix}
|
|
2164
|
-
* U_x * V_x &
|
|
2165
|
-
*
|
|
2166
|
-
*
|
|
2229
|
+
* U_x * V_x & U_x * V_y & U_x * V_z \\
|
|
2230
|
+
* U_y * V_x & U_y * V_y & U_y * V_z \\
|
|
2231
|
+
* U_z * V_x & U_z * V_y & U_z * V_z \end{bmatrix}
|
|
2167
2232
|
* ```
|
|
2168
|
-
* @param
|
|
2233
|
+
* @param vectorU first vector in the outer product.
|
|
2234
|
+
* @param vectorV second vector in the outer product.
|
|
2169
2235
|
* @param scale scale factor to apply to the added values.
|
|
2170
2236
|
*/
|
|
2171
2237
|
addScaledOuterProductInPlace(vectorU, vectorV, scale) {
|
|
@@ -2180,14 +2246,6 @@ export class Matrix3d {
|
|
|
2180
2246
|
this.coffs[8] += scale * vectorU.z * vectorV.z;
|
|
2181
2247
|
this.inverseState = InverseMatrixState.unknown;
|
|
2182
2248
|
}
|
|
2183
|
-
/** create a Matrix3d whose values are uniformly scaled from this.
|
|
2184
|
-
* @param scale scale factor to apply.
|
|
2185
|
-
* @param result optional preallocated result.
|
|
2186
|
-
* @returns Return the new or repopulated matrix
|
|
2187
|
-
*/
|
|
2188
|
-
scale(scale, result) {
|
|
2189
|
-
return Matrix3d.createRowValues(this.coffs[0] * scale, this.coffs[1] * scale, this.coffs[2] * scale, this.coffs[3] * scale, this.coffs[4] * scale, this.coffs[5] * scale, this.coffs[6] * scale, this.coffs[7] * scale, this.coffs[8] * scale, result);
|
|
2190
|
-
}
|
|
2191
2249
|
/**
|
|
2192
2250
|
* Create a rigid matrix (columns and rows are unit length and pairwise perpendicular) for
|
|
2193
2251
|
* the given eye coordinate.
|
|
@@ -2210,7 +2268,6 @@ export class Matrix3d {
|
|
|
2210
2268
|
result.scaleColumnsInPlace(1.0, -1.0, -1.0);
|
|
2211
2269
|
}
|
|
2212
2270
|
else {
|
|
2213
|
-
// if coordinate is (x,y,0), i.e., Front or Back or Left or Right view
|
|
2214
2271
|
/**
|
|
2215
2272
|
* The matrix that the "else" statement creates is
|
|
2216
2273
|
* [-s -s1*c c1*c]
|
|
@@ -2240,57 +2297,56 @@ export class Matrix3d {
|
|
|
2240
2297
|
}
|
|
2241
2298
|
return result;
|
|
2242
2299
|
}
|
|
2243
|
-
/** Return the determinant of this matrix. */
|
|
2300
|
+
/** Return the determinant of `this` matrix. */
|
|
2244
2301
|
determinant() {
|
|
2245
2302
|
return this.coffs[0] * this.coffs[4] * this.coffs[8]
|
|
2246
|
-
- this.coffs[0] * this.coffs[
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
+ this.coffs[
|
|
2250
|
-
- this.coffs[
|
|
2303
|
+
- this.coffs[0] * this.coffs[5] * this.coffs[7]
|
|
2304
|
+
- this.coffs[1] * this.coffs[3] * this.coffs[8]
|
|
2305
|
+
+ this.coffs[1] * this.coffs[5] * this.coffs[6]
|
|
2306
|
+
+ this.coffs[2] * this.coffs[3] * this.coffs[7]
|
|
2307
|
+
- this.coffs[2] * this.coffs[4] * this.coffs[6];
|
|
2251
2308
|
}
|
|
2252
|
-
/**
|
|
2309
|
+
/**
|
|
2310
|
+
* Return an estimate of how independent the columns of `this` matrix are. Near zero is bad (i.e.,
|
|
2311
|
+
* columns are almost dependent and matrix is nearly singular). Near 1 is good (i.e., columns are
|
|
2312
|
+
* almost independent and matrix is invertible).
|
|
2253
2313
|
*/
|
|
2254
2314
|
conditionNumber() {
|
|
2255
2315
|
const determinant = this.determinant();
|
|
2256
|
-
const
|
|
2316
|
+
const columnMagnitudeSum = Geometry.hypotenuseXYZ(this.coffs[0], this.coffs[3], this.coffs[6])
|
|
2257
2317
|
+ Geometry.hypotenuseXYZ(this.coffs[1], this.coffs[4], this.coffs[7])
|
|
2258
2318
|
+ Geometry.hypotenuseXYZ(this.coffs[2], this.coffs[5], this.coffs[8]);
|
|
2259
|
-
return Geometry.safeDivideFraction(determinant,
|
|
2319
|
+
return Geometry.safeDivideFraction(determinant, columnMagnitudeSum, 0.0);
|
|
2260
2320
|
}
|
|
2261
2321
|
/** Return the sum of squares of all entries */
|
|
2262
2322
|
sumSquares() {
|
|
2263
|
-
let i = 0;
|
|
2264
2323
|
let sum = 0;
|
|
2265
|
-
for (i = 0; i < 9; i++)
|
|
2324
|
+
for (let i = 0; i < 9; i++)
|
|
2266
2325
|
sum += this.coffs[i] * this.coffs[i];
|
|
2267
2326
|
return sum;
|
|
2268
2327
|
}
|
|
2269
2328
|
/** Return the sum of squares of diagonal entries */
|
|
2270
2329
|
sumDiagonalSquares() {
|
|
2271
|
-
let i = 0;
|
|
2272
2330
|
let sum = 0;
|
|
2273
|
-
for (i = 0; i < 9; i += 4)
|
|
2331
|
+
for (let i = 0; i < 9; i += 4)
|
|
2274
2332
|
sum += this.coffs[i] * this.coffs[i];
|
|
2275
2333
|
return sum;
|
|
2276
2334
|
}
|
|
2277
|
-
/** Return the sum of diagonal entries
|
|
2335
|
+
/** Return the matrix `trace` (sum of diagonal entries) */
|
|
2278
2336
|
sumDiagonal() {
|
|
2279
2337
|
return this.coffs[0] + this.coffs[4] + this.coffs[8];
|
|
2280
2338
|
}
|
|
2281
2339
|
/** Return the Maximum absolute value of any single entry */
|
|
2282
2340
|
maxAbs() {
|
|
2283
|
-
let i = 0;
|
|
2284
2341
|
let max = 0;
|
|
2285
|
-
for (i = 0; i < 9; i++)
|
|
2342
|
+
for (let i = 0; i < 9; i++)
|
|
2286
2343
|
max = Math.max(max, Math.abs(this.coffs[i]));
|
|
2287
2344
|
return max;
|
|
2288
2345
|
}
|
|
2289
2346
|
/** Return the maximum absolute difference between corresponding entries of `this` and `other` */
|
|
2290
2347
|
maxDiff(other) {
|
|
2291
|
-
let i = 0;
|
|
2292
2348
|
let max = 0;
|
|
2293
|
-
for (i = 0; i < 9; i++)
|
|
2349
|
+
for (let i = 0; i < 9; i++)
|
|
2294
2350
|
max = Math.max(max, Math.abs(this.coffs[i] - other.coffs[i]));
|
|
2295
2351
|
return max;
|
|
2296
2352
|
}
|
|
@@ -2309,86 +2365,102 @@ export class Matrix3d {
|
|
|
2309
2365
|
get hasCachedInverse() {
|
|
2310
2366
|
return this.inverseState === InverseMatrixState.inverseStored && this.inverseCoffs !== undefined;
|
|
2311
2367
|
}
|
|
2312
|
-
/** Test if the below diagonal entries are all nearly zero */
|
|
2368
|
+
/** Test if the below diagonal entries (3,6,7) are all nearly zero */
|
|
2313
2369
|
get isUpperTriangular() {
|
|
2314
2370
|
const sumAll = this.sumSquares();
|
|
2315
2371
|
const sumLow = Geometry.hypotenuseSquaredXYZ(this.coffs[3], this.coffs[6], this.coffs[7]);
|
|
2316
2372
|
return Math.sqrt(sumLow) <= Geometry.smallAngleRadians * (1.0 + Math.sqrt(sumAll));
|
|
2317
2373
|
}
|
|
2318
|
-
/**
|
|
2374
|
+
/** Test if the above diagonal entries (1,2,5) are all nearly zero */
|
|
2375
|
+
get isLowerTriangular() {
|
|
2376
|
+
const sumAll = this.sumSquares();
|
|
2377
|
+
const sumLow = Geometry.hypotenuseSquaredXYZ(this.coffs[1], this.coffs[2], this.coffs[75]);
|
|
2378
|
+
return Math.sqrt(sumLow) <= Geometry.smallAngleRadians * (1.0 + Math.sqrt(sumAll));
|
|
2379
|
+
}
|
|
2380
|
+
/**
|
|
2381
|
+
* If the matrix is diagonal and all diagonals are almost equal, return the first diagonal (entry 0
|
|
2382
|
+
* which is same as entry 4 and 8). Otherwise return `undefined`.
|
|
2319
2383
|
*/
|
|
2320
2384
|
sameDiagonalScale() {
|
|
2321
2385
|
const sumAll = this.sumSquares();
|
|
2322
2386
|
const sumDiagonal = this.sumDiagonalSquares();
|
|
2323
2387
|
const sumOff = Math.abs(sumAll - sumDiagonal);
|
|
2324
2388
|
if (Math.sqrt(sumOff) <= Geometry.smallAngleRadians * (1.0 + Math.sqrt(sumAll))
|
|
2325
|
-
&& Geometry.isSameCoordinate(this.coffs[0], this.coffs[4])
|
|
2389
|
+
&& Geometry.isSameCoordinate(this.coffs[0], this.coffs[4])
|
|
2390
|
+
&& Geometry.isSameCoordinate(this.coffs[0], this.coffs[8]))
|
|
2326
2391
|
return this.coffs[0];
|
|
2327
2392
|
return undefined;
|
|
2328
2393
|
}
|
|
2329
|
-
/** Sum of squared differences between symmetric pairs */
|
|
2394
|
+
/** Sum of squared differences between symmetric pairs (entry 1 and 3 - 2 and 6 - 5 and 7) */
|
|
2330
2395
|
sumSkewSquares() {
|
|
2331
2396
|
return Geometry.hypotenuseSquaredXYZ(this.coffs[1] - this.coffs[3], this.coffs[2] - this.coffs[6], this.coffs[5] - this.coffs[7]);
|
|
2332
2397
|
}
|
|
2333
|
-
/**
|
|
2334
|
-
*
|
|
2398
|
+
/**
|
|
2399
|
+
* Test if all rows and columns are unit length and are perpendicular to each other, i.e., the matrix is either
|
|
2400
|
+
* a `pure rotation` (determinant is +1) or is a `mirror` (determinant is -1).
|
|
2401
|
+
* * **Note:** such a matrix is called `orthogonal` and its inverse is its transpose.
|
|
2402
|
+
*/
|
|
2403
|
+
testPerpendicularUnitRowsAndColumns() {
|
|
2404
|
+
const product = this.multiplyMatrixMatrixTranspose(this);
|
|
2405
|
+
return product.isIdentity;
|
|
2406
|
+
}
|
|
2407
|
+
/**
|
|
2408
|
+
* Test if the matrix is a `rigid` matrix (or `pure rotation`, i.e., columns and rows are unit length and
|
|
2409
|
+
* pairwise perpendicular and determinant is +1).
|
|
2410
|
+
* @param allowMirror whether to widen the test to return true if the matrix is a `mirror` (determinant is -1).
|
|
2335
2411
|
*/
|
|
2336
2412
|
isRigid(allowMirror = false) {
|
|
2337
2413
|
return this.testPerpendicularUnitRowsAndColumns() && (allowMirror || this.determinant() > 0);
|
|
2338
2414
|
}
|
|
2339
|
-
/**
|
|
2340
|
-
*
|
|
2341
|
-
*
|
|
2342
|
-
*
|
|
2415
|
+
/**
|
|
2416
|
+
* Test if all rows and columns are perpendicular to each other and have equal length.
|
|
2417
|
+
* If so, the length (or its negative) is the `scale` factor from a set of `orthonormal axes` to
|
|
2418
|
+
* the set of axes created by columns of `this` matrix. Otherwise, returns `undefined`.
|
|
2419
|
+
* @returns returns `{ rigidAxes, scale }` where `rigidAxes` is a Matrix3d with its columns as the rigid axes
|
|
2420
|
+
* (with the scale factor removed) and `scale` is the scale factor.
|
|
2421
|
+
* * Note that determinant of a rigid matrix is +1.
|
|
2422
|
+
* * The context for this method is to determine if the matrix is the product a `rotation` matrix and a uniform
|
|
2423
|
+
* `scale` matrix (diagonal matrix with all diagonal entries the same nonzero number).
|
|
2343
2424
|
*/
|
|
2344
2425
|
factorRigidWithSignedScale() {
|
|
2345
2426
|
const product = this.multiplyMatrixMatrixTranspose(this);
|
|
2346
|
-
const
|
|
2347
|
-
if (
|
|
2427
|
+
const scaleSquare = product.sameDiagonalScale();
|
|
2428
|
+
if (scaleSquare === undefined || scaleSquare <= 0.0)
|
|
2348
2429
|
return undefined;
|
|
2349
|
-
const
|
|
2350
|
-
const
|
|
2351
|
-
const result = { rigidAxes: this.scaleColumns(
|
|
2430
|
+
const scale = this.determinant() > 0 ? Math.sqrt(scaleSquare) : -Math.sqrt(scaleSquare);
|
|
2431
|
+
const scaleInverse = 1.0 / scale;
|
|
2432
|
+
const result = { rigidAxes: this.scaleColumns(scaleInverse, scaleInverse, scaleInverse), scale };
|
|
2352
2433
|
return result;
|
|
2353
2434
|
}
|
|
2354
|
-
/** Test if
|
|
2435
|
+
/** Test if `this` matrix reorders and/or negates the columns of the `identity` matrix. */
|
|
2355
2436
|
get isSignedPermutation() {
|
|
2356
2437
|
let count = 0;
|
|
2357
2438
|
for (let row = 0; row < 3; row++)
|
|
2358
2439
|
for (let col = 0; col < 3; col++) {
|
|
2359
2440
|
const q = this.at(row, col);
|
|
2360
|
-
if (q === 0) {
|
|
2441
|
+
if (q === 0) {
|
|
2442
|
+
// do nothing
|
|
2361
2443
|
}
|
|
2362
2444
|
else if (q === 1 || q === -1) {
|
|
2363
|
-
// the rest of this row and column should be 0.
|
|
2364
|
-
// "at" will apply cyclic indexing.
|
|
2365
2445
|
count++;
|
|
2366
|
-
if
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
return false;
|
|
2370
|
-
if (this.at(row, col + 1) !== 0)
|
|
2371
|
-
return false;
|
|
2372
|
-
if (this.at(row, col + 2) !== 0)
|
|
2446
|
+
// if the rest of this row and column should be 0 ("at" will apply cyclic indexing)
|
|
2447
|
+
if ((this.at(row + 1, col) !== 0) || (this.at(row + 2, col) !== 0) ||
|
|
2448
|
+
(this.at(row, col + 1) !== 0) || (this.at(row, col + 2) !== 0))
|
|
2373
2449
|
return false;
|
|
2374
2450
|
}
|
|
2375
|
-
else { // entry is not
|
|
2451
|
+
else { // entry is not 0, 1, or -1
|
|
2376
2452
|
return false;
|
|
2377
2453
|
}
|
|
2378
2454
|
}
|
|
2379
2455
|
return count === 3;
|
|
2380
2456
|
}
|
|
2381
|
-
/**
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
/** Adjust the matrix in place so that:
|
|
2387
|
-
* * columns are perpendicular and have unit length
|
|
2388
|
-
* * transpose equals inverse
|
|
2389
|
-
* * mirroring is removed
|
|
2457
|
+
/**
|
|
2458
|
+
* Adjust the matrix in place to make is a `rigid` matrix so that:
|
|
2459
|
+
* * columns are perpendicular and have unit length.
|
|
2460
|
+
* * transpose equals inverse.
|
|
2461
|
+
* * mirroring is removed.
|
|
2390
2462
|
* @param axisOrder how to reorder the matrix columns
|
|
2391
|
-
* @return whether the
|
|
2463
|
+
* @return whether the adjusted matrix is `rigid` on return
|
|
2392
2464
|
*/
|
|
2393
2465
|
makeRigid(axisOrder = AxisOrder.XYZ) {
|
|
2394
2466
|
const maxAbs = this.maxAbs();
|
|
@@ -2409,22 +2481,13 @@ export class Matrix3d {
|
|
|
2409
2481
|
return result;
|
|
2410
2482
|
return undefined;
|
|
2411
2483
|
}
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
}
|
|
2420
|
-
else {
|
|
2421
|
-
coff = numerator * reciprocal;
|
|
2422
|
-
}
|
|
2423
|
-
return coff;
|
|
2424
|
-
}
|
|
2425
|
-
/** create a matrix from a quaternion.
|
|
2426
|
-
* **WARNING:** There is frequent confusion over whether a "from quaternion" matrix is organized by rows and columns.
|
|
2427
|
-
* **WARNING:** If you find that the matrix seems to rotate by the opposite angle expect it, transpose it.
|
|
2484
|
+
/**
|
|
2485
|
+
* Create a matrix from a quaternion.
|
|
2486
|
+
* **WARNING:** There is frequent confusion over whether a "from quaternion" matrix is organized by
|
|
2487
|
+
* rows or columns. If you find that the matrix seems to rotate by the opposite angle, transpose it.
|
|
2488
|
+
*
|
|
2489
|
+
* Some math details can be found at
|
|
2490
|
+
* http://marc-b-reynolds.github.io/quaternions/2017/08/08/QuatRotMatrix.html
|
|
2428
2491
|
*/
|
|
2429
2492
|
static createFromQuaternion(quat) {
|
|
2430
2493
|
const qqx = quat.x * quat.x;
|
|
@@ -2437,31 +2500,57 @@ export class Matrix3d {
|
|
|
2437
2500
|
}
|
|
2438
2501
|
else {
|
|
2439
2502
|
const a = 1.0 / mag2;
|
|
2440
|
-
const matrix = Matrix3d.createRowValues(
|
|
2503
|
+
const matrix = Matrix3d.createRowValues(
|
|
2504
|
+
// first row
|
|
2505
|
+
a * (qqw + qqx - qqy - qqz), 2.0 * a * (quat.w * quat.z + quat.x * quat.y), 2.0 * a * (quat.x * quat.z - quat.w * quat.y),
|
|
2506
|
+
// second row
|
|
2507
|
+
2.0 * a * (quat.x * quat.y - quat.w * quat.z), a * (qqw - qqx + qqy - qqz), 2.0 * a * (quat.w * quat.x + quat.y * quat.z),
|
|
2508
|
+
// third row
|
|
2509
|
+
2.0 * a * (quat.x * quat.z + quat.w * quat.y), 2.0 * a * (quat.y * quat.z - quat.w * quat.x), a * (qqw - qqx - qqy + qqz));
|
|
2441
2510
|
return matrix;
|
|
2442
2511
|
}
|
|
2443
2512
|
}
|
|
2444
|
-
/** convert
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2513
|
+
/** Calculate quaternion terms used to convert matrix to a quaternion */
|
|
2514
|
+
static computeQuatTerm(numerator, denomCoff, reciprocal, diagSum) {
|
|
2515
|
+
let coff;
|
|
2516
|
+
const diagTol = 0.500;
|
|
2517
|
+
if (diagSum > diagTol) {
|
|
2518
|
+
coff = 0.5 * Math.sqrt(diagSum);
|
|
2519
|
+
if (denomCoff * numerator < 0.0)
|
|
2520
|
+
coff = -coff;
|
|
2521
|
+
}
|
|
2522
|
+
else {
|
|
2523
|
+
coff = numerator * reciprocal;
|
|
2524
|
+
}
|
|
2525
|
+
return coff;
|
|
2526
|
+
}
|
|
2527
|
+
/**
|
|
2528
|
+
* Create `this` matrix to a quaternion.
|
|
2529
|
+
* **Note:** This calculation requires `this` matrix to have unit length rows and columns.
|
|
2530
|
+
* **WARNING:** There is frequent confusion over whether a "from quaternion" matrix is organized by
|
|
2531
|
+
* rows or columns. If you find that the matrix seems to rotate by the opposite angle, transpose it.
|
|
2532
|
+
*
|
|
2533
|
+
* Some math details can be found at
|
|
2534
|
+
* http://marc-b-reynolds.github.io/quaternions/2017/08/08/QuatRotMatrix.html
|
|
2448
2535
|
*/
|
|
2449
2536
|
toQuaternion() {
|
|
2450
2537
|
const result = Point4d.createZero();
|
|
2451
|
-
const props = [
|
|
2538
|
+
const props = [
|
|
2539
|
+
[this.coffs[0], this.coffs[3], this.coffs[6]],
|
|
2452
2540
|
[this.coffs[1], this.coffs[4], this.coffs[7]],
|
|
2453
|
-
[this.coffs[2], this.coffs[5], this.coffs[8]]
|
|
2541
|
+
[this.coffs[2], this.coffs[5], this.coffs[8]],
|
|
2542
|
+
];
|
|
2454
2543
|
const xx = props[0][0];
|
|
2455
2544
|
const yy = props[1][1];
|
|
2456
2545
|
const zz = props[2][2];
|
|
2457
2546
|
const dSum = [];
|
|
2458
|
-
let denom, maxIndex, i;
|
|
2459
2547
|
dSum[0] = 1.0 + xx - yy - zz;
|
|
2460
2548
|
dSum[1] = 1.0 - xx + yy - zz;
|
|
2461
2549
|
dSum[2] = 1.0 - xx - yy + zz;
|
|
2462
2550
|
dSum[3] = 1.0 + xx + yy + zz;
|
|
2463
|
-
|
|
2464
|
-
|
|
2551
|
+
let denom;
|
|
2552
|
+
let maxIndex = 0;
|
|
2553
|
+
for (let i = 1; i <= 3; i++) {
|
|
2465
2554
|
if (dSum[i] > dSum[maxIndex])
|
|
2466
2555
|
maxIndex = i;
|
|
2467
2556
|
}
|