diff --git a/src/Mod/Test/BaseTests.py b/src/Mod/Test/BaseTests.py index 3e32767447..a07f6b596b 100644 --- a/src/Mod/Test/BaseTests.py +++ b/src/Mod/Test/BaseTests.py @@ -363,6 +363,61 @@ class AlgebraTestCase(unittest.TestCase): p.Rotation.Angle = math.pi / 2 self.assertEqual(abs(p.inverse().Rotation.Angle), p.Rotation.Angle) + def testDecomposeScale(self): + mat = FreeCAD.Matrix() + mat.scale(FreeCAD.Vector(2, 3, 4)) + res = mat.decompose() + self.assertTrue(res[0].isUnity()) + self.assertEqual(res[1], mat) + self.assertTrue(res[2].isUnity()) + self.assertTrue(res[3].isUnity()) + + def testDecomposeRotation(self): + mat = FreeCAD.Matrix() + mat.rotateX(1) + mat.rotateY(1) + mat.rotateZ(1) + res = mat.decompose() + self.assertTrue(res[0].isUnity()) + self.assertTrue(res[1].isUnity(1e-12)) + self.assertEqual(res[2], mat) + self.assertTrue(res[3].isUnity()) + + def testDecomposeMove(self): + mat = FreeCAD.Matrix() + mat.move(FreeCAD.Vector(1, 2, 3)) + res = mat.decompose() + self.assertTrue(res[0].isUnity()) + self.assertTrue(res[1].isUnity()) + self.assertTrue(res[2].isUnity()) + self.assertEqual(res[3], mat) + + def testMatrixDecompose(self): + mat = FreeCAD.Matrix() + mat.A21 = 1.0 + mat.A14 = 1.0 + mat.A24 = 2.0 + mat.A34 = 3.0 + res = mat.decompose() + + mul = res[3] * res[2] * res[1] * res[0] + self.assertEqual(mul, mat) + + # shearing + self.assertAlmostEqual(res[0].determinant(), 1.0) + + # scaling + self.assertEqual(res[1].hasScale(), FreeCAD.ScaleType.NonUniformLeft) + + # rotation + rot1 = FreeCAD.Rotation(res[2]) + rot2 = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), 45) + self.assertTrue(rot1.isSame(rot2, 1e-12)) + + # translation + plm = FreeCAD.Placement(res[3]) + self.assertEqual(plm.Base, FreeCAD.Vector(1, 2, 3)) + def testYawPitchRoll(self): def getYPR1(yaw, pitch, roll): r = FreeCAD.Rotation() diff --git a/tests/src/Base/Matrix.cpp b/tests/src/Base/Matrix.cpp index 962267c359..9a29f79e90 100644 --- a/tests/src/Base/Matrix.cpp +++ b/tests/src/Base/Matrix.cpp @@ -295,6 +295,64 @@ TEST(Matrix, TestDyadic) EXPECT_EQ(mat1, mat2); } +TEST(Matrix, TestDecomposeScale) +{ + Base::Matrix4D mat; + mat.scale(1.0, 2.0, 3.0); + auto res = mat.decompose(); + + EXPECT_TRUE(res[0].isUnity()); + EXPECT_EQ(res[1], mat); + EXPECT_TRUE(res[2].isUnity()); + EXPECT_TRUE(res[3].isUnity()); +} + +TEST(Matrix, TestDecomposeRotation) +{ + Base::Matrix4D mat; + mat.rotX(1.0); + mat.rotY(1.0); + mat.rotZ(1.0); + auto res = mat.decompose(); + + EXPECT_TRUE(res[0].isUnity(1e-12)); + EXPECT_TRUE(res[1].isUnity(1e-12)); + EXPECT_EQ(res[2], mat); + EXPECT_TRUE(res[3].isUnity(1e-12)); +} + +TEST(Matrix, TestDecomposeMove) +{ + Base::Matrix4D mat; + mat.move(1.0, 2.0, 3.0); + auto res = mat.decompose(); + + EXPECT_TRUE(res[0].isUnity()); + EXPECT_TRUE(res[1].isUnity()); + EXPECT_TRUE(res[2].isUnity()); + EXPECT_EQ(res[3], mat); +} + +TEST(Matrix, TestDecompose) +{ + Base::Matrix4D mat; + mat[0][0] = 1.0; + mat[0][3] = 1.0; + mat[1][3] = 2.0; + mat[2][3] = 3.0; + auto res = mat.decompose(); + + Base::Matrix4D mul = res[3] * res[2] * res[1] * res[0]; + EXPECT_EQ(mul, mat); + + // shearing + EXPECT_DOUBLE_EQ(res[0].determinant3(), 1.0); + // rotation + EXPECT_DOUBLE_EQ(res[2].determinant3(), 1.0); + // translation + EXPECT_DOUBLE_EQ(res[2].determinant3(), 1.0); +} + TEST(Matrix, TestRotLine) { Base::Vector3d axis{1.0, 2.0, 3.0}; diff --git a/tests/src/Base/Rotation.cpp b/tests/src/Base/Rotation.cpp index d8d6676a9e..72a61184bd 100644 --- a/tests/src/Base/Rotation.cpp +++ b/tests/src/Base/Rotation.cpp @@ -67,4 +67,14 @@ TEST(Rotation, TestUniformScaleLT1) EXPECT_EQ(scaled_rot.isSame(scaled_rot, 1.0e-7), true); } +TEST(Rotation, TestRotationDecompose) +{ + Base::Matrix4D mat; + mat.setCol(0, Base::Vector3d {1, 0, 0}); + mat.setCol(1, Base::Vector3d {1, 1, 0}); + mat.setCol(2, Base::Vector3d {0, 0, 1}); + + // decompose rotation part + EXPECT_TRUE(Base::Rotation {mat}.isIdentity()); +} // NOLINTEND(cppcoreguidelines-avoid-magic-numbers,readability-magic-numbers)