Base: fix Matrix4D::hasScale

* If all column vectors of the 3x3 sub-matrix are equal the function incorrectly claims that it's uniform scaling.
* Detect also non-uniform scaling and if was applied from the left or right side
* Replace the int with an enum and expose it to Python
* Add several new unit tests
This commit is contained in:
wmayer
2022-02-15 21:05:11 +01:00
parent 97d1c114d0
commit 0208608b9e
8 changed files with 110 additions and 40 deletions

View File

@@ -154,7 +154,7 @@ def autogroup(obj):
# do not autogroup if obj points to active_part to prevent cyclic references
return
matrix = parent.getSubObject(sub, retType=4)
if matrix.hasScale() == 1:
if matrix.hasScale() == App.ScaleType.Uniform:
err = translate("draft",
"Unable to insert new object into "
"a scaled part")

View File

@@ -4297,7 +4297,8 @@ bool TopoShape::_makETransform(const TopoShape &shape,
const Base::Matrix4D &rclTrf, const char *op, bool checkScale, bool copy)
{
if(checkScale) {
if(rclTrf.hasScale()<0) {
auto type = rclTrf.hasScale();
if (type != Base::ScaleType::Uniform && type != Base::ScaleType::NoScaling) {
makEGTransform(shape,rclTrf,op,copy);
return true;
}

View File

@@ -422,13 +422,42 @@ class MatrixTestCase(unittest.TestCase):
def testScale(self):
self.mat.scale(1., 2., 3.)
self.assertEqual(self.mat.determinant(), 6.0)
self.assertEqual(self.mat.hasScale(), -1)
self.assertEqual(self.mat.hasScale(), FreeCAD.ScaleType.NonUniformLeft)
self.mat.unity()
self.assertEqual(self.mat.hasScale(), 0)
self.assertEqual(self.mat.hasScale(), FreeCAD.ScaleType.NoScaling)
self.mat.scale(2., 2., 2.)
self.assertEqual(self.mat.hasScale(), 1)
self.assertEqual(self.mat.hasScale(), FreeCAD.ScaleType.Uniform)
self.mat.rotateX(1.0)
self.assertEqual(self.mat.hasScale(), 1)
self.assertEqual(self.mat.hasScale(), FreeCAD.ScaleType.Uniform)
self.mat.scale(1., 2., 3.)
self.assertEqual(self.mat.hasScale(), FreeCAD.ScaleType.NonUniformLeft)
self.mat.unity()
self.mat.scale(1., 2., 3.)
self.mat.rotateX(1.0)
self.assertEqual(self.mat.hasScale(), FreeCAD.ScaleType.NonUniformRight)
self.mat.unity()
self.mat.setCol(0, FreeCAD.Vector(1,2,3))
self.mat.setCol(1, FreeCAD.Vector(1,2,3))
self.mat.setCol(2, FreeCAD.Vector(1,2,3))
self.assertEqual(self.mat.hasScale(), FreeCAD.ScaleType.Other)
self.mat.unity()
self.mat.setRow(0, FreeCAD.Vector(1,2,3))
self.mat.setRow(1, FreeCAD.Vector(1,2,3))
self.mat.setRow(2, FreeCAD.Vector(1,2,3))
self.assertEqual(self.mat.hasScale(), FreeCAD.ScaleType.Other)
def testShearing(self):
self.mat.setRow(1, FreeCAD.Vector(0,1,1))
self.assertEqual(self.mat.hasScale(), FreeCAD.ScaleType.Other)
def testMultLeftOrRight(self):
mat1 = FreeCAD.Matrix()
mat1.rotateX(1.0)
mat2 = FreeCAD.Matrix()
mat2.scale(1., 2., 3.)
self.assertEqual((mat1 * mat2).hasScale(), FreeCAD.ScaleType.NonUniformRight)
self.assertEqual((mat2 * mat1).hasScale(), FreeCAD.ScaleType.NonUniformLeft)
def testNull(self):
self.assertFalse(self.mat.isNull())