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