@itwin/core-geometry 4.0.0-dev.6 → 4.0.0-dev.8
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 +3 -3
- package/lib/cjs/Geometry.d.ts.map +1 -1
- package/lib/cjs/Geometry.js +27 -11
- package/lib/cjs/Geometry.js.map +1 -1
- package/lib/cjs/curve/CurveCurve.d.ts +11 -8
- package/lib/cjs/curve/CurveCurve.d.ts.map +1 -1
- package/lib/cjs/curve/CurveCurve.js +16 -12
- package/lib/cjs/curve/CurveCurve.js.map +1 -1
- package/lib/cjs/curve/CurveCurveIntersectXY.d.ts +5 -1
- package/lib/cjs/curve/CurveCurveIntersectXY.d.ts.map +1 -1
- package/lib/cjs/curve/CurveCurveIntersectXY.js +11 -10
- package/lib/cjs/curve/CurveCurveIntersectXY.js.map +1 -1
- package/lib/cjs/geometry3d/Angle.d.ts +18 -0
- package/lib/cjs/geometry3d/Angle.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Angle.js +38 -0
- package/lib/cjs/geometry3d/Angle.js.map +1 -1
- package/lib/cjs/geometry3d/CoincidentGeometryOps.d.ts +1 -0
- package/lib/cjs/geometry3d/CoincidentGeometryOps.d.ts.map +1 -1
- package/lib/cjs/geometry3d/CoincidentGeometryOps.js +3 -0
- package/lib/cjs/geometry3d/CoincidentGeometryOps.js.map +1 -1
- package/lib/cjs/geometry3d/Matrix3d.d.ts +171 -118
- package/lib/cjs/geometry3d/Matrix3d.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Matrix3d.js +448 -417
- package/lib/cjs/geometry3d/Matrix3d.js.map +1 -1
- package/lib/cjs/geometry3d/Point3dVector3d.d.ts +12 -13
- package/lib/cjs/geometry3d/Point3dVector3d.d.ts.map +1 -1
- package/lib/cjs/geometry3d/Point3dVector3d.js +15 -13
- package/lib/cjs/geometry3d/Point3dVector3d.js.map +1 -1
- package/lib/cjs/geometry3d/Segment1d.d.ts +1 -1
- package/lib/cjs/geometry3d/Segment1d.js +1 -1
- package/lib/cjs/geometry3d/Segment1d.js.map +1 -1
- package/lib/cjs/numerics/Polynomials.d.ts +12 -0
- package/lib/cjs/numerics/Polynomials.d.ts.map +1 -1
- package/lib/cjs/numerics/Polynomials.js +14 -0
- package/lib/cjs/numerics/Polynomials.js.map +1 -1
- package/lib/cjs/polyface/PolyfaceBuilder.d.ts +1 -0
- package/lib/cjs/polyface/PolyfaceBuilder.d.ts.map +1 -1
- package/lib/cjs/polyface/PolyfaceBuilder.js +46 -6
- package/lib/cjs/polyface/PolyfaceBuilder.js.map +1 -1
- package/lib/cjs/polyface/PolyfaceQuery.d.ts +54 -0
- package/lib/cjs/polyface/PolyfaceQuery.d.ts.map +1 -1
- package/lib/cjs/polyface/PolyfaceQuery.js +71 -1
- package/lib/cjs/polyface/PolyfaceQuery.js.map +1 -1
- package/lib/cjs/polyface/multiclip/OffsetMeshContext.d.ts +202 -0
- package/lib/cjs/polyface/multiclip/OffsetMeshContext.d.ts.map +1 -0
- package/lib/cjs/polyface/multiclip/OffsetMeshContext.js +1038 -0
- package/lib/cjs/polyface/multiclip/OffsetMeshContext.js.map +1 -0
- package/lib/cjs/serialization/GeometrySamples.d.ts +4 -1
- package/lib/cjs/serialization/GeometrySamples.d.ts.map +1 -1
- package/lib/cjs/serialization/GeometrySamples.js +14 -6
- package/lib/cjs/serialization/GeometrySamples.js.map +1 -1
- package/lib/cjs/topology/Graph.d.ts +113 -7
- package/lib/cjs/topology/Graph.d.ts.map +1 -1
- package/lib/cjs/topology/Graph.js +185 -7
- package/lib/cjs/topology/Graph.js.map +1 -1
- package/lib/cjs/topology/HalfEdgeGraphFromIndexedLoopsContext.d.ts +38 -0
- package/lib/cjs/topology/HalfEdgeGraphFromIndexedLoopsContext.d.ts.map +1 -0
- package/lib/cjs/topology/HalfEdgeGraphFromIndexedLoopsContext.js +82 -0
- package/lib/cjs/topology/HalfEdgeGraphFromIndexedLoopsContext.js.map +1 -0
- package/lib/esm/Geometry.d.ts +3 -3
- package/lib/esm/Geometry.d.ts.map +1 -1
- package/lib/esm/Geometry.js +27 -11
- package/lib/esm/Geometry.js.map +1 -1
- package/lib/esm/curve/CurveCurve.d.ts +11 -8
- package/lib/esm/curve/CurveCurve.d.ts.map +1 -1
- package/lib/esm/curve/CurveCurve.js +16 -12
- package/lib/esm/curve/CurveCurve.js.map +1 -1
- package/lib/esm/curve/CurveCurveIntersectXY.d.ts +5 -1
- package/lib/esm/curve/CurveCurveIntersectXY.d.ts.map +1 -1
- package/lib/esm/curve/CurveCurveIntersectXY.js +11 -10
- package/lib/esm/curve/CurveCurveIntersectXY.js.map +1 -1
- package/lib/esm/geometry3d/Angle.d.ts +18 -0
- package/lib/esm/geometry3d/Angle.d.ts.map +1 -1
- package/lib/esm/geometry3d/Angle.js +38 -0
- package/lib/esm/geometry3d/Angle.js.map +1 -1
- package/lib/esm/geometry3d/CoincidentGeometryOps.d.ts +1 -0
- package/lib/esm/geometry3d/CoincidentGeometryOps.d.ts.map +1 -1
- package/lib/esm/geometry3d/CoincidentGeometryOps.js +3 -0
- package/lib/esm/geometry3d/CoincidentGeometryOps.js.map +1 -1
- package/lib/esm/geometry3d/Matrix3d.d.ts +171 -118
- package/lib/esm/geometry3d/Matrix3d.d.ts.map +1 -1
- package/lib/esm/geometry3d/Matrix3d.js +448 -417
- package/lib/esm/geometry3d/Matrix3d.js.map +1 -1
- package/lib/esm/geometry3d/Point3dVector3d.d.ts +12 -13
- package/lib/esm/geometry3d/Point3dVector3d.d.ts.map +1 -1
- package/lib/esm/geometry3d/Point3dVector3d.js +15 -13
- package/lib/esm/geometry3d/Point3dVector3d.js.map +1 -1
- package/lib/esm/geometry3d/Segment1d.d.ts +1 -1
- package/lib/esm/geometry3d/Segment1d.js +1 -1
- package/lib/esm/geometry3d/Segment1d.js.map +1 -1
- package/lib/esm/numerics/Polynomials.d.ts +12 -0
- package/lib/esm/numerics/Polynomials.d.ts.map +1 -1
- package/lib/esm/numerics/Polynomials.js +14 -0
- package/lib/esm/numerics/Polynomials.js.map +1 -1
- package/lib/esm/polyface/PolyfaceBuilder.d.ts +1 -0
- package/lib/esm/polyface/PolyfaceBuilder.d.ts.map +1 -1
- package/lib/esm/polyface/PolyfaceBuilder.js +46 -6
- package/lib/esm/polyface/PolyfaceBuilder.js.map +1 -1
- package/lib/esm/polyface/PolyfaceQuery.d.ts +54 -0
- package/lib/esm/polyface/PolyfaceQuery.d.ts.map +1 -1
- package/lib/esm/polyface/PolyfaceQuery.js +69 -0
- package/lib/esm/polyface/PolyfaceQuery.js.map +1 -1
- package/lib/esm/polyface/multiclip/OffsetMeshContext.d.ts +202 -0
- package/lib/esm/polyface/multiclip/OffsetMeshContext.d.ts.map +1 -0
- package/lib/esm/polyface/multiclip/OffsetMeshContext.js +1032 -0
- package/lib/esm/polyface/multiclip/OffsetMeshContext.js.map +1 -0
- package/lib/esm/serialization/GeometrySamples.d.ts +4 -1
- package/lib/esm/serialization/GeometrySamples.d.ts.map +1 -1
- package/lib/esm/serialization/GeometrySamples.js +14 -6
- package/lib/esm/serialization/GeometrySamples.js.map +1 -1
- package/lib/esm/topology/Graph.d.ts +113 -7
- package/lib/esm/topology/Graph.d.ts.map +1 -1
- package/lib/esm/topology/Graph.js +185 -7
- package/lib/esm/topology/Graph.js.map +1 -1
- package/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.d.ts +38 -0
- package/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.d.ts.map +1 -0
- package/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js +78 -0
- package/lib/esm/topology/HalfEdgeGraphFromIndexedLoopsContext.js.map +1 -0
- package/package.json +4 -4
|
@@ -15,6 +15,7 @@ const Point2dVector2d_1 = require("./Point2dVector2d");
|
|
|
15
15
|
const Point3dVector3d_1 = require("./Point3dVector3d");
|
|
16
16
|
const Transform_1 = require("./Transform");
|
|
17
17
|
/* eslint-disable @itwin/prefer-get */
|
|
18
|
+
// cSpell:words XXYZ YXYZ ZXYZ
|
|
18
19
|
/**
|
|
19
20
|
* PackedMatrix3dOps contains static methods for matrix operations where the matrix is a Float64Array.
|
|
20
21
|
* * The Float64Array contains the matrix entries in row-major order
|
|
@@ -643,7 +644,8 @@ class Matrix3d {
|
|
|
643
644
|
return undefined;
|
|
644
645
|
}
|
|
645
646
|
/**
|
|
646
|
-
* Construct a rigid matrix using vectorA and its 2 perpendicular.
|
|
647
|
+
* Construct a rigid matrix (orthogonal matrix with +1 determinant) using vectorA and its 2 perpendicular.
|
|
648
|
+
* * If axisOrder is not passed then `AxisOrder = AxisOrder.ZXY` is used as default.
|
|
647
649
|
* * This function internally uses createPerpendicularVectorFavorXYPlane and createRigidFromColumns.
|
|
648
650
|
*/
|
|
649
651
|
static createRigidHeadsUp(vectorA, axisOrder = Geometry_1.AxisOrder.ZXY, result) {
|
|
@@ -655,7 +657,7 @@ class Matrix3d {
|
|
|
655
657
|
}
|
|
656
658
|
return Matrix3d.createIdentity(result);
|
|
657
659
|
}
|
|
658
|
-
/** Return the matrix for rotation of `angle` around `axis` */
|
|
660
|
+
/** Return the matrix for rotation of `angle` around desired `axis` */
|
|
659
661
|
static createRotationAroundVector(axis, angle, result) {
|
|
660
662
|
// Rodriguez formula (matrix form), https://mathworld.wolfram.com/RodriguesRotationFormula.html
|
|
661
663
|
const c = angle.cos();
|
|
@@ -669,7 +671,7 @@ class Matrix3d {
|
|
|
669
671
|
}
|
|
670
672
|
return undefined;
|
|
671
673
|
}
|
|
672
|
-
/** Returns a rotation of specified angle around
|
|
674
|
+
/** Returns a rotation of specified angle around one of the main axis (X,Y,Z).
|
|
673
675
|
* @param axisIndex index of axis (AxisIndex.X, AxisIndex.Y, AxisIndex.Z) kept fixed by the rotation.
|
|
674
676
|
* @param angle angle of rotation
|
|
675
677
|
* @param result optional result matrix.
|
|
@@ -692,14 +694,33 @@ class Matrix3d {
|
|
|
692
694
|
return myResult;
|
|
693
695
|
}
|
|
694
696
|
/**
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
697
|
+
* Replace current rows Ui and Uj with (c*Ui + s*Uj) and (c*Uj - s*Ui).
|
|
698
|
+
* * There is no checking for i,j being 0,1,2.
|
|
699
|
+
* @param i first row index. **must be 0,1,2** (unchecked)
|
|
700
|
+
* @param j second row index. **must be 0,1,2** (unchecked)
|
|
701
|
+
* @param c fist coefficient
|
|
702
|
+
* @param s second coefficient
|
|
703
|
+
*/
|
|
704
|
+
applyGivensRowOp(i, j, c, s) {
|
|
705
|
+
let ii = 3 * i;
|
|
706
|
+
let jj = 3 * j;
|
|
707
|
+
const limit = ii + 3;
|
|
708
|
+
for (; ii < limit; ii++, jj++) {
|
|
709
|
+
const a = this.coffs[ii];
|
|
710
|
+
const b = this.coffs[jj];
|
|
711
|
+
this.coffs[ii] = a * c + b * s;
|
|
712
|
+
this.coffs[jj] = -a * s + b * c;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Replace current columns Ui and Uj with (c*Ui + s*Uj) and (c*Uj - s*Ui).
|
|
717
|
+
* * There is no checking for i,j being 0,1,2.
|
|
718
|
+
* * This is used in compute intensive inner loops
|
|
719
|
+
* @param i first row index. **must be 0,1,2** (unchecked)
|
|
720
|
+
* @param j second row index. **must be 0,1,2** (unchecked)
|
|
721
|
+
* @param c fist coefficient
|
|
722
|
+
* @param s second coefficient
|
|
723
|
+
*/
|
|
703
724
|
applyGivensColumnOp(i, j, c, s) {
|
|
704
725
|
const limit = i + 9;
|
|
705
726
|
for (; i < limit; i += 3, j += 3) {
|
|
@@ -710,12 +731,12 @@ class Matrix3d {
|
|
|
710
731
|
}
|
|
711
732
|
}
|
|
712
733
|
/**
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
734
|
+
* Create a matrix from column vectors.
|
|
735
|
+
* ```
|
|
736
|
+
* equation
|
|
737
|
+
* \begin{bmatrix}U_x & V_x & W_x \\ U_y & V_y & W_y \\ U_z & V_z & W_z \end{bmatrix}
|
|
738
|
+
* ```
|
|
739
|
+
*/
|
|
719
740
|
static createColumns(vectorU, vectorV, vectorW, result) {
|
|
720
741
|
return Matrix3d.createRowValues(vectorU.x, vectorV.x, vectorW.x, vectorU.y, vectorV.y, vectorW.y, vectorU.z, vectorV.z, vectorW.z, result);
|
|
721
742
|
}
|
|
@@ -732,8 +753,9 @@ class Matrix3d {
|
|
|
732
753
|
* * ColumnX points in the rightVector direction
|
|
733
754
|
* * ColumnY points in the upVector direction
|
|
734
755
|
* * ColumnZ is a unit cross product of ColumnX and ColumnY.
|
|
735
|
-
* * Optionally rotate
|
|
736
|
-
* * Optionally rotate
|
|
756
|
+
* * Optionally rotate by 45 degrees around `upVector` to bring its left or right vertical edge to center.
|
|
757
|
+
* * Optionally rotate by arctan(1/sqrt(2)) ~ 35.264 degrees around `rightVector` to bring the top or bottom
|
|
758
|
+
* horizontal edge of the view to the center (for isometric views).
|
|
737
759
|
* * This is expected to be used with various principal unit vectors that are perpendicular to each other.
|
|
738
760
|
* * STANDARD TOP VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitY(), 0, 0)
|
|
739
761
|
* * STANDARD FRONT VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitZ(), 0, 0)
|
|
@@ -741,16 +763,20 @@ class Matrix3d {
|
|
|
741
763
|
* * STANDARD RIGHT VIEW: createViewedAxes(Vector3d.unitY(), Vector3d.unitZ(), 0, 0)
|
|
742
764
|
* * STANDARD LEFT VIEW: createViewedAxes(Vector3d.unitY(-1), Vector3d.unitZ(), 0, 0)
|
|
743
765
|
* * STANDARD BOTTOM VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitY(-1), 0, 0)
|
|
766
|
+
* * STANDARD ISO VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitZ(), -1, 1)
|
|
767
|
+
* * STANDARD RIGHT ISO VIEW: createViewedAxes(Vector3d.unitX(), Vector3d.unitZ(), 1, 1)
|
|
768
|
+
* * Front, right, back, left, top, and bottom standard views are views from faces of the cube
|
|
769
|
+
* and iso and right iso standard views are views from corners of the cube.
|
|
744
770
|
* * Note: createViewedAxes is column-based so always returns local to world
|
|
745
771
|
*
|
|
746
772
|
* @param rightVector ColumnX of the returned matrix. Expected to be perpendicular to upVector.
|
|
747
773
|
* @param upVector ColumnY of the returned matrix. Expected to be perpendicular to rightVector.
|
|
748
|
-
* @param leftNoneRight Specifies the ccw rotation around
|
|
749
|
-
* "-1" indicates rotation by 45 degrees to bring the left vertical edge to center, "0" means no rotation,
|
|
774
|
+
* @param leftNoneRight Specifies the ccw rotation around `upVector` axis. Normally one of "-1", "0", and "1",
|
|
775
|
+
* where "-1" indicates rotation by 45 degrees to bring the left vertical edge to center, "0" means no rotation,
|
|
750
776
|
* and "1" indicates rotation by 45 degrees to bring the right vertical edge to center. Other numbers are
|
|
751
777
|
* used as multiplier for this 45 degree rotation.
|
|
752
|
-
* @param topNoneBottom Specifies the ccw rotation around
|
|
753
|
-
* "-1" indicates isometric rotation (35.264 degrees) to bring the bottom upward, "0" means no rotation,
|
|
778
|
+
* @param topNoneBottom Specifies the ccw rotation around `rightVector` axis. Normally one of "-1", "0", and "1",
|
|
779
|
+
* where "-1" indicates isometric rotation (35.264 degrees) to bring the bottom upward, "0" means no rotation,
|
|
754
780
|
* and "1" indicates isometric rotation (35.264 degrees) to bring the top downward. Other numbers are
|
|
755
781
|
* used as multiplier for the 35.264 degree rotation.
|
|
756
782
|
* @returns matrix = [rightVector, upVector, rightVector cross upVector] with the applied rotations specified
|
|
@@ -788,9 +814,11 @@ class Matrix3d {
|
|
|
788
814
|
* * Default is TOP view (`local X = world X`, `local Y = world Y`, `local Z = world Z`).
|
|
789
815
|
* * To change view from the TOP to one of the other 7 standard views, we need to multiply "world data" to
|
|
790
816
|
* the corresponding matrix1 provided by `createStandardWorldToView(index, false)` and then
|
|
791
|
-
* `matrix1.multiply(world data)` will
|
|
817
|
+
* `matrix1.multiply(world data)` will return "local data".
|
|
792
818
|
* * To change view back to the TOP, we need to multiply "local data" to the corresponding matrix2 provided
|
|
793
819
|
* by `createStandardWorldToView(index, true)` and then `matrix2.multiply(local data)` will returns "world data".
|
|
820
|
+
* * Note: No matter how you rotate the world axis, local X is always pointing right, local Y is always pointing up,
|
|
821
|
+
* and local Z is always pointing toward you.
|
|
794
822
|
*
|
|
795
823
|
* @param index standard view index `StandardViewIndex.Top, Bottom, Left, Right, Front, Back, Iso, RightIso`
|
|
796
824
|
* @param invert if false (default), the return matrix is world to local (view) and if true, the the return
|
|
@@ -799,343 +827,182 @@ class Matrix3d {
|
|
|
799
827
|
*/
|
|
800
828
|
static createStandardWorldToView(index, invert = false, result) {
|
|
801
829
|
switch (index) {
|
|
802
|
-
//
|
|
830
|
+
// Start with TOP view, ccw rotation by 180 degrees around X
|
|
803
831
|
case Geometry_1.StandardViewIndex.Bottom:
|
|
804
832
|
result = Matrix3d.createRowValues(1, 0, 0, 0, -1, 0, 0, 0, -1);
|
|
805
833
|
break;
|
|
806
|
-
//
|
|
834
|
+
// Start with TOP view, ccw rotation by -90 degrees around X and by 90 degrees around Z
|
|
807
835
|
case Geometry_1.StandardViewIndex.Left:
|
|
808
836
|
result = Matrix3d.createRowValues(0, -1, 0, 0, 0, 1, -1, 0, 0);
|
|
809
837
|
break;
|
|
810
|
-
//
|
|
838
|
+
// Start with TOP view, ccw rotation by -90 degrees around X and by -90 degrees around Z
|
|
811
839
|
case Geometry_1.StandardViewIndex.Right:
|
|
812
840
|
result = Matrix3d.createRowValues(0, 1, 0, 0, 0, 1, 1, 0, 0);
|
|
813
841
|
break;
|
|
814
|
-
//
|
|
842
|
+
// Start with TOP view, ccw rotation by -90 degrees around X
|
|
815
843
|
case Geometry_1.StandardViewIndex.Front:
|
|
816
844
|
result = Matrix3d.createRowValues(1, 0, 0, 0, 0, 1, 0, -1, 0);
|
|
817
845
|
break;
|
|
818
|
-
//
|
|
846
|
+
// Start with TOP view, ccw rotation by -90 degrees around X and by 180 degrees around Z
|
|
819
847
|
case Geometry_1.StandardViewIndex.Back:
|
|
820
848
|
result = Matrix3d.createRowValues(-1, 0, 0, 0, 0, 1, 0, 1, 0);
|
|
821
849
|
break;
|
|
850
|
+
/**
|
|
851
|
+
* Isometric view
|
|
852
|
+
* Start with FRONT view, ccw rotation by -45 degrees around Y and by arctan(1/sqrt(2)) ~ 35.264 degrees around X
|
|
853
|
+
* cos(45) = 1/sqrt(2) = 0.70710678118 and sin(45) = 1/sqrt(2) = 0.70710678118
|
|
854
|
+
* cos(35.264) = 2/sqrt(6) = 0.81649658092 and sin(35.264) = 1/sqrt(3) = 0.57735026919
|
|
855
|
+
* More info: https://en.wikipedia.org/wiki/Isometric_projection
|
|
856
|
+
*/
|
|
822
857
|
case Geometry_1.StandardViewIndex.Iso:
|
|
823
|
-
// start with FRONT view, ccw rotation by -45 degrees around Y and by 35.264 degrees around X
|
|
824
858
|
result = Matrix3d.createRowValues(0.707106781186548, -0.70710678118654757, 0.00000000000000000, 0.408248290463863, 0.40824829046386302, 0.81649658092772603, -0.577350269189626, -0.57735026918962573, 0.57735026918962573);
|
|
825
859
|
break;
|
|
860
|
+
// Start with FRONT view, ccw rotation by 45 degrees around Y and by 35.264 degrees around X
|
|
826
861
|
case Geometry_1.StandardViewIndex.RightIso:
|
|
827
862
|
result = Matrix3d.createRowValues(0.707106781186548, 0.70710678118654757, 0.00000000000000000, -0.408248290463863, 0.40824829046386302, 0.81649658092772603, 0.577350269189626, -0.57735026918962573, 0.57735026918962573);
|
|
828
863
|
break;
|
|
829
|
-
|
|
864
|
+
// no rotation
|
|
865
|
+
case Geometry_1.StandardViewIndex.Top:
|
|
830
866
|
default:
|
|
831
867
|
result = Matrix3d.createIdentity(result);
|
|
832
868
|
}
|
|
833
869
|
if (invert)
|
|
834
|
-
result.transposeInPlace();
|
|
870
|
+
result.transposeInPlace(); // matrix is rigid so transpose and inverse are the same
|
|
835
871
|
return result;
|
|
836
872
|
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
return result
|
|
902
|
-
}
|
|
903
|
-
*/
|
|
873
|
+
/**
|
|
874
|
+
* Apply (in place) a jacobi update that zeros out this.at(i,j).
|
|
875
|
+
* @param i row index of zeroed member
|
|
876
|
+
* @param j column index of zeroed member
|
|
877
|
+
* @param k other row/column index (different from i and j)
|
|
878
|
+
* @param leftEigenVectors a matrix that its columns will be filled by eigenvectors of this Matrix3d
|
|
879
|
+
* (allocated by caller, computed and filled by this function)
|
|
880
|
+
*/
|
|
881
|
+
applyFastSymmetricJacobiUpdate(i, j, k, leftEigenVectors) {
|
|
882
|
+
const indexII = 4 * i;
|
|
883
|
+
const indexJJ = 4 * j;
|
|
884
|
+
const indexIJ = 3 * i + j;
|
|
885
|
+
const indexIK = 3 * i + k;
|
|
886
|
+
const indexJK = 3 * j + k;
|
|
887
|
+
const dotUU = this.coffs[indexII];
|
|
888
|
+
const dotVV = this.coffs[indexJJ];
|
|
889
|
+
const dotUV = this.coffs[indexIJ];
|
|
890
|
+
const jacobi = Angle_1.Angle.trigValuesToHalfAngleTrigValues(dotUU - dotVV, 2.0 * dotUV);
|
|
891
|
+
if (Math.abs(dotUV) < 1.0e-15 * (dotUU + dotVV))
|
|
892
|
+
return 0.0;
|
|
893
|
+
const c = jacobi.c;
|
|
894
|
+
const s = jacobi.s;
|
|
895
|
+
const cc = c * c;
|
|
896
|
+
const ss = s * s;
|
|
897
|
+
const sc2 = 2.0 * c * s;
|
|
898
|
+
this.coffs[indexII] = cc * dotUU + sc2 * dotUV + ss * dotVV;
|
|
899
|
+
this.coffs[indexJJ] = ss * dotUU - sc2 * dotUV + cc * dotVV;
|
|
900
|
+
this.coffs[indexIJ] = 0.0;
|
|
901
|
+
const a = this.coffs[indexIK];
|
|
902
|
+
const b = this.coffs[indexJK];
|
|
903
|
+
this.coffs[indexIK] = a * c + b * s;
|
|
904
|
+
this.coffs[indexJK] = -s * a + c * b;
|
|
905
|
+
this.coffs[3 * j + i] = 0.0;
|
|
906
|
+
this.coffs[3 * k + i] = this.coffs[indexIK];
|
|
907
|
+
this.coffs[3 * k + j] = this.coffs[indexJK];
|
|
908
|
+
leftEigenVectors.applyGivensColumnOp(i, j, c, s);
|
|
909
|
+
return Math.abs(dotUV);
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Factor this (symmetrized) as a product U * lambda * UT where U is orthogonal, lambda is diagonal.
|
|
913
|
+
* The upper triangle is mirrored to lower triangle to enforce symmetry.
|
|
914
|
+
* @param leftEigenvectors a matrix that its columns will be filled by eigenvectors of this Matrix3d
|
|
915
|
+
* (allocated by caller, computed and filled by this function)
|
|
916
|
+
* @param lambda a vector that its entries will be filled by eigenvalues of this Matrix3d
|
|
917
|
+
* (allocated by caller, computed and filled by this function)
|
|
918
|
+
*/
|
|
919
|
+
fastSymmetricEigenvalues(leftEigenvectors, lambda) {
|
|
920
|
+
const matrix = this.clone();
|
|
921
|
+
leftEigenvectors.setIdentity();
|
|
922
|
+
const tolerance = 1.0e-12 * this.sumSquares();
|
|
923
|
+
for (let iteration = 0; iteration < 7; iteration++) {
|
|
924
|
+
const sum = matrix.applyFastSymmetricJacobiUpdate(0, 1, 2, leftEigenvectors)
|
|
925
|
+
+ matrix.applyFastSymmetricJacobiUpdate(0, 2, 1, leftEigenvectors)
|
|
926
|
+
+ matrix.applyFastSymmetricJacobiUpdate(1, 2, 0, leftEigenvectors);
|
|
927
|
+
// console.log("symmetric sum", sum);
|
|
928
|
+
// console.log ("sum", sum);
|
|
929
|
+
if (sum < tolerance) {
|
|
930
|
+
// console.log("symmetric iterations", iteration);
|
|
931
|
+
lambda.set(matrix.at(0, 0), matrix.at(1, 1), matrix.at(2, 2));
|
|
932
|
+
return true;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
return false;
|
|
936
|
+
}
|
|
904
937
|
/**
|
|
905
938
|
* Compute the (unit vector) axis and angle of rotation.
|
|
939
|
+
* * math details can be found at docs/learning/geometry/Angle.md
|
|
906
940
|
* @returns Returns axis and angle of rotation with result.ok === true when the conversion succeeded.
|
|
907
941
|
*/
|
|
908
942
|
getAxisAndAngleOfRotation() {
|
|
909
943
|
const trace = this.coffs[0] + this.coffs[4] + this.coffs[8];
|
|
910
|
-
|
|
911
|
-
const
|
|
912
|
-
const
|
|
913
|
-
|
|
914
|
-
const c = (trace - 1.0) / 2.0;
|
|
915
|
-
const s = Geometry_1.Geometry.hypotenuseXYZ(skewXY, skewYZ, skewZX) / 2.0;
|
|
916
|
-
const e = c * c + s * s - 1.0;
|
|
944
|
+
const skewXY = this.coffs[3] - this.coffs[1]; // 2*z*sin
|
|
945
|
+
const skewYZ = this.coffs[7] - this.coffs[5]; // 2*y*sin
|
|
946
|
+
const skewZX = this.coffs[2] - this.coffs[6]; // 2*x*sin
|
|
947
|
+
// trace = (m00^2 + m11^2 + m22^2) * (1-cos) + 3cos = (1-cos) + 3cos = 1 + 2cos ==> cos = (trace-1) / 2
|
|
948
|
+
const c = (trace - 1.0) / 2.0; // cosine
|
|
949
|
+
const s = Geometry_1.Geometry.hypotenuseXYZ(skewXY, skewYZ, skewZX) / 2.0; // sine
|
|
950
|
+
const e = c * c + s * s - 1.0; // s^2 + c^2 = 1
|
|
951
|
+
// if s^2 + c^2 != 1 then we have a bad matrix so return false
|
|
917
952
|
if (Math.abs(e) > Geometry_1.Geometry.smallAngleRadians) {
|
|
918
|
-
// the sine and cosine are not a unit circle point. bad matrix . ..
|
|
919
953
|
return { axis: Point3dVector3d_1.Vector3d.create(0, 0, 1), angle: Angle_1.Angle.createRadians(0), ok: false };
|
|
920
954
|
}
|
|
955
|
+
// sin is close to 0 then we got to special cases (angle 0 or 180) which needs to be handled differently
|
|
921
956
|
if (Math.abs(s) < Geometry_1.Geometry.smallAngleRadians) {
|
|
922
|
-
//
|
|
923
|
-
// The matrix is symmetric
|
|
924
|
-
// So it has simple eigenvalues -- either (1,1,1) or (1,-1,-1).
|
|
925
|
-
if (c > 0) // no rotation
|
|
957
|
+
if (c > 0) // sin = 0 and cos = 1 so angle = 0 (i.e., no rotation)
|
|
926
958
|
return { axis: Point3dVector3d_1.Vector3d.create(0, 0, 1), angle: Angle_1.Angle.createRadians(0), ok: true };
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
959
|
+
/**
|
|
960
|
+
* If sin = 0 and cos = -1 then angle = 180 (i.e., 180 degree rotation around some axis)
|
|
961
|
+
* then the rotation matrix becomes
|
|
962
|
+
* 2x^2-1 2xy 2xz
|
|
963
|
+
* 2xy 2y^2-1 2yz
|
|
964
|
+
* 2xz 2yz 2z^2-1
|
|
965
|
+
* Note that the matrix is symmetric.
|
|
966
|
+
* If rotation is around one the standard basis then non-diagonal entries become 0 and we
|
|
967
|
+
* have one 1 and two -1s on the diagonal.
|
|
968
|
+
* If rotation is around an axis other than standard basis, then the axis is the eigenvector
|
|
969
|
+
* of the rotation matrix with eigenvalue = 1.
|
|
970
|
+
*/
|
|
930
971
|
const axx = this.coffs[0];
|
|
931
972
|
const ayy = this.coffs[4];
|
|
932
973
|
const azz = this.coffs[8];
|
|
933
|
-
|
|
934
|
-
// Look for principal axis flips as a special case . ..
|
|
974
|
+
// Look for a pair of "-1" entries on the diagonal (for rotation around the basis X,Y,Z axis)
|
|
935
975
|
if (Geometry_1.Geometry.isAlmostEqualNumber(-1.0, ayy) && Geometry_1.Geometry.isAlmostEqualNumber(-1, azz)) {
|
|
936
|
-
|
|
937
|
-
return { axis: Point3dVector3d_1.Vector3d.create(1, 0, 0), angle: theta180, ok: true };
|
|
976
|
+
return { axis: Point3dVector3d_1.Vector3d.create(1, 0, 0), angle: Angle_1.Angle.createDegrees(180), ok: true };
|
|
938
977
|
}
|
|
939
978
|
else if (Geometry_1.Geometry.isAlmostEqualNumber(-1.0, axx) && Geometry_1.Geometry.isAlmostEqualNumber(-1, azz)) {
|
|
940
|
-
return { axis: Point3dVector3d_1.Vector3d.create(0, 1, 0), angle:
|
|
979
|
+
return { axis: Point3dVector3d_1.Vector3d.create(0, 1, 0), angle: Angle_1.Angle.createDegrees(180), ok: true };
|
|
941
980
|
}
|
|
942
981
|
else if (Geometry_1.Geometry.isAlmostEqualNumber(-1.0, axx) && Geometry_1.Geometry.isAlmostEqualNumber(-1, ayy)) {
|
|
943
|
-
return { axis: Point3dVector3d_1.Vector3d.create(0, 0, 1), angle:
|
|
982
|
+
return { axis: Point3dVector3d_1.Vector3d.create(0, 0, 1), angle: Angle_1.Angle.createDegrees(180), ok: true };
|
|
944
983
|
}
|
|
945
|
-
//
|
|
946
|
-
// eigenvalues will have 1.0 once, -1.0 twice.
|
|
947
|
-
// These cases look for each place (x,y,z) that the 1.0 might appear.
|
|
948
|
-
// But fastSymmetricEigenvalues reliably always seems to put the 1.0 as the x eigenvalue.
|
|
949
|
-
// so only the getColumn(0) return seems reachable in unit tests.
|
|
984
|
+
// Look for eigenvector with eigenvalue = 1
|
|
950
985
|
const eigenvectors = Matrix3d.createIdentity();
|
|
951
986
|
const eigenvalues = Point3dVector3d_1.Vector3d.create(0, 0, 0);
|
|
952
987
|
if (this.fastSymmetricEigenvalues(eigenvectors, eigenvalues)) {
|
|
953
988
|
for (let axisIndex = 0; axisIndex < 2; axisIndex++) {
|
|
954
989
|
const lambda = eigenvalues.at(axisIndex);
|
|
955
990
|
if (Geometry_1.Geometry.isAlmostEqualNumber(1, lambda))
|
|
956
|
-
return { axis: eigenvectors.getColumn(axisIndex), angle:
|
|
991
|
+
return { axis: eigenvectors.getColumn(axisIndex), angle: Angle_1.Angle.createDegrees(180), ok: true };
|
|
957
992
|
}
|
|
958
|
-
//
|
|
993
|
+
// if no eigenvalue = 1 was found return false
|
|
959
994
|
return { axis: Point3dVector3d_1.Vector3d.create(0, 0, 1), angle: Angle_1.Angle.createRadians(0), ok: false };
|
|
960
995
|
}
|
|
996
|
+
// if no axis was found return false
|
|
961
997
|
return { axis: Point3dVector3d_1.Vector3d.create(0, 0, 1), angle: Angle_1.Angle.createRadians(0), ok: false };
|
|
962
998
|
}
|
|
999
|
+
// good matrix and non-zero sine
|
|
963
1000
|
const a = 1.0 / (2.0 * s);
|
|
964
|
-
const result = {
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
*/
|
|
970
|
-
static createRotationVectorToVector(vectorA, vectorB, result) {
|
|
971
|
-
return this.createPartialRotationVectorToVector(vectorA, 1.0, vectorB, result);
|
|
972
|
-
}
|
|
973
|
-
/**
|
|
974
|
-
* Return a matrix that rotates a fraction of the angular sweep from vectorA to vectorB.
|
|
975
|
-
* @param vectorA initial vector position
|
|
976
|
-
* @param fraction fractional rotation. 1.0 is "all the way"
|
|
977
|
-
* @param vectorB final vector position
|
|
978
|
-
* @param result optional result matrix.
|
|
979
|
-
*/
|
|
980
|
-
static createPartialRotationVectorToVector(vectorA, fraction, vectorB, result) {
|
|
981
|
-
let upVector = vectorA.unitCrossProduct(vectorB);
|
|
982
|
-
if (upVector) { // the usual case --
|
|
983
|
-
return Matrix3d.createRotationAroundVector(upVector, Angle_1.Angle.createRadians(fraction * vectorA.planarAngleTo(vectorB, upVector).radians));
|
|
984
|
-
}
|
|
985
|
-
// fail if either vector is zero ...
|
|
986
|
-
if (Geometry_1.Geometry.isSmallMetricDistance(vectorA.magnitude())
|
|
987
|
-
|| Geometry_1.Geometry.isSmallMetricDistance(vectorB.magnitude()))
|
|
988
|
-
return undefined;
|
|
989
|
-
// nonzero but aligned vectors ...
|
|
990
|
-
if (vectorA.dotProduct(vectorB) > 0.0)
|
|
991
|
-
return Matrix3d.createIdentity(result);
|
|
992
|
-
// nonzero opposing vectors ..
|
|
993
|
-
upVector = Matrix3d.createPerpendicularVectorFavorPlaneContainingZ(vectorA, upVector);
|
|
994
|
-
return Matrix3d.createRotationAroundVector(upVector, Angle_1.Angle.createRadians(fraction * Math.PI));
|
|
995
|
-
}
|
|
996
|
-
/** Create a 90 degree rotation around a principal axis */
|
|
997
|
-
static create90DegreeRotationAroundAxis(axisIndex) {
|
|
998
|
-
axisIndex = Geometry_1.Geometry.cyclic3dAxis(axisIndex);
|
|
999
|
-
if (axisIndex === 0) {
|
|
1000
|
-
const retVal = Matrix3d.createRowValues(1, 0, 0, 0, 0, -1, 0, 1, 0);
|
|
1001
|
-
retVal.setupInverseTranspose();
|
|
1002
|
-
return retVal;
|
|
1003
|
-
}
|
|
1004
|
-
else if (axisIndex === 1) {
|
|
1005
|
-
const retVal = Matrix3d.createRowValues(0, 0, 1, 0, 1, 0, -1, 0, 0);
|
|
1006
|
-
retVal.setupInverseTranspose();
|
|
1007
|
-
return retVal;
|
|
1008
|
-
}
|
|
1009
|
-
else {
|
|
1010
|
-
const retVal = Matrix3d.createRowValues(0, -1, 0, 1, 0, 0, 0, 0, 1);
|
|
1011
|
-
retVal.setupInverseTranspose();
|
|
1012
|
-
return retVal;
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
/** Return (a copy of) the X column */
|
|
1016
|
-
columnX(result) { return Point3dVector3d_1.Vector3d.create(this.coffs[0], this.coffs[3], this.coffs[6], result); }
|
|
1017
|
-
/** Return (a copy of)the Y column */
|
|
1018
|
-
columnY(result) { return Point3dVector3d_1.Vector3d.create(this.coffs[1], this.coffs[4], this.coffs[7], result); }
|
|
1019
|
-
/** Return (a copy of)the Z column */
|
|
1020
|
-
columnZ(result) { return Point3dVector3d_1.Vector3d.create(this.coffs[2], this.coffs[5], this.coffs[8], result); }
|
|
1021
|
-
/** Return the X column magnitude squared */
|
|
1022
|
-
columnXMagnitudeSquared() { return Geometry_1.Geometry.hypotenuseSquaredXYZ(this.coffs[0], this.coffs[3], this.coffs[6]); }
|
|
1023
|
-
/** Return the Y column magnitude squared */
|
|
1024
|
-
columnYMagnitudeSquared() { return Geometry_1.Geometry.hypotenuseSquaredXYZ(this.coffs[1], this.coffs[4], this.coffs[7]); }
|
|
1025
|
-
/** Return the Z column magnitude squared */
|
|
1026
|
-
columnZMagnitudeSquared() { return Geometry_1.Geometry.hypotenuseSquaredXYZ(this.coffs[2], this.coffs[5], this.coffs[8]); }
|
|
1027
|
-
/** Return the X column magnitude */
|
|
1028
|
-
columnXMagnitude() { return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[0], this.coffs[3], this.coffs[6]); }
|
|
1029
|
-
/** Return the Y column magnitude */
|
|
1030
|
-
columnYMagnitude() { return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[1], this.coffs[4], this.coffs[7]); }
|
|
1031
|
-
/** Return the Z column magnitude */
|
|
1032
|
-
columnZMagnitude() { return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[2], this.coffs[5], this.coffs[8]); }
|
|
1033
|
-
/** Return magnitude of columnX cross columnY. */
|
|
1034
|
-
columnXYCrossProductMagnitude() {
|
|
1035
|
-
return Geometry_1.Geometry.crossProductMagnitude(this.coffs[0], this.coffs[3], this.coffs[6], this.coffs[1], this.coffs[4], this.coffs[7]);
|
|
1036
|
-
}
|
|
1037
|
-
/** Return the X row magnitude d */
|
|
1038
|
-
rowXMagnitude() { return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[0], this.coffs[1], this.coffs[2]); }
|
|
1039
|
-
/** Return the Y row magnitude */
|
|
1040
|
-
rowYMagnitude() { return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[3], this.coffs[4], this.coffs[5]); }
|
|
1041
|
-
/** Return the Z row magnitude */
|
|
1042
|
-
rowZMagnitude() { return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[6], this.coffs[7], this.coffs[8]); }
|
|
1043
|
-
/** Return the dot product of column X with column Y */
|
|
1044
|
-
/** Return the dot product of column X with column Y */
|
|
1045
|
-
columnXDotColumnY() {
|
|
1046
|
-
return this.coffs[0] * this.coffs[1]
|
|
1047
|
-
+ this.coffs[3] * this.coffs[4]
|
|
1048
|
-
+ this.coffs[6] * this.coffs[7];
|
|
1049
|
-
}
|
|
1050
|
-
/**
|
|
1051
|
-
* Dot product of an indexed column with a vector given as x,y,z
|
|
1052
|
-
* @param columnIndex index of column. Must be 0,1,2
|
|
1053
|
-
* @param x x component of vector
|
|
1054
|
-
* @param y y component of vector
|
|
1055
|
-
* @param z z component of vector
|
|
1056
|
-
*/
|
|
1057
|
-
columnDotXYZ(columnIndex, x, y, z) {
|
|
1058
|
-
return this.coffs[columnIndex] * x + this.coffs[columnIndex + 3] * y + this.coffs[columnIndex + 6] * z;
|
|
1059
|
-
}
|
|
1060
|
-
/** Return (a copy of) the X row */
|
|
1061
|
-
rowX(result) { return Point3dVector3d_1.Vector3d.create(this.coffs[0], this.coffs[1], this.coffs[2], result); }
|
|
1062
|
-
/** Return (a copy of) the Y row */
|
|
1063
|
-
rowY(result) { return Point3dVector3d_1.Vector3d.create(this.coffs[3], this.coffs[4], this.coffs[5], result); }
|
|
1064
|
-
/** Return (a copy of) the Z row */
|
|
1065
|
-
rowZ(result) { return Point3dVector3d_1.Vector3d.create(this.coffs[6], this.coffs[7], this.coffs[8], result); }
|
|
1066
|
-
/** Return the dot product of the vector parameter with the X column. */
|
|
1067
|
-
dotColumnX(vector) { return vector.x * this.coffs[0] + vector.y * this.coffs[3] + vector.z * this.coffs[6]; }
|
|
1068
|
-
/** Return the dot product of the vector parameter with the Y column. */
|
|
1069
|
-
dotColumnY(vector) { return vector.x * this.coffs[1] + vector.y * this.coffs[4] + vector.z * this.coffs[7]; }
|
|
1070
|
-
/** Return the dot product of the vector parameter with the Z column. */
|
|
1071
|
-
dotColumnZ(vector) { return vector.x * this.coffs[2] + vector.y * this.coffs[5] + vector.z * this.coffs[8]; }
|
|
1072
|
-
/** Return the dot product of the vector parameter with the X row. */
|
|
1073
|
-
dotRowX(vector) { return vector.x * this.coffs[0] + vector.y * this.coffs[1] + vector.z * this.coffs[2]; }
|
|
1074
|
-
/** Return the dot product of the vector parameter with the Y row. */
|
|
1075
|
-
dotRowY(vector) { return vector.x * this.coffs[3] + vector.y * this.coffs[4] + vector.z * this.coffs[5]; }
|
|
1076
|
-
/** Return the dot product of the vector parameter with the Z row. */
|
|
1077
|
-
dotRowZ(vector) { return vector.x * this.coffs[6] + vector.y * this.coffs[7] + vector.z * this.coffs[8]; }
|
|
1078
|
-
// cSpell:words XXYZ YXYZ ZXYZ XYZAs Eigen
|
|
1079
|
-
/** Return the dot product of the x,y,z with the X row. */
|
|
1080
|
-
dotRowXXYZ(x, y, z) { return x * this.coffs[0] + y * this.coffs[1] + z * this.coffs[2]; }
|
|
1081
|
-
/** Return the dot product of the x,y,z with the Y row. */
|
|
1082
|
-
dotRowYXYZ(x, y, z) { return x * this.coffs[3] + y * this.coffs[4] + z * this.coffs[5]; }
|
|
1083
|
-
/** Return the dot product of the x,y,z with the Z row. */
|
|
1084
|
-
dotRowZXYZ(x, y, z) { return x * this.coffs[6] + y * this.coffs[7] + z * this.coffs[8]; }
|
|
1085
|
-
/** Return the (vector) cross product of the Z column with the vector parameter. */
|
|
1086
|
-
columnZCrossVector(vector, result) {
|
|
1087
|
-
return Geometry_1.Geometry.crossProductXYZXYZ(this.coffs[2], this.coffs[5], this.coffs[8], vector.x, vector.y, vector.z, result);
|
|
1088
|
-
}
|
|
1089
|
-
/*
|
|
1090
|
-
* Replace current rows Ui Uj with (c*Ui - s*Uj) and (c*Uj + s*Ui).
|
|
1091
|
-
* @param i first row index. must be 0,1,2 (unchecked)
|
|
1092
|
-
* @param j second row index. must be 0,1,2 (unchecked)
|
|
1093
|
-
* @param c fist coefficient
|
|
1094
|
-
* @param s second coefficient
|
|
1095
|
-
*/
|
|
1096
|
-
applyGivensRowOp(i, j, c, s) {
|
|
1097
|
-
let ii = 3 * i;
|
|
1098
|
-
let jj = 3 * j;
|
|
1099
|
-
const limit = ii + 3;
|
|
1100
|
-
for (; ii < limit; ii++, jj++) {
|
|
1101
|
-
const a = this.coffs[ii];
|
|
1102
|
-
const b = this.coffs[jj];
|
|
1103
|
-
this.coffs[ii] = a * c + b * s;
|
|
1104
|
-
this.coffs[jj] = -a * s + b * c;
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
/**
|
|
1108
|
-
* create a rigid coordinate frame column z parallel to (_x_,_y_,_z_) and column x in the xy plane.
|
|
1109
|
-
* * column z points from origin to x,y,z
|
|
1110
|
-
* * column x is perpendicular and in the xy plane
|
|
1111
|
-
* * column y is perpendicular to both. It is the "up" vector on the view plane.
|
|
1112
|
-
* * Multiplying a world vector times the transpose of this matrix transforms into the view xy
|
|
1113
|
-
* * Multiplying the matrix times the an in-view vector transforms the vector to world.
|
|
1114
|
-
* @param x eye x coordinate
|
|
1115
|
-
* @param y eye y coordinate
|
|
1116
|
-
* @param z eye z coordinate
|
|
1117
|
-
* @param result
|
|
1118
|
-
*/
|
|
1119
|
-
static createRigidViewAxesZTowardsEye(x, y, z, result) {
|
|
1120
|
-
result = Matrix3d.createIdentity(result);
|
|
1121
|
-
const rxy = Geometry_1.Geometry.hypotenuseXY(x, y);
|
|
1122
|
-
if (Geometry_1.Geometry.isSmallMetricDistance(rxy)) {
|
|
1123
|
-
// special case for top or bottom view.
|
|
1124
|
-
if (z < 0.0)
|
|
1125
|
-
result.scaleColumnsInPlace(1.0, -1, -1.0);
|
|
1126
|
-
}
|
|
1127
|
-
else {
|
|
1128
|
-
// const d = Geometry.hypotenuseSquaredXYZ(x, y, z);
|
|
1129
|
-
const c = x / rxy;
|
|
1130
|
-
const s = y / rxy;
|
|
1131
|
-
result.setRowValues(-s, 0, c, c, 0, s, 0, 1, 0);
|
|
1132
|
-
if (z !== 0.0) {
|
|
1133
|
-
const r = Geometry_1.Geometry.hypotenuseXYZ(x, y, z);
|
|
1134
|
-
const s1 = z / r;
|
|
1135
|
-
const c1 = rxy / r;
|
|
1136
|
-
result.applyGivensColumnOp(1, 2, c1, -s1);
|
|
1137
|
-
}
|
|
1138
|
-
}
|
|
1001
|
+
const result = {
|
|
1002
|
+
axis: Point3dVector3d_1.Vector3d.create(skewYZ * a, skewZX * a, skewXY * a),
|
|
1003
|
+
angle: Angle_1.Angle.createAtan2(s, c),
|
|
1004
|
+
ok: true,
|
|
1005
|
+
};
|
|
1139
1006
|
return result;
|
|
1140
1007
|
}
|
|
1141
1008
|
/** Rotate so columns i and j become perpendicular */
|
|
@@ -1167,8 +1034,7 @@ class Matrix3d {
|
|
|
1167
1034
|
factorPerpendicularColumns(matrixC, matrixU) {
|
|
1168
1035
|
matrixC.setFrom(this);
|
|
1169
1036
|
matrixU.setIdentity();
|
|
1170
|
-
const
|
|
1171
|
-
const tolerance = 1.0e-12 * ss;
|
|
1037
|
+
const tolerance = 1.0e-12 * this.sumSquares();
|
|
1172
1038
|
for (let iteration = 0; iteration < 7; iteration++) {
|
|
1173
1039
|
const sum = matrixC.applyJacobiColumnRotation(0, 1, matrixU)
|
|
1174
1040
|
+ matrixC.applyJacobiColumnRotation(0, 2, matrixU)
|
|
@@ -1259,8 +1125,7 @@ class Matrix3d {
|
|
|
1259
1125
|
matrix.coffs[3] = matrix.coffs[1];
|
|
1260
1126
|
matrix.coffs[6] = matrix.coffs[2];
|
|
1261
1127
|
matrix.coffs[7] = matrix.coffs[5];
|
|
1262
|
-
const
|
|
1263
|
-
const tolerance = 1.0e-12 * ss;
|
|
1128
|
+
const tolerance = 1.0e-12 * this.sumSquares();
|
|
1264
1129
|
for (let iteration = 0; iteration < 7; iteration++) {
|
|
1265
1130
|
const sum = leftEigenvectors.applySymmetricJacobi(0, 1, matrix)
|
|
1266
1131
|
+ leftEigenvectors.applySymmetricJacobi(0, 2, matrix)
|
|
@@ -1275,68 +1140,174 @@ class Matrix3d {
|
|
|
1275
1140
|
}
|
|
1276
1141
|
return false;
|
|
1277
1142
|
}
|
|
1278
|
-
/**
|
|
1279
|
-
*
|
|
1143
|
+
/**
|
|
1144
|
+
* Return a matrix that rotates a fraction of the angular sweep from vectorA to vectorB.
|
|
1145
|
+
* @param vectorA initial vector position
|
|
1146
|
+
* @param fraction fractional rotation (1 means rotate all the way)
|
|
1147
|
+
* @param vectorB final vector position
|
|
1148
|
+
* @param result optional result matrix.
|
|
1280
1149
|
*/
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1150
|
+
static createPartialRotationVectorToVector(vectorA, fraction, vectorB, result) {
|
|
1151
|
+
let upVector = vectorA.unitCrossProduct(vectorB);
|
|
1152
|
+
// the usual case (both vectors and also their cross product is non-zero)
|
|
1153
|
+
if (upVector) {
|
|
1154
|
+
return Matrix3d.createRotationAroundVector(upVector, Angle_1.Angle.createRadians(fraction * vectorA.planarAngleTo(vectorB, upVector).radians));
|
|
1155
|
+
}
|
|
1156
|
+
// if either vector is zero
|
|
1157
|
+
if (Geometry_1.Geometry.isSmallMetricDistance(vectorA.magnitude())
|
|
1158
|
+
|| Geometry_1.Geometry.isSmallMetricDistance(vectorB.magnitude()))
|
|
1159
|
+
return undefined;
|
|
1160
|
+
// aligned vectors (cross product = 0, dot product > 0)
|
|
1161
|
+
if (vectorA.dotProduct(vectorB) > 0.0)
|
|
1162
|
+
return Matrix3d.createIdentity(result);
|
|
1163
|
+
// opposing vectors (cross product = 0, dot product < 0)
|
|
1164
|
+
upVector = Matrix3d.createPerpendicularVectorFavorPlaneContainingZ(vectorA, upVector);
|
|
1165
|
+
return Matrix3d.createRotationAroundVector(upVector, Angle_1.Angle.createRadians(fraction * Math.PI));
|
|
1166
|
+
}
|
|
1167
|
+
/** Returns a matrix that rotates from vectorA to vectorB. */
|
|
1168
|
+
static createRotationVectorToVector(vectorA, vectorB, result) {
|
|
1169
|
+
return this.createPartialRotationVectorToVector(vectorA, 1.0, vectorB, result);
|
|
1170
|
+
}
|
|
1171
|
+
/** Create a 90 degree rotation around a principal axis */
|
|
1172
|
+
static create90DegreeRotationAroundAxis(axisIndex) {
|
|
1173
|
+
axisIndex = Geometry_1.Geometry.cyclic3dAxis(axisIndex);
|
|
1174
|
+
if (axisIndex === 0) {
|
|
1175
|
+
const retVal = Matrix3d.createRowValues(1, 0, 0, 0, 0, -1, 0, 1, 0);
|
|
1176
|
+
retVal.setupInverseTranspose();
|
|
1177
|
+
return retVal;
|
|
1178
|
+
}
|
|
1179
|
+
else if (axisIndex === 1) {
|
|
1180
|
+
const retVal = Matrix3d.createRowValues(0, 0, 1, 0, 1, 0, -1, 0, 0);
|
|
1181
|
+
retVal.setupInverseTranspose();
|
|
1182
|
+
return retVal;
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
const retVal = Matrix3d.createRowValues(0, -1, 0, 1, 0, 0, 0, 0, 1);
|
|
1186
|
+
retVal.setupInverseTranspose();
|
|
1187
|
+
return retVal;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
/** Return (a copy of) the X column */
|
|
1191
|
+
columnX(result) {
|
|
1192
|
+
return Point3dVector3d_1.Vector3d.create(this.coffs[0], this.coffs[3], this.coffs[6], result);
|
|
1193
|
+
}
|
|
1194
|
+
/** Return (a copy of) the Y column */
|
|
1195
|
+
columnY(result) {
|
|
1196
|
+
return Point3dVector3d_1.Vector3d.create(this.coffs[1], this.coffs[4], this.coffs[7], result);
|
|
1197
|
+
}
|
|
1198
|
+
/** Return (a copy of) the Z column */
|
|
1199
|
+
columnZ(result) {
|
|
1200
|
+
return Point3dVector3d_1.Vector3d.create(this.coffs[2], this.coffs[5], this.coffs[8], result);
|
|
1201
|
+
}
|
|
1202
|
+
/** Return the X column magnitude squared */
|
|
1203
|
+
columnXMagnitudeSquared() {
|
|
1204
|
+
return Geometry_1.Geometry.hypotenuseSquaredXYZ(this.coffs[0], this.coffs[3], this.coffs[6]);
|
|
1205
|
+
}
|
|
1206
|
+
/** Return the Y column magnitude squared */
|
|
1207
|
+
columnYMagnitudeSquared() {
|
|
1208
|
+
return Geometry_1.Geometry.hypotenuseSquaredXYZ(this.coffs[1], this.coffs[4], this.coffs[7]);
|
|
1209
|
+
}
|
|
1210
|
+
/** Return the Z column magnitude squared */
|
|
1211
|
+
columnZMagnitudeSquared() {
|
|
1212
|
+
return Geometry_1.Geometry.hypotenuseSquaredXYZ(this.coffs[2], this.coffs[5], this.coffs[8]);
|
|
1213
|
+
}
|
|
1214
|
+
/** Return the X column magnitude */
|
|
1215
|
+
columnXMagnitude() {
|
|
1216
|
+
return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[0], this.coffs[3], this.coffs[6]);
|
|
1217
|
+
}
|
|
1218
|
+
/** Return the Y column magnitude */
|
|
1219
|
+
columnYMagnitude() {
|
|
1220
|
+
return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[1], this.coffs[4], this.coffs[7]);
|
|
1221
|
+
}
|
|
1222
|
+
/** Return the Z column magnitude */
|
|
1223
|
+
columnZMagnitude() {
|
|
1224
|
+
return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[2], this.coffs[5], this.coffs[8]);
|
|
1225
|
+
}
|
|
1226
|
+
/** Return magnitude of columnX cross columnY. */
|
|
1227
|
+
columnXYCrossProductMagnitude() {
|
|
1228
|
+
return Geometry_1.Geometry.crossProductMagnitude(this.coffs[0], this.coffs[3], this.coffs[6], this.coffs[1], this.coffs[4], this.coffs[7]);
|
|
1229
|
+
}
|
|
1230
|
+
/** Return the X row magnitude */
|
|
1231
|
+
rowXMagnitude() {
|
|
1232
|
+
return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[0], this.coffs[1], this.coffs[2]);
|
|
1233
|
+
}
|
|
1234
|
+
/** Return the Y row magnitude */
|
|
1235
|
+
rowYMagnitude() {
|
|
1236
|
+
return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[3], this.coffs[4], this.coffs[5]);
|
|
1237
|
+
}
|
|
1238
|
+
/** Return the Z row magnitude */
|
|
1239
|
+
rowZMagnitude() {
|
|
1240
|
+
return Geometry_1.Geometry.hypotenuseXYZ(this.coffs[6], this.coffs[7], this.coffs[8]);
|
|
1241
|
+
}
|
|
1242
|
+
/** Return the dot product of column X with column Y */
|
|
1243
|
+
columnXDotColumnY() {
|
|
1244
|
+
return this.coffs[0] * this.coffs[1]
|
|
1245
|
+
+ this.coffs[3] * this.coffs[4]
|
|
1246
|
+
+ this.coffs[6] * this.coffs[7];
|
|
1313
1247
|
}
|
|
1314
1248
|
/**
|
|
1315
|
-
*
|
|
1316
|
-
*
|
|
1317
|
-
* @param
|
|
1318
|
-
* @param
|
|
1249
|
+
* Dot product of an indexed column with a vector given as x,y,z
|
|
1250
|
+
* @param columnIndex index of column. Must be 0,1,2.
|
|
1251
|
+
* @param x x component of vector
|
|
1252
|
+
* @param y y component of vector
|
|
1253
|
+
* @param z z component of vector
|
|
1319
1254
|
*/
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
// console.log (" sum", sum);
|
|
1331
|
-
if (sum < tolerance) {
|
|
1332
|
-
// console.log("symmetric iterations", iteration);
|
|
1333
|
-
lambda.set(matrix.at(0, 0), matrix.at(1, 1), matrix.at(2, 2));
|
|
1334
|
-
return true;
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
return false;
|
|
1255
|
+
columnDotXYZ(columnIndex, x, y, z) {
|
|
1256
|
+
return this.coffs[columnIndex] * x + this.coffs[columnIndex + 3] * y + this.coffs[columnIndex + 6] * z;
|
|
1257
|
+
}
|
|
1258
|
+
/** Return (a copy of) the X row */
|
|
1259
|
+
rowX(result) {
|
|
1260
|
+
return Point3dVector3d_1.Vector3d.create(this.coffs[0], this.coffs[1], this.coffs[2], result);
|
|
1261
|
+
}
|
|
1262
|
+
/** Return (a copy of) the Y row */
|
|
1263
|
+
rowY(result) {
|
|
1264
|
+
return Point3dVector3d_1.Vector3d.create(this.coffs[3], this.coffs[4], this.coffs[5], result);
|
|
1338
1265
|
}
|
|
1339
|
-
/**
|
|
1266
|
+
/** Return (a copy of) the Z row */
|
|
1267
|
+
rowZ(result) {
|
|
1268
|
+
return Point3dVector3d_1.Vector3d.create(this.coffs[6], this.coffs[7], this.coffs[8], result);
|
|
1269
|
+
}
|
|
1270
|
+
/** Return the dot product of the vector parameter with the X column. */
|
|
1271
|
+
dotColumnX(vector) {
|
|
1272
|
+
return vector.x * this.coffs[0] + vector.y * this.coffs[3] + vector.z * this.coffs[6];
|
|
1273
|
+
}
|
|
1274
|
+
/** Return the dot product of the vector parameter with the Y column. */
|
|
1275
|
+
dotColumnY(vector) {
|
|
1276
|
+
return vector.x * this.coffs[1] + vector.y * this.coffs[4] + vector.z * this.coffs[7];
|
|
1277
|
+
}
|
|
1278
|
+
/** Return the dot product of the vector parameter with the Z column. */
|
|
1279
|
+
dotColumnZ(vector) {
|
|
1280
|
+
return vector.x * this.coffs[2] + vector.y * this.coffs[5] + vector.z * this.coffs[8];
|
|
1281
|
+
}
|
|
1282
|
+
/** Return the dot product of the vector parameter with the X row. */
|
|
1283
|
+
dotRowX(vector) {
|
|
1284
|
+
return vector.x * this.coffs[0] + vector.y * this.coffs[1] + vector.z * this.coffs[2];
|
|
1285
|
+
}
|
|
1286
|
+
/** Return the dot product of the vector parameter with the Y row. */
|
|
1287
|
+
dotRowY(vector) {
|
|
1288
|
+
return vector.x * this.coffs[3] + vector.y * this.coffs[4] + vector.z * this.coffs[5];
|
|
1289
|
+
}
|
|
1290
|
+
/** Return the dot product of the vector parameter with the Z row. */
|
|
1291
|
+
dotRowZ(vector) {
|
|
1292
|
+
return vector.x * this.coffs[6] + vector.y * this.coffs[7] + vector.z * this.coffs[8];
|
|
1293
|
+
}
|
|
1294
|
+
/** Return the dot product of the x,y,z with the X row. */
|
|
1295
|
+
dotRowXXYZ(x, y, z) {
|
|
1296
|
+
return x * this.coffs[0] + y * this.coffs[1] + z * this.coffs[2];
|
|
1297
|
+
}
|
|
1298
|
+
/** Return the dot product of the x,y,z with the Y row. */
|
|
1299
|
+
dotRowYXYZ(x, y, z) {
|
|
1300
|
+
return x * this.coffs[3] + y * this.coffs[4] + z * this.coffs[5];
|
|
1301
|
+
}
|
|
1302
|
+
/** Return the dot product of the x,y,z with the Z row. */
|
|
1303
|
+
dotRowZXYZ(x, y, z) {
|
|
1304
|
+
return x * this.coffs[6] + y * this.coffs[7] + z * this.coffs[8];
|
|
1305
|
+
}
|
|
1306
|
+
/** Return the cross product of the Z column with the vector parameter. */
|
|
1307
|
+
columnZCrossVector(vector, result) {
|
|
1308
|
+
return Geometry_1.Geometry.crossProductXYZXYZ(this.coffs[2], this.coffs[5], this.coffs[8], vector.x, vector.y, vector.z, result);
|
|
1309
|
+
}
|
|
1310
|
+
/** Set data from xyz parts of Point4d (w part of Point4d ignored) */
|
|
1340
1311
|
setColumnsPoint4dXYZ(vectorU, vectorV, vectorW) {
|
|
1341
1312
|
this.inverseState = InverseMatrixState.unknown;
|
|
1342
1313
|
this.setRowValues(vectorU.x, vectorV.x, vectorW.x, vectorU.y, vectorV.y, vectorW.y, vectorU.z, vectorV.z, vectorW.z);
|
|
@@ -1360,16 +1331,22 @@ class Matrix3d {
|
|
|
1360
1331
|
this.coffs[index + 6] = 0.0;
|
|
1361
1332
|
}
|
|
1362
1333
|
}
|
|
1363
|
-
/**
|
|
1334
|
+
/**
|
|
1335
|
+
* Set all columns of the matrix. Any undefined vector is zeros.
|
|
1336
|
+
* @param vectorX values for column 0
|
|
1337
|
+
* @param vectorY values for column 1
|
|
1338
|
+
* @param vectorZ optional values for column 2 (it's optional in case column 2 is 000, which is a
|
|
1339
|
+
* projection onto the xy-plane)
|
|
1340
|
+
*/
|
|
1364
1341
|
setColumns(vectorX, vectorY, vectorZ) {
|
|
1365
1342
|
this.setColumn(0, vectorX);
|
|
1366
1343
|
this.setColumn(1, vectorY);
|
|
1367
1344
|
this.setColumn(2, vectorZ);
|
|
1368
1345
|
}
|
|
1369
1346
|
/**
|
|
1370
|
-
*
|
|
1371
|
-
* @param rowIndex row index.
|
|
1372
|
-
* @param value x,
|
|
1347
|
+
* Set entries in one row of the matrix.
|
|
1348
|
+
* @param rowIndex row index. This is interpreted cyclically (using Geometry.cyclic3dAxis).
|
|
1349
|
+
* @param value x,y,z values for row.
|
|
1373
1350
|
*/
|
|
1374
1351
|
setRow(rowIndex, value) {
|
|
1375
1352
|
const index = 3 * Geometry_1.Geometry.cyclic3dAxis(rowIndex);
|
|
@@ -1378,21 +1355,26 @@ class Matrix3d {
|
|
|
1378
1355
|
this.coffs[index + 2] = value.z;
|
|
1379
1356
|
this.inverseState = InverseMatrixState.unknown;
|
|
1380
1357
|
}
|
|
1381
|
-
/**
|
|
1382
|
-
*
|
|
1358
|
+
/**
|
|
1359
|
+
* Return (a copy of) a column of the matrix.
|
|
1360
|
+
* @param i column index. This is interpreted cyclically (using Geometry.cyclic3dAxis).
|
|
1361
|
+
* @param result optional preallocated result.
|
|
1383
1362
|
*/
|
|
1384
1363
|
getColumn(columnIndex, result) {
|
|
1385
1364
|
const index = Geometry_1.Geometry.cyclic3dAxis(columnIndex);
|
|
1386
1365
|
return Point3dVector3d_1.Vector3d.create(this.coffs[index], this.coffs[index + 3], this.coffs[index + 6], result);
|
|
1387
1366
|
}
|
|
1388
|
-
/**
|
|
1389
|
-
*
|
|
1367
|
+
/**
|
|
1368
|
+
* Return a (copy of) a row of the matrix.
|
|
1369
|
+
* @param i row index. This is interpreted cyclically (using Geometry.cyclic3dAxis).
|
|
1370
|
+
* @param result optional preallocated result.
|
|
1390
1371
|
*/
|
|
1391
1372
|
getRow(columnIndex, result) {
|
|
1392
1373
|
const index = 3 * Geometry_1.Geometry.cyclic3dAxis(columnIndex);
|
|
1393
1374
|
return Point3dVector3d_1.Vector3d.create(this.coffs[index], this.coffs[index + 1], this.coffs[index + 2], result);
|
|
1394
1375
|
}
|
|
1395
|
-
/**
|
|
1376
|
+
/**
|
|
1377
|
+
* Create a matrix from row vectors.
|
|
1396
1378
|
* ```
|
|
1397
1379
|
* equation
|
|
1398
1380
|
* \begin{bmatrix}U_x & U_y & U_z \\ V_x & V_y & V_z \\ W_x & W_y & W_z \end{bmatrix}
|
|
@@ -1401,13 +1383,18 @@ class Matrix3d {
|
|
|
1401
1383
|
static createRows(vectorU, vectorV, vectorW, result) {
|
|
1402
1384
|
return Matrix3d.createRowValues(vectorU.x, vectorU.y, vectorU.z, vectorV.x, vectorV.y, vectorV.z, vectorW.x, vectorW.y, vectorW.z, result);
|
|
1403
1385
|
}
|
|
1404
|
-
/**
|
|
1405
|
-
*
|
|
1406
|
-
*
|
|
1386
|
+
/**
|
|
1387
|
+
* Create a matrix that scales along a specified `direction`. This means if you multiply the returned matrix
|
|
1388
|
+
* by a `vector`, you get `directional scale` of that `vector`. Suppose `plane` is the plane perpendicular
|
|
1389
|
+
* to the `direction`. When scale = 0, `directional scale` is projection of the `vector` to the `plane`.
|
|
1390
|
+
* When scale = 1, `directional scale` is the `vector` itself. When scale = -1, `directional scale` is
|
|
1391
|
+
* mirror of the `vector` across the `plane`. In general, When scale != 0, the result is computed by first
|
|
1392
|
+
* projecting the `vector` to the `plane`, then translating that projection along the `direction` (if scale > 0)
|
|
1393
|
+
* or in opposite direction (if scale < 0).
|
|
1407
1394
|
* ```
|
|
1408
1395
|
* equation
|
|
1409
|
-
* \text{The matrix is } I
|
|
1410
|
-
* \\ \text{with }
|
|
1396
|
+
* \text{The matrix is } I + (s-1) D D^T
|
|
1397
|
+
* \\ \text{with }D\text{ being the normalized direction vector and }s\text{ being the scale.}
|
|
1411
1398
|
* ```
|
|
1412
1399
|
*/
|
|
1413
1400
|
static createDirectionalScale(direction, scale, result) {
|
|
@@ -1416,19 +1403,13 @@ class Matrix3d {
|
|
|
1416
1403
|
const x = unit.x;
|
|
1417
1404
|
const y = unit.y;
|
|
1418
1405
|
const z = unit.z;
|
|
1419
|
-
const a =
|
|
1406
|
+
const a = scale - 1;
|
|
1420
1407
|
return Matrix3d.createRowValues(1 + a * x * x, a * x * y, a * x * z, a * y * x, 1 + a * y * y, a * y * z, a * z * x, a * z * y, 1 + a * z * z, result);
|
|
1421
1408
|
}
|
|
1422
1409
|
return Matrix3d.createUniformScale(scale);
|
|
1423
1410
|
}
|
|
1424
|
-
|
|
1425
|
-
* *
|
|
1426
|
-
* * If the direction vector is not close to Z, the "next" column ((axisIndex + 1) mod 3) will be in the XY plane in the direction of (direction cross Z)
|
|
1427
|
-
* * If the direction vector is close to Z, the "next" column ((axisIndex + 1) mode 3) will be in the direction of (direction cross Y)
|
|
1428
|
-
*/
|
|
1429
|
-
// static create1Vector(direction: Vector3d, axisIndex: number): Matrix3d;
|
|
1430
|
-
// static createFromXYVectors(vectorX: Vector3d, vectorY: Vector3d, axisIndex: number): Matrix3d;
|
|
1431
|
-
/** Multiply the matrix * vector, treating the vector is a column vector on the right.
|
|
1411
|
+
/**
|
|
1412
|
+
* Multiply `matrix * vector`, treating the vector is a column vector on the right.
|
|
1432
1413
|
* ```
|
|
1433
1414
|
* equation
|
|
1434
1415
|
* \matrixXY{A}\columnSubXYZ{U}
|
|
@@ -1439,36 +1420,38 @@ class Matrix3d {
|
|
|
1439
1420
|
const x = vectorU.x;
|
|
1440
1421
|
const y = vectorU.y;
|
|
1441
1422
|
const z = vectorU.z;
|
|
1442
|
-
return Point3dVector3d_1.Vector3d.create(
|
|
1423
|
+
return Point3dVector3d_1.Vector3d.create(this.coffs[0] * x + this.coffs[1] * y + this.coffs[2] * z, this.coffs[3] * x + this.coffs[4] * y + this.coffs[5] * z, this.coffs[6] * x + this.coffs[7] * y + this.coffs[8] * z, result);
|
|
1443
1424
|
}
|
|
1444
|
-
/**
|
|
1445
|
-
*
|
|
1425
|
+
/**
|
|
1426
|
+
* Multiply `matrix * vector` in place for vector in the array, i.e. treating the vector is a column
|
|
1427
|
+
* vector on the right.
|
|
1428
|
+
* * Each `vector` is updated to be `matrix * vector`
|
|
1446
1429
|
*/
|
|
1447
1430
|
multiplyVectorArrayInPlace(data) {
|
|
1448
1431
|
for (const v of data)
|
|
1449
|
-
v.set(
|
|
1432
|
+
v.set(this.coffs[0] * v.x + this.coffs[1] * v.y + this.coffs[2] * v.z, this.coffs[3] * v.x + this.coffs[4] * v.y + this.coffs[5] * v.z, this.coffs[6] * v.x + this.coffs[7] * v.y + this.coffs[8] * v.z);
|
|
1450
1433
|
}
|
|
1451
|
-
/**
|
|
1434
|
+
/** Compute `origin - matrix * vector` */
|
|
1452
1435
|
static xyzMinusMatrixTimesXYZ(origin, matrix, vector, result) {
|
|
1453
1436
|
const x = vector.x;
|
|
1454
1437
|
const y = vector.y;
|
|
1455
1438
|
const z = vector.z;
|
|
1456
1439
|
return Point3dVector3d_1.Point3d.create(origin.x - (matrix.coffs[0] * x + matrix.coffs[1] * y + matrix.coffs[2] * z), origin.y - (matrix.coffs[3] * x + matrix.coffs[4] * y + matrix.coffs[5] * z), origin.z - (matrix.coffs[6] * x + matrix.coffs[7] * y + matrix.coffs[8] * z), result);
|
|
1457
1440
|
}
|
|
1458
|
-
/**
|
|
1441
|
+
/** Compute `origin + matrix * vector` using only the xy parts of the inputs. */
|
|
1459
1442
|
static xyPlusMatrixTimesXY(origin, matrix, vector, result) {
|
|
1460
1443
|
const x = vector.x;
|
|
1461
1444
|
const y = vector.y;
|
|
1462
1445
|
return Point2dVector2d_1.Point2d.create(origin.x + matrix.coffs[0] * x + matrix.coffs[1] * y, origin.y + matrix.coffs[3] * x + matrix.coffs[4] * y, result);
|
|
1463
1446
|
}
|
|
1464
|
-
/**
|
|
1447
|
+
/** Compute `origin + matrix * vector` using all xyz parts of the inputs. */
|
|
1465
1448
|
static xyzPlusMatrixTimesXYZ(origin, matrix, vector, result) {
|
|
1466
1449
|
const x = vector.x;
|
|
1467
1450
|
const y = vector.y;
|
|
1468
1451
|
const z = vector.z;
|
|
1469
1452
|
return Point3dVector3d_1.Point3d.create(origin.x + matrix.coffs[0] * x + matrix.coffs[1] * y + matrix.coffs[2] * z, origin.y + matrix.coffs[3] * x + matrix.coffs[4] * y + matrix.coffs[5] * z, origin.z + matrix.coffs[6] * x + matrix.coffs[7] * y + matrix.coffs[8] * z, result);
|
|
1470
1453
|
}
|
|
1471
|
-
/**
|
|
1454
|
+
/** Updates vector to be `origin + matrix * vector` using all xyz parts of the inputs. */
|
|
1472
1455
|
static xyzPlusMatrixTimesXYZInPlace(origin, matrix, vector) {
|
|
1473
1456
|
const x = vector.x;
|
|
1474
1457
|
const y = vector.y;
|
|
@@ -1477,61 +1460,72 @@ class Matrix3d {
|
|
|
1477
1460
|
vector.y = origin.y + matrix.coffs[3] * x + matrix.coffs[4] * y + matrix.coffs[5] * z;
|
|
1478
1461
|
vector.z = origin.z + matrix.coffs[6] * x + matrix.coffs[7] * y + matrix.coffs[8] * z;
|
|
1479
1462
|
}
|
|
1480
|
-
/**
|
|
1463
|
+
/** Compute `origin + matrix * vector` where the final vector is given as direct x,y,z coordinates */
|
|
1481
1464
|
static xyzPlusMatrixTimesCoordinates(origin, matrix, x, y, z, result) {
|
|
1482
1465
|
return Point3dVector3d_1.Point3d.create(origin.x + matrix.coffs[0] * x + matrix.coffs[1] * y + matrix.coffs[2] * z, origin.y + matrix.coffs[3] * x + matrix.coffs[4] * y + matrix.coffs[5] * z, origin.z + matrix.coffs[6] * x + matrix.coffs[7] * y + matrix.coffs[8] * z, result);
|
|
1483
1466
|
}
|
|
1484
1467
|
/**
|
|
1485
1468
|
* Treat the 3x3 matrix and origin as upper 3x4 part of a 4x4 matrix, with 0001 as the final row.
|
|
1486
|
-
* Multiply
|
|
1469
|
+
* Multiply the 4x4 matrix by `[x,y,z,w]`
|
|
1470
|
+
* ```
|
|
1471
|
+
* equation
|
|
1472
|
+
* \begin{bmatrix}M_0 & M_1 & M_2 & Ox \\ M_3 & M_4 & M_5 & Oy \\ M_6 & M_7 & M_8 & Oz \\ 0 & 0 & 0 & 1\end{bmatrix} * \begin{bmatrix}x \\ y \\ z \\ w\end{bmatrix}
|
|
1473
|
+
* ```
|
|
1487
1474
|
* @param origin translation part (xyz in column 3)
|
|
1488
1475
|
* @param matrix matrix part (leading 3x3)
|
|
1489
1476
|
* @param x x part of multiplied point
|
|
1490
1477
|
* @param y y part of multiplied point
|
|
1491
1478
|
* @param z z part of multiplied point
|
|
1492
1479
|
* @param w w part of multiplied point
|
|
1493
|
-
* @param result optional result.
|
|
1480
|
+
* @param result optional preallocated result.
|
|
1494
1481
|
*/
|
|
1495
1482
|
static xyzPlusMatrixTimesWeightedCoordinates(origin, matrix, x, y, z, w, result) {
|
|
1496
|
-
return Point4d_1.Point4d.create(
|
|
1483
|
+
return Point4d_1.Point4d.create(matrix.coffs[0] * x + matrix.coffs[1] * y + matrix.coffs[2] * z + origin.x * w, matrix.coffs[3] * x + matrix.coffs[4] * y + matrix.coffs[5] * z + origin.y * w, matrix.coffs[6] * x + matrix.coffs[7] * y + matrix.coffs[8] * z + origin.z * w, w, result);
|
|
1497
1484
|
}
|
|
1498
1485
|
/**
|
|
1499
1486
|
* Treat the 3x3 matrix and origin as upper 3x4 part of a 4x4 matrix, with 0001 as the final row.
|
|
1500
|
-
* Multiply
|
|
1487
|
+
* Multiply the 4x4 matrix by `[x,y,z,w]`
|
|
1488
|
+
* ```
|
|
1489
|
+
* equation
|
|
1490
|
+
* \begin{bmatrix}M_0 & M_1 & M_2 & Ox \\ M_3 & M_4 & M_5 & Oy \\ M_6 & M_7 & M_8 & Oz \\ 0 & 0 & 0 & 1\end{bmatrix} * \begin{bmatrix}x \\ y \\ z \\ w\end{bmatrix}
|
|
1491
|
+
* ```
|
|
1501
1492
|
* @param origin translation part (xyz in column 3)
|
|
1502
1493
|
* @param matrix matrix part (leading 3x3)
|
|
1503
1494
|
* @param x x part of multiplied point
|
|
1504
1495
|
* @param y y part of multiplied point
|
|
1505
1496
|
* @param z z part of multiplied point
|
|
1506
1497
|
* @param w w part of multiplied point
|
|
1507
|
-
* @param result optional result.
|
|
1498
|
+
* @param result optional preallocated result.
|
|
1508
1499
|
*/
|
|
1509
1500
|
static xyzPlusMatrixTimesWeightedCoordinatesToFloat64Array(origin, matrix, x, y, z, w, result) {
|
|
1510
1501
|
if (!result)
|
|
1511
1502
|
result = new Float64Array(4);
|
|
1512
|
-
result[0] =
|
|
1513
|
-
result[1] =
|
|
1514
|
-
result[2] =
|
|
1503
|
+
result[0] = matrix.coffs[0] * x + matrix.coffs[1] * y + matrix.coffs[2] * z + origin.x * w;
|
|
1504
|
+
result[1] = matrix.coffs[3] * x + matrix.coffs[4] * y + matrix.coffs[5] * z + origin.y * w;
|
|
1505
|
+
result[2] = matrix.coffs[6] * x + matrix.coffs[7] * y + matrix.coffs[8] * z + origin.z * w;
|
|
1515
1506
|
result[3] = w;
|
|
1516
1507
|
return result;
|
|
1517
1508
|
}
|
|
1518
1509
|
/**
|
|
1519
|
-
* Treat the 3x3 matrix and origin as
|
|
1520
|
-
* Multiply
|
|
1510
|
+
* Treat the 3x3 matrix and origin as a 3x4 matrix.
|
|
1511
|
+
* * Multiply the 3x4 matrix by `[x,y,z,1]`
|
|
1512
|
+
* ```
|
|
1513
|
+
* equation
|
|
1514
|
+
* \begin{bmatrix}M_0 & M_1 & M_2 & Ox \\ M_3 & M_4 & M_5 & Oy \\ M_6 & M_7 & M_8 & Oz\end{bmatrix} * \begin{bmatrix}x \\ y \\ z \\ 1\end{bmatrix}
|
|
1515
|
+
* ```
|
|
1521
1516
|
* @param origin translation part (xyz in column 3)
|
|
1522
1517
|
* @param matrix matrix part (leading 3x3)
|
|
1523
1518
|
* @param x x part of multiplied point
|
|
1524
1519
|
* @param y y part of multiplied point
|
|
1525
1520
|
* @param z z part of multiplied point
|
|
1526
|
-
* @param
|
|
1527
|
-
* @param result optional result.
|
|
1521
|
+
* @param result optional preallocated result.
|
|
1528
1522
|
*/
|
|
1529
1523
|
static xyzPlusMatrixTimesCoordinatesToFloat64Array(origin, matrix, x, y, z, result) {
|
|
1530
1524
|
if (!result)
|
|
1531
1525
|
result = new Float64Array(3);
|
|
1532
|
-
result[0] =
|
|
1533
|
-
result[1] =
|
|
1534
|
-
result[2] =
|
|
1526
|
+
result[0] = matrix.coffs[0] * x + matrix.coffs[1] * y + matrix.coffs[2] * z + origin.x;
|
|
1527
|
+
result[1] = matrix.coffs[3] * x + matrix.coffs[4] * y + matrix.coffs[5] * z + origin.y;
|
|
1528
|
+
result[2] = matrix.coffs[6] * x + matrix.coffs[7] * y + matrix.coffs[8] * z + origin.z;
|
|
1535
1529
|
return result;
|
|
1536
1530
|
}
|
|
1537
1531
|
/**
|
|
@@ -1551,9 +1545,9 @@ class Matrix3d {
|
|
|
1551
1545
|
const x = vector.x;
|
|
1552
1546
|
const y = vector.y;
|
|
1553
1547
|
const z = vector.z;
|
|
1554
|
-
result.x =
|
|
1555
|
-
result.y =
|
|
1556
|
-
result.z =
|
|
1548
|
+
result.x = this.coffs[0] * x + this.coffs[3] * y + this.coffs[6] * z;
|
|
1549
|
+
result.y = this.coffs[1] * x + this.coffs[4] * y + this.coffs[7] * z;
|
|
1550
|
+
result.z = this.coffs[2] * x + this.coffs[5] * y + this.coffs[8] * z;
|
|
1557
1551
|
return result;
|
|
1558
1552
|
}
|
|
1559
1553
|
/** Multiply the matrix * (x,y,z), i.e. the vector (x,y,z) is a column vector on the right.
|
|
@@ -2081,7 +2075,7 @@ class Matrix3d {
|
|
|
2081
2075
|
* @param scaleX scale factor for column x
|
|
2082
2076
|
* @param scaleY scale factor for column y
|
|
2083
2077
|
* @param scaleZ scale factor for column z
|
|
2084
|
-
* @param result optional result.
|
|
2078
|
+
* @param result optional preallocated result.
|
|
2085
2079
|
*/
|
|
2086
2080
|
scaleColumns(scaleX, scaleY, scaleZ, result) {
|
|
2087
2081
|
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);
|
|
@@ -2102,7 +2096,7 @@ class Matrix3d {
|
|
|
2102
2096
|
this.coffs[7] *= scaleY;
|
|
2103
2097
|
this.coffs[8] *= scaleZ;
|
|
2104
2098
|
if (this.inverseState === InverseMatrixState.inverseStored && this.inverseCoffs !== undefined) {
|
|
2105
|
-
// apply
|
|
2099
|
+
// apply reverse scales to the ROWS of the inverse
|
|
2106
2100
|
const divX = Geometry_1.Geometry.conditionalDivideFraction(1.0, scaleX);
|
|
2107
2101
|
const divY = Geometry_1.Geometry.conditionalDivideFraction(1.0, scaleY);
|
|
2108
2102
|
const divZ = Geometry_1.Geometry.conditionalDivideFraction(1.0, scaleZ);
|
|
@@ -2125,7 +2119,7 @@ class Matrix3d {
|
|
|
2125
2119
|
* @param scaleX scale factor for row x
|
|
2126
2120
|
* @param scaleY scale factor for row y
|
|
2127
2121
|
* @param scaleZ scale factor for row z
|
|
2128
|
-
* @param result optional result.
|
|
2122
|
+
* @param result optional preallocated result.
|
|
2129
2123
|
*/
|
|
2130
2124
|
scaleRows(scaleX, scaleY, scaleZ, result) {
|
|
2131
2125
|
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);
|
|
@@ -2169,12 +2163,49 @@ class Matrix3d {
|
|
|
2169
2163
|
}
|
|
2170
2164
|
/** create a Matrix3d whose values are uniformly scaled from this.
|
|
2171
2165
|
* @param scale scale factor to apply.
|
|
2172
|
-
* @param result optional result.
|
|
2166
|
+
* @param result optional preallocated result.
|
|
2173
2167
|
* @returns Return the new or repopulated matrix
|
|
2174
2168
|
*/
|
|
2175
2169
|
scale(scale, result) {
|
|
2176
2170
|
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);
|
|
2177
2171
|
}
|
|
2172
|
+
/**
|
|
2173
|
+
* Create a rigid matrix (columns and rows are unit length and pairwise perpendicular) for
|
|
2174
|
+
* the given eye coordinate.
|
|
2175
|
+
* * column z is parallel to x,y,z
|
|
2176
|
+
* * column x is perpendicular to column z and is in the xy plane
|
|
2177
|
+
* * column y is perpendicular to both. It is the "up" vector on the view plane.
|
|
2178
|
+
* * Multiplying the returned matrix times a local (view) vector gives the world vector.
|
|
2179
|
+
* * Multiplying transpose of the returned matrix times a world vector gives the local
|
|
2180
|
+
* (view) vector.
|
|
2181
|
+
* @param x eye x coordinate
|
|
2182
|
+
* @param y eye y coordinate
|
|
2183
|
+
* @param z eye z coordinate
|
|
2184
|
+
* @param result optional preallocated result
|
|
2185
|
+
*/
|
|
2186
|
+
static createRigidViewAxesZTowardsEye(x, y, z, result) {
|
|
2187
|
+
result = Matrix3d.createIdentity(result);
|
|
2188
|
+
const rxy = Geometry_1.Geometry.hypotenuseXY(x, y);
|
|
2189
|
+
// if coordinate is (0,0,z), i.e., Top or Bottom view
|
|
2190
|
+
if (Geometry_1.Geometry.isSmallMetricDistance(rxy)) {
|
|
2191
|
+
if (z < 0.0)
|
|
2192
|
+
result.scaleColumnsInPlace(1.0, -1.0, -1.0);
|
|
2193
|
+
}
|
|
2194
|
+
else {
|
|
2195
|
+
const c = x / rxy;
|
|
2196
|
+
const s = y / rxy;
|
|
2197
|
+
// if coordinate is (x,y,0), i.e., Front or Back or Left or Right view
|
|
2198
|
+
result.setRowValues(-s, 0, c, c, 0, s, 0, 1, 0);
|
|
2199
|
+
// if coordinate is (x,y,z), i.e., other views such as Iso or RightIso
|
|
2200
|
+
if (z !== 0.0) {
|
|
2201
|
+
const r = Geometry_1.Geometry.hypotenuseXYZ(x, y, z);
|
|
2202
|
+
const s1 = z / r;
|
|
2203
|
+
const c1 = rxy / r;
|
|
2204
|
+
result.applyGivensColumnOp(1, 2, c1, -s1);
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
return result;
|
|
2208
|
+
}
|
|
2178
2209
|
/** Return the determinant of this matrix. */
|
|
2179
2210
|
determinant() {
|
|
2180
2211
|
return this.coffs[0] * this.coffs[4] * this.coffs[8]
|