diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a3791d0828..0a5c6b5dc2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,8 @@ files: | tests/src| src/Mod/Sketcher/App/planegcs| src/Mod/Sketcher/App| - src/Mod/Sketcher/Gui + src/Mod/Sketcher/Gui| + src/Mod/Sketcher| ) exclude: | (?x)^( diff --git a/src/Mod/Sketcher/SketcherTests/TestSketchExpression.py b/src/Mod/Sketcher/SketcherTests/TestSketchExpression.py index 05289823bf..4aba472f28 100644 --- a/src/Mod/Sketcher/SketcherTests/TestSketchExpression.py +++ b/src/Mod/Sketcher/SketcherTests/TestSketchExpression.py @@ -1,24 +1,24 @@ -#*************************************************************************** -#* Copyright (c) 2021 Werner Mayer * -#* * -#* This file is part of the FreeCAD CAx development system. * -#* * -#* This program is free software; you can redistribute it and/or modify * -#* it under the terms of the GNU Lesser General Public License (LGPL) * -#* as published by the Free Software Foundation; either version 2 of * -#* the License, or (at your option) any later version. * -#* for detail see the LICENCE text file. * -#* * -#* FreeCAD is distributed in the hope that it will be useful, * -#* but WITHOUT ANY WARRANTY; without even the implied warranty of * -#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -#* GNU Library General Public License for more details. * -#* * -#* You should have received a copy of the GNU Library General Public * -#* License along with FreeCAD; if not, write to the Free Software * -#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * -#* USA * -#***************************************************************************/ +# *************************************************************************** +# * Copyright (c) 2021 Werner Mayer * +# * * +# * This file is part of the FreeCAD CAx development system. * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU Lesser General Public License (LGPL) * +# * as published by the Free Software Foundation; either version 2 of * +# * the License, or (at your option) any later version. * +# * for detail see the LICENCE text file. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU Library General Public License for more details. * +# * * +# * You should have received a copy of the GNU Library General Public * +# * License along with FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# ***************************************************************************/ import math, os, sys, unittest @@ -28,6 +28,7 @@ import Sketcher App = FreeCAD + class TestSketchExpression(unittest.TestCase): def setUp(self): self.Doc = FreeCAD.newDocument("TestSketchExpr") @@ -35,33 +36,33 @@ class TestSketchExpression(unittest.TestCase): # See https://forum.freecad.org/viewtopic.php?f=3&t=64699 # and https://forum.freecad.org/viewtopic.php?f=10&t=64718 def testConstraintWithExpression(self): - sketch = self.Doc.addObject('Sketcher::SketchObject','Sketch') + sketch = self.Doc.addObject("Sketcher::SketchObject", "Sketch") geoList = [] - geoList.append(Part.LineSegment(App.Vector(0,5,0),App.Vector(5,5,0))) - geoList.append(Part.LineSegment(App.Vector(5,5,0),App.Vector(5,0,0))) - geoList.append(Part.LineSegment(App.Vector(5,0,0),App.Vector(0,0,0))) - geoList.append(Part.LineSegment(App.Vector(0,0,0),App.Vector(0,5,0))) - sketch.addGeometry(geoList,False) + geoList.append(Part.LineSegment(App.Vector(0, 5, 0), App.Vector(5, 5, 0))) + geoList.append(Part.LineSegment(App.Vector(5, 5, 0), App.Vector(5, 0, 0))) + geoList.append(Part.LineSegment(App.Vector(5, 0, 0), App.Vector(0, 0, 0))) + geoList.append(Part.LineSegment(App.Vector(0, 0, 0), App.Vector(0, 5, 0))) + sketch.addGeometry(geoList, False) conList = [] - conList.append(Sketcher.Constraint('Coincident',0,2,1,1)) - conList.append(Sketcher.Constraint('Coincident',1,2,2,1)) - conList.append(Sketcher.Constraint('Coincident',2,2,3,1)) - conList.append(Sketcher.Constraint('Coincident',3,2,0,1)) - conList.append(Sketcher.Constraint('Horizontal',0)) - conList.append(Sketcher.Constraint('Horizontal',2)) - conList.append(Sketcher.Constraint('Vertical',1)) - conList.append(Sketcher.Constraint('Vertical',3)) + conList.append(Sketcher.Constraint("Coincident", 0, 2, 1, 1)) + conList.append(Sketcher.Constraint("Coincident", 1, 2, 2, 1)) + conList.append(Sketcher.Constraint("Coincident", 2, 2, 3, 1)) + conList.append(Sketcher.Constraint("Coincident", 3, 2, 0, 1)) + conList.append(Sketcher.Constraint("Horizontal", 0)) + conList.append(Sketcher.Constraint("Horizontal", 2)) + conList.append(Sketcher.Constraint("Vertical", 1)) + conList.append(Sketcher.Constraint("Vertical", 3)) sketch.addConstraint(conList) del geoList, conList - length = sketch.addConstraint(Sketcher.Constraint('Distance',0,6.0)) - height = sketch.addConstraint(Sketcher.Constraint('Distance',3,5.0)) + length = sketch.addConstraint(Sketcher.Constraint("Distance", 0, 6.0)) + height = sketch.addConstraint(Sketcher.Constraint("Distance", 3, 5.0)) - sketch.renameConstraint(length, u'Length') - sketch.setExpression('Constraints[{}]'.format(height), u'.Constraints.Length') + sketch.renameConstraint(length, "Length") + sketch.setExpression("Constraints[{}]".format(height), ".Constraints.Length") def tearDown(self): - # comment out to omit closing document for debugging - FreeCAD.closeDocument(self.Doc.Name) + # comment out to omit closing document for debugging + FreeCAD.closeDocument(self.Doc.Name) diff --git a/src/Mod/Sketcher/SketcherTests/TestSketchFillet.py b/src/Mod/Sketcher/SketcherTests/TestSketchFillet.py index dcdaafb62d..9523dcc8de 100644 --- a/src/Mod/Sketcher/SketcherTests/TestSketchFillet.py +++ b/src/Mod/Sketcher/SketcherTests/TestSketchFillet.py @@ -1,4 +1,4 @@ -#************************************************************************** +# ************************************************************************** # Copyright (c) 2021 Emmanuel O'Brien * # * # This file is part of the FreeCAD CAx development system. * @@ -18,276 +18,314 @@ # License along with FreeCAD; if not, write to the Free Software * # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * # USA * -#************************************************************************** +# ************************************************************************** import FreeCAD, math, os, sys, unittest, Part, Sketcher from .TestSketcherSolver import CreateRectangleSketch + App = FreeCAD + def VShape(SketchFeature): - # Simple inverted V shape - SketchFeature.addGeometry(Part.LineSegment(App.Vector(0,0,0),App.Vector(1,1,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',0,1,-1,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',0,1,0,2,1)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(1,1,0),App.Vector(2,0,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',1,1,0,2)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',1,1,1,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',1,1,1,2,-1)) - SketchFeature.fillet(0, 2, 0.25, True, True) + # Simple inverted V shape + SketchFeature.addGeometry(Part.LineSegment(App.Vector(0, 0, 0), App.Vector(1, 1, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 0, 1, 0, 2, 1)) + SketchFeature.addGeometry(Part.LineSegment(App.Vector(1, 1, 0), App.Vector(2, 0, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 1, 1, 0, 2)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 1, 1, 1, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 1, 1, 1, 2, -1)) + SketchFeature.fillet(0, 2, 0.25, True, True) + def BoxCircle(SketchFeature): - # Square with a circle centered at the upper right corner - top_edge = int(SketchFeature.GeometryCount) - right_edge = top_edge + 1 - CreateRectangleSketch(SketchFeature, [0, 0], [2, 2]) - top_midpoint = App.Vector(1, 2, 0) - right_midpoint = App.Vector(2, 1, 0) - circle = int(SketchFeature.GeometryCount) - SketchFeature.addGeometry(Part.Circle(App.Vector(0,0,0), App.Vector(0,0,1), 1),False) - SketchFeature.addConstraint(Sketcher.Constraint('Radius',circle,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',top_edge,2,circle,3)) - # Since the circle center is coincident with the corner, there are three coincident points - # and thus the simpler fillet() call would get confused. Instead we'll need to point at the two - # lines and their midpoints - SketchFeature.fillet(top_edge, right_edge, top_midpoint, right_midpoint, 0.25, True, True) + # Square with a circle centered at the upper right corner + top_edge = int(SketchFeature.GeometryCount) + right_edge = top_edge + 1 + CreateRectangleSketch(SketchFeature, [0, 0], [2, 2]) + top_midpoint = App.Vector(1, 2, 0) + right_midpoint = App.Vector(2, 1, 0) + circle = int(SketchFeature.GeometryCount) + SketchFeature.addGeometry(Part.Circle(App.Vector(0, 0, 0), App.Vector(0, 0, 1), 1), False) + SketchFeature.addConstraint(Sketcher.Constraint("Radius", circle, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", top_edge, 2, circle, 3)) + # Since the circle center is coincident with the corner, there are three coincident points + # and thus the simpler fillet() call would get confused. Instead we'll need to point at the two + # lines and their midpoints + SketchFeature.fillet(top_edge, right_edge, top_midpoint, right_midpoint, 0.25, True, True) + def PointOnObject(SketchFeature): - # Square with the upper right corner touching the edge of a circle - top_edge = int(SketchFeature.GeometryCount) - right_edge = top_edge + 1 - CreateRectangleSketch(SketchFeature, [0, 0], [2, 2]) - circle = int(SketchFeature.GeometryCount) - SketchFeature.addGeometry(Part.Circle(App.Vector(12,3,0), App.Vector(0,0,1), 1),False) - SketchFeature.addConstraint(Sketcher.Constraint('Radius',circle,1)) - SketchFeature.addConstraint(Sketcher.Constraint('PointOnObject',top_edge,2,circle)) - SketchFeature.fillet(top_edge, 2, 0.25, True, True) + # Square with the upper right corner touching the edge of a circle + top_edge = int(SketchFeature.GeometryCount) + right_edge = top_edge + 1 + CreateRectangleSketch(SketchFeature, [0, 0], [2, 2]) + circle = int(SketchFeature.GeometryCount) + SketchFeature.addGeometry(Part.Circle(App.Vector(12, 3, 0), App.Vector(0, 0, 1), 1), False) + SketchFeature.addConstraint(Sketcher.Constraint("Radius", circle, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("PointOnObject", top_edge, 2, circle)) + SketchFeature.fillet(top_edge, 2, 0.25, True, True) + class TestSketchFillet(unittest.TestCase): - def setUp(self): - self.Doc = FreeCAD.newDocument("TestSketchFillet") + def setUp(self): + self.Doc = FreeCAD.newDocument("TestSketchFillet") - def testBasicFillet(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'BasicFillet') - CreateRectangleSketch(SketchFeature, [0, 0], [2, 2]) - SketchFeature.fillet(0,2, 0.25, True, True) - self.assertAlmostEqual(SketchFeature.Geometry[4].Radius, 0.25) + def testBasicFillet(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "BasicFillet") + CreateRectangleSketch(SketchFeature, [0, 0], [2, 2]) + SketchFeature.fillet(0, 2, 0.25, True, True) + self.assertAlmostEqual(SketchFeature.Geometry[4].Radius, 0.25) - # Fillets can be made even between unconnected lines - def testUnconnected(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'Unconnected') - # Inverted open V - SketchFeature.addGeometry(Part.LineSegment(App.Vector(0,0,0),App.Vector(1,1,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',0,1,-1,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',0,1,0,2,1)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(2.1,1,0),App.Vector(3,0,0))) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',1,1, 1,2, 0.9)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',1,1, 1,2, -1)) + # Fillets can be made even between unconnected lines + def testUnconnected(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "Unconnected") + # Inverted open V + SketchFeature.addGeometry(Part.LineSegment(App.Vector(0, 0, 0), App.Vector(1, 1, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 0, 1, 0, 2, 1)) + SketchFeature.addGeometry(Part.LineSegment(App.Vector(2.1, 1, 0), App.Vector(3, 0, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 1, 1, 1, 2, 0.9)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 1, 1, 1, 2, -1)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(3,3,0),App.Vector(5,3,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Equal',0,2)) - self.Doc.recompute() - self.assertAlmostEqual(SketchFeature.Geometry[2].length(), math.sqrt(2)) + SketchFeature.addGeometry(Part.LineSegment(App.Vector(3, 3, 0), App.Vector(5, 3, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Equal", 0, 2)) + self.Doc.recompute() + self.assertAlmostEqual(SketchFeature.Geometry[2].length(), math.sqrt(2)) - SketchFeature.fillet(0,1, App.Vector(0.5,0.5,0), App.Vector(2.55,0.5,0), 0.25, True, True) - # Make sure a fillet was created - self.assertAlmostEqual(SketchFeature.Geometry[3].Radius, 0.25) + SketchFeature.fillet( + 0, 1, App.Vector(0.5, 0.5, 0), App.Vector(2.55, 0.5, 0), 0.25, True, True + ) + # Make sure a fillet was created + self.assertAlmostEqual(SketchFeature.Geometry[3].Radius, 0.25) - self.Doc.recompute() - # Third line's length shouldn't have changed - self.assertAlmostEqual(SketchFeature.Geometry[2].length(), math.sqrt(2)) - # First line should be shorter - self.assertNotAlmostEqual(SketchFeature.Geometry[0].length(), math.sqrt(2)) + self.Doc.recompute() + # Third line's length shouldn't have changed + self.assertAlmostEqual(SketchFeature.Geometry[2].length(), math.sqrt(2)) + # First line should be shorter + self.assertNotAlmostEqual(SketchFeature.Geometry[0].length(), math.sqrt(2)) - # Curved lines can also be filleted - def testCurve(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'Curve') - SketchFeature.addGeometry(Part.LineSegment(App.Vector(0,0,0),App.Vector(1,1,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',0,1,-1,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',0,1,0,2,1)) - arc = Part.ArcOfCircle(Part.Circle(App.Vector(3,0,0),App.Vector(0,0,1),3),0,-1) - SketchFeature.addGeometry(arc) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',1,3, -1,1, -3)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',1,3, -1,1, 0)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',1,1, 0,2)) - self.Doc.recompute() + # Curved lines can also be filleted + def testCurve(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "Curve") + SketchFeature.addGeometry(Part.LineSegment(App.Vector(0, 0, 0), App.Vector(1, 1, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 0, 1, 0, 2, 1)) + arc = Part.ArcOfCircle(Part.Circle(App.Vector(3, 0, 0), App.Vector(0, 0, 1), 3), 0, -1) + SketchFeature.addGeometry(arc) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 1, 3, -1, 1, -3)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 1, 3, -1, 1, 0)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 1, 1, 0, 2)) + self.Doc.recompute() - SketchFeature.fillet(0,1, App.Vector(0.5,0.5,0), App.Vector(0.8,0.3,0), 0.25, True, True) - self.assertAlmostEqual(SketchFeature.Geometry[2].Radius, 0.25) + SketchFeature.fillet( + 0, 1, App.Vector(0.5, 0.5, 0), App.Vector(0.8, 0.3, 0), 0.25, True, True + ) + self.assertAlmostEqual(SketchFeature.Geometry[2].Radius, 0.25) - def testUnconnectedCurve(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'UnconnectedCurve') - SketchFeature.addGeometry(Part.LineSegment(App.Vector(0,0,0),App.Vector(1,1,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',0,1,-1,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',0,1,0,2,1)) - arc = Part.ArcOfCircle(Part.Circle(App.Vector(3,1,0),App.Vector(0,0,1), 1.75), -3.14, -2.17) - SketchFeature.addGeometry(arc) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',-1,1, 1,3, 3.0)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',-1,1, 1,3, 1.0)) - SketchFeature.addConstraint(Sketcher.Constraint('Distance',0,2, 1,1, 0.25)) - self.Doc.recompute() + def testUnconnectedCurve(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "UnconnectedCurve") + SketchFeature.addGeometry(Part.LineSegment(App.Vector(0, 0, 0), App.Vector(1, 1, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 0, 1, 0, 2, 1)) + arc = Part.ArcOfCircle( + Part.Circle(App.Vector(3, 1, 0), App.Vector(0, 0, 1), 1.75), -3.14, -2.17 + ) + SketchFeature.addGeometry(arc) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", -1, 1, 1, 3, 3.0)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", -1, 1, 1, 3, 1.0)) + SketchFeature.addConstraint(Sketcher.Constraint("Distance", 0, 2, 1, 1, 0.25)) + self.Doc.recompute() - #SketchFeature.fillet(0,1, App.Vector(0.75,0.75,0), App.Vector(1.22,0.66,0), 0.25, True, True) - # Make sure the fillet happened - #self.Doc.recompute() - #self.assertAlmostEqual(SketchFeature.Geometry[2].Radius, 0.25) + # SketchFeature.fillet(0,1, App.Vector(0.75,0.75,0), App.Vector(1.22,0.66,0), 0.25, True, True) + # Make sure the fillet happened + # self.Doc.recompute() + # self.assertAlmostEqual(SketchFeature.Geometry[2].Radius, 0.25) - # The following tests are mostly about verifying that transferFilletConstraints - # does the right thing with pre-existing constraints when a fillet is created. + # The following tests are mostly about verifying that transferFilletConstraints + # does the right thing with pre-existing constraints when a fillet is created. - # Make sure the original corner is preserved when filleting - def testOriginalCorner(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'OriginalCorner') - VShape(SketchFeature) - self.Doc.recompute() - # If fillet() ever gets refactored such that the corner gets added after - # the arc, then getPoint(3,1) might break. A more general approach would - # be to iterate over the geometry list and find the bare vertex. - self.assertAlmostEqual(App.Vector(1,1,0), SketchFeature.getPoint(3,1)) + # Make sure the original corner is preserved when filleting + def testOriginalCorner(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "OriginalCorner") + VShape(SketchFeature) + self.Doc.recompute() + # If fillet() ever gets refactored such that the corner gets added after + # the arc, then getPoint(3,1) might break. A more general approach would + # be to iterate over the geometry list and find the bare vertex. + self.assertAlmostEqual(App.Vector(1, 1, 0), SketchFeature.getPoint(3, 1)) - # Make sure coincident constraints get moved to the old corner location - def testCoincident(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'Coincident') - BoxCircle(SketchFeature) - self.Doc.recompute() - # Make sure the circle center is still at the old corner - self.assertAlmostEqual(App.Vector(2,2,0).distanceToPoint(SketchFeature.getPoint(4,3)), 0.0) + # Make sure coincident constraints get moved to the old corner location + def testCoincident(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "Coincident") + BoxCircle(SketchFeature) + self.Doc.recompute() + # Make sure the circle center is still at the old corner + self.assertAlmostEqual( + App.Vector(2, 2, 0).distanceToPoint(SketchFeature.getPoint(4, 3)), 0.0 + ) - # Point-to-point horizontal and vertical constraints should also move to the old corner - def testHorizontalVertical(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'HorizontalVertical') - # Inverted V - SketchFeature.addGeometry(Part.LineSegment(App.Vector(0,0,0),App.Vector(1,1,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',0,1,-1,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',0,1,0,2,1)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(1,1,0),App.Vector(2,0,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',1,1,0,2)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',1,1,1,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',1,1,1,2,-1)) + # Point-to-point horizontal and vertical constraints should also move to the old corner + def testHorizontalVertical(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "HorizontalVertical") + # Inverted V + SketchFeature.addGeometry(Part.LineSegment(App.Vector(0, 0, 0), App.Vector(1, 1, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 0, 1, 0, 2, 1)) + SketchFeature.addGeometry(Part.LineSegment(App.Vector(1, 1, 0), App.Vector(2, 0, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 1, 1, 0, 2)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 1, 1, 1, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 1, 1, 1, 2, -1)) - SketchFeature.addGeometry(Part.Point(App.Vector(2,1))) - SketchFeature.addConstraint(Sketcher.Constraint('Horizontal',0,2, 2,1)) - SketchFeature.addGeometry(Part.Point(App.Vector(1,2))) - SketchFeature.addConstraint(Sketcher.Constraint('Vertical',1,1, 3,1)) + SketchFeature.addGeometry(Part.Point(App.Vector(2, 1))) + SketchFeature.addConstraint(Sketcher.Constraint("Horizontal", 0, 2, 2, 1)) + SketchFeature.addGeometry(Part.Point(App.Vector(1, 2))) + SketchFeature.addConstraint(Sketcher.Constraint("Vertical", 1, 1, 3, 1)) - SketchFeature.fillet(0, 2, 0.25, True, True) + SketchFeature.fillet(0, 2, 0.25, True, True) - # Verify the constraint moved to the original corner - found_horizontal = False - found_vertical = False - for c in SketchFeature.Constraints: - if c.Type == 'Horizontal' and c.First == 5 and c.FirstPos == 1 and \ - c.Second == 2 and c.SecondPos == 1: - found_horizontal = True - elif c.Type == 'Vertical' and c.First == 5 and c.FirstPos == 1 and \ - c.Second == 3 and c.SecondPos == 1: - found_vertical = True + # Verify the constraint moved to the original corner + found_horizontal = False + found_vertical = False + for c in SketchFeature.Constraints: + if ( + c.Type == "Horizontal" + and c.First == 5 + and c.FirstPos == 1 + and c.Second == 2 + and c.SecondPos == 1 + ): + found_horizontal = True + elif ( + c.Type == "Vertical" + and c.First == 5 + and c.FirstPos == 1 + and c.Second == 3 + and c.SecondPos == 1 + ): + found_vertical = True - self.assertTrue(found_horizontal) - self.assertTrue(found_vertical) + self.assertTrue(found_horizontal) + self.assertTrue(found_vertical) - # Distance constraints to the old corner point should be preserved - def testDistance(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'Distance') - # We'll end up implicitly testing line length constraints as well since that's - # what CreateRectangleSketch uses to enforce side length. If the side length doesn't - # switch to a point-to-point distance constraint with the original corner as expected, - # the point won't end up at its expected destination. - CreateRectangleSketch(SketchFeature, [0, 0], [2, 2]) + # Distance constraints to the old corner point should be preserved + def testDistance(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "Distance") + # We'll end up implicitly testing line length constraints as well since that's + # what CreateRectangleSketch uses to enforce side length. If the side length doesn't + # switch to a point-to-point distance constraint with the original corner as expected, + # the point won't end up at its expected destination. + CreateRectangleSketch(SketchFeature, [0, 0], [2, 2]) - point = int(SketchFeature.GeometryCount) - SketchFeature.addGeometry(Part.Point(App.Vector(3,2,0))) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',0,2, point,1, 1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',0,2, point,1, 0)) + point = int(SketchFeature.GeometryCount) + SketchFeature.addGeometry(Part.Point(App.Vector(3, 2, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 0, 2, point, 1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 0, 2, point, 1, 0)) - self.Doc.recompute() - self.assertTrue(SketchFeature.FullyConstrained) - SketchFeature.fillet(0, 2, 0.25, True, True) - SketchFeature.addConstraint(Sketcher.Constraint('Radius',5,0.25)) - self.Doc.recompute() - # If any constraints disappeared then we won't be fully constrained - self.assertTrue(SketchFeature.FullyConstrained) - # Make sure the point is to the right of the original corner as expected - self.assertAlmostEqual(SketchFeature.getPoint(point,1), App.Vector(3, 2, 0)) + self.Doc.recompute() + self.assertTrue(SketchFeature.FullyConstrained) + SketchFeature.fillet(0, 2, 0.25, True, True) + SketchFeature.addConstraint(Sketcher.Constraint("Radius", 5, 0.25)) + self.Doc.recompute() + # If any constraints disappeared then we won't be fully constrained + self.assertTrue(SketchFeature.FullyConstrained) + # Make sure the point is to the right of the original corner as expected + self.assertAlmostEqual(SketchFeature.getPoint(point, 1), App.Vector(3, 2, 0)) - # Make sure point on object constraints get moved to the old corner location - def testPointOnObject(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'PointOnObject') - PointOnObject(SketchFeature) - self.Doc.recompute() - # Make sure the circle center is one radius away from the old corner - self.assertAlmostEqual(App.Vector(2,2,0).distanceToPoint(SketchFeature.getPoint(4,3)), 1.0) + # Make sure point on object constraints get moved to the old corner location + def testPointOnObject(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "PointOnObject") + PointOnObject(SketchFeature) + self.Doc.recompute() + # Make sure the circle center is one radius away from the old corner + self.assertAlmostEqual( + App.Vector(2, 2, 0).distanceToPoint(SketchFeature.getPoint(4, 3)), 1.0 + ) - # Make sure colinearity doesn't get dropped - def testTangent(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'Tangent') + # Make sure colinearity doesn't get dropped + def testTangent(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "Tangent") - # Setup the geometry - first_line = int(SketchFeature.GeometryCount) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(0,0,0),App.Vector(1,1,0))) - # Anchor at the origin - SketchFeature.addConstraint(Sketcher.Constraint('Coincident', 0, 1, -1, 1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',first_line,2,-1,1,-1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',first_line,2,-1,1,-1)) + # Setup the geometry + first_line = int(SketchFeature.GeometryCount) + SketchFeature.addGeometry(Part.LineSegment(App.Vector(0, 0, 0), App.Vector(1, 1, 0))) + # Anchor at the origin + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", first_line, 2, -1, 1, -1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", first_line, 2, -1, 1, -1)) - second_line = int(SketchFeature.GeometryCount) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(1,1,0),App.Vector(2,0,0))) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',second_line,2,-1,1,-2)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',first_line,2,second_line,1)) - tangent_line = int(SketchFeature.GeometryCount) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(2,2,0), App.Vector(3,3,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Tangent', tangent_line, first_line)) - SketchFeature.addConstraint(Sketcher.Constraint('Distance', tangent_line, 1.41421356237)) - SketchFeature.fillet(first_line, 2, 0.25, True, True) + second_line = int(SketchFeature.GeometryCount) + SketchFeature.addGeometry(Part.LineSegment(App.Vector(1, 1, 0), App.Vector(2, 0, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", second_line, 2, -1, 1, -2)) + SketchFeature.addConstraint( + Sketcher.Constraint("Coincident", first_line, 2, second_line, 1) + ) + tangent_line = int(SketchFeature.GeometryCount) + SketchFeature.addGeometry(Part.LineSegment(App.Vector(2, 2, 0), App.Vector(3, 3, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Tangent", tangent_line, first_line)) + SketchFeature.addConstraint(Sketcher.Constraint("Distance", tangent_line, 1.41421356237)) + SketchFeature.fillet(first_line, 2, 0.25, True, True) - self.Doc.recompute() - # Move the tangent line and see if it's aimed right - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',tangent_line,1,-1,1,-4)) - self.Doc.recompute() + self.Doc.recompute() + # Move the tangent line and see if it's aimed right + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", tangent_line, 1, -1, 1, -4)) + self.Doc.recompute() - # The first endpoint should now be at 4,4 - self.assertAlmostEqual(App.Vector(4,4,0).distanceToPoint(SketchFeature.getPoint(tangent_line, 1)), 0.0) + # The first endpoint should now be at 4,4 + self.assertAlmostEqual( + App.Vector(4, 4, 0).distanceToPoint(SketchFeature.getPoint(tangent_line, 1)), + 0.0, + ) - # We expect the other end of the tangent line to be at 5,5, but I think 3,3 also satisfies - # the colinearity constraint - try: - self.assertAlmostEqual(App.Vector(3,3,0).distanceToPoint(SketchFeature.getPoint(tangent_line, 2)), 0.0) - except AssertionError: - self.assertAlmostEqual(App.Vector(5,5,0).distanceToPoint(SketchFeature.getPoint(tangent_line, 2)), 0.0) + # We expect the other end of the tangent line to be at 5,5, but I think 3,3 also satisfies + # the colinearity constraint + try: + self.assertAlmostEqual( + App.Vector(3, 3, 0).distanceToPoint(SketchFeature.getPoint(tangent_line, 2)), + 0.0, + ) + except AssertionError: + self.assertAlmostEqual( + App.Vector(5, 5, 0).distanceToPoint(SketchFeature.getPoint(tangent_line, 2)), + 0.0, + ) - def testSymmetric(self): - SketchFeature = self.Doc.addObject('Sketcher::SketchObject', 'Symmetric') - # Inverted V - SketchFeature.addGeometry(Part.LineSegment(App.Vector(0,0,0),App.Vector(1,1,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',0,1,-1,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',0,1,0,2,1)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(1,1,0),App.Vector(2,0,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',1,1,0,2)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',1,1,1,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',1,1,1,2,-1)) + def testSymmetric(self): + SketchFeature = self.Doc.addObject("Sketcher::SketchObject", "Symmetric") + # Inverted V + SketchFeature.addGeometry(Part.LineSegment(App.Vector(0, 0, 0), App.Vector(1, 1, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 0, 1, 0, 2, 1)) + SketchFeature.addGeometry(Part.LineSegment(App.Vector(1, 1, 0), App.Vector(2, 0, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 1, 1, 0, 2)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 1, 1, 1, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 1, 1, 1, 2, -1)) - # Mirror point - SketchFeature.addGeometry(Part.Point(App.Vector(3,2,0))) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',-1,1, 2,1, 3)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',-1,1, 2,1, 2)) + # Mirror point + SketchFeature.addGeometry(Part.Point(App.Vector(3, 2, 0))) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", -1, 1, 2, 1, 3)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", -1, 1, 2, 1, 2)) - # Point that will mirror the apex of the V - SketchFeature.addGeometry(Part.Point(App.Vector(4,2,0))) + # Point that will mirror the apex of the V + SketchFeature.addGeometry(Part.Point(App.Vector(4, 2, 0))) - SketchFeature.addConstraint(Sketcher.Constraint('Symmetric',0,2, 3,1, 2,1)) - self.Doc.recompute() + SketchFeature.addConstraint(Sketcher.Constraint("Symmetric", 0, 2, 3, 1, 2, 1)) + self.Doc.recompute() - SketchFeature.fillet(0, 2, 0.25, True, True) - self.Doc.recompute() - self.assertAlmostEqual(App.Vector(5,3,0).distanceToPoint(SketchFeature.getPoint(3, 1)), 0.0) + SketchFeature.fillet(0, 2, 0.25, True, True) + self.Doc.recompute() + self.assertAlmostEqual( + App.Vector(5, 3, 0).distanceToPoint(SketchFeature.getPoint(3, 1)), 0.0 + ) - def tearDown(self): - # comment out to omit closing document for debugging - FreeCAD.closeDocument("TestSketchFillet") - pass + def tearDown(self): + # comment out to omit closing document for debugging + FreeCAD.closeDocument("TestSketchFillet") + pass diff --git a/src/Mod/Sketcher/SketcherTests/TestSketcherSolver.py b/src/Mod/Sketcher/SketcherTests/TestSketcherSolver.py index b50a94aa76..ef90789d30 100644 --- a/src/Mod/Sketcher/SketcherTests/TestSketcherSolver.py +++ b/src/Mod/Sketcher/SketcherTests/TestSketcherSolver.py @@ -1,4 +1,4 @@ -#************************************************************************** +# ************************************************************************** # Copyright (c) 2011 Juergen Riegel * # * # This file is part of the FreeCAD CAx development system. * @@ -18,124 +18,206 @@ # License along with FreeCAD; if not, write to the Free Software * # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * # USA * -#************************************************************************** +# ************************************************************************** import FreeCAD, os, sys, unittest, Part, Sketcher from Part import Precision + App = FreeCAD xy_normal = FreeCAD.Vector(0, 0, 1) + def vec(x, y): """Shorthand to create a vector in the XY-plane""" return FreeCAD.Vector(x, y, 0) + def CreateRectangleSketch(SketchFeature, corner, lengths): hmin, hmax = corner[0], corner[0] + lengths[0] vmin, vmax = corner[1], corner[1] + lengths[1] # add the geometry and grab the count offset i = int(SketchFeature.GeometryCount) - SketchFeature.addGeometry(Part.LineSegment(FreeCAD.Vector(hmin,vmax),FreeCAD.Vector(hmax,vmax,0))) - SketchFeature.addGeometry(Part.LineSegment(FreeCAD.Vector(hmax,vmax,0),FreeCAD.Vector(hmax,vmin,0))) - SketchFeature.addGeometry(Part.LineSegment(FreeCAD.Vector(hmax,vmin,0),FreeCAD.Vector(hmin,vmin,0))) - SketchFeature.addGeometry(Part.LineSegment(FreeCAD.Vector(hmin,vmin,0),FreeCAD.Vector(hmin,vmax,0))) + SketchFeature.addGeometry( + Part.LineSegment(FreeCAD.Vector(hmin, vmax), FreeCAD.Vector(hmax, vmax, 0)) + ) + SketchFeature.addGeometry( + Part.LineSegment(FreeCAD.Vector(hmax, vmax, 0), FreeCAD.Vector(hmax, vmin, 0)) + ) + SketchFeature.addGeometry( + Part.LineSegment(FreeCAD.Vector(hmax, vmin, 0), FreeCAD.Vector(hmin, vmin, 0)) + ) + SketchFeature.addGeometry( + Part.LineSegment(FreeCAD.Vector(hmin, vmin, 0), FreeCAD.Vector(hmin, vmax, 0)) + ) # add the rectangular constraints - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',i+0,2,i+1,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',i+1,2,i+2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',i+2,2,i+3,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',i+3,2,i+0,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Horizontal',i+0)) - SketchFeature.addConstraint(Sketcher.Constraint('Horizontal',i+2)) - SketchFeature.addConstraint(Sketcher.Constraint('Vertical',i+1)) - SketchFeature.addConstraint(Sketcher.Constraint('Vertical',i+3)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", i + 0, 2, i + 1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", i + 1, 2, i + 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", i + 2, 2, i + 3, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", i + 3, 2, i + 0, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Horizontal", i + 0)) + SketchFeature.addConstraint(Sketcher.Constraint("Horizontal", i + 2)) + SketchFeature.addConstraint(Sketcher.Constraint("Vertical", i + 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Vertical", i + 3)) # Fix the bottom left corner of the rectangle - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',i+2,2,corner[0])) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',i+2,2,corner[1])) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", i + 2, 2, corner[0])) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", i + 2, 2, corner[1])) # add dimensions if lengths[0] == lengths[1]: - SketchFeature.addConstraint(Sketcher.Constraint('Equal',i+2,i+3)) - SketchFeature.addConstraint(Sketcher.Constraint('Distance',i+0,hmax-hmin)) + SketchFeature.addConstraint(Sketcher.Constraint("Equal", i + 2, i + 3)) + SketchFeature.addConstraint(Sketcher.Constraint("Distance", i + 0, hmax - hmin)) else: - SketchFeature.addConstraint(Sketcher.Constraint('Distance',i+1,vmax-vmin)) - SketchFeature.addConstraint(Sketcher.Constraint('Distance',i+0,hmax-hmin)) + SketchFeature.addConstraint(Sketcher.Constraint("Distance", i + 1, vmax - vmin)) + SketchFeature.addConstraint(Sketcher.Constraint("Distance", i + 0, hmax - hmin)) + def CreateCircleSketch(SketchFeature, center, radius): i = int(SketchFeature.GeometryCount) - SketchFeature.addGeometry(Part.Circle(App.Vector(*center), App.Vector(0,0,1), radius),False) - SketchFeature.addConstraint(Sketcher.Constraint('Radius',i,radius)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',i,3,center[0])) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',i,3,center[1])) + SketchFeature.addGeometry(Part.Circle(App.Vector(*center), App.Vector(0, 0, 1), radius), False) + SketchFeature.addConstraint(Sketcher.Constraint("Radius", i, radius)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", i, 3, center[0])) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", i, 3, center[1])) + def CreateBoxSketchSet(SketchFeature): - SketchFeature.addGeometry(Part.LineSegment(FreeCAD.Vector(-99.230339,36.960674,0),FreeCAD.Vector(69.432587,36.960674,0))) - SketchFeature.addGeometry(Part.LineSegment(FreeCAD.Vector(69.432587,36.960674,0),FreeCAD.Vector(69.432587,-53.196629,0))) - SketchFeature.addGeometry(Part.LineSegment(FreeCAD.Vector(69.432587,-53.196629,0),FreeCAD.Vector(-99.230339,-53.196629,0))) - SketchFeature.addGeometry(Part.LineSegment(FreeCAD.Vector(-99.230339,-53.196629,0),FreeCAD.Vector(-99.230339,36.960674,0))) + SketchFeature.addGeometry( + Part.LineSegment( + FreeCAD.Vector(-99.230339, 36.960674, 0), + FreeCAD.Vector(69.432587, 36.960674, 0), + ) + ) + SketchFeature.addGeometry( + Part.LineSegment( + FreeCAD.Vector(69.432587, 36.960674, 0), + FreeCAD.Vector(69.432587, -53.196629, 0), + ) + ) + SketchFeature.addGeometry( + Part.LineSegment( + FreeCAD.Vector(69.432587, -53.196629, 0), + FreeCAD.Vector(-99.230339, -53.196629, 0), + ) + ) + SketchFeature.addGeometry( + Part.LineSegment( + FreeCAD.Vector(-99.230339, -53.196629, 0), + FreeCAD.Vector(-99.230339, 36.960674, 0), + ) + ) # add the constraints - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',0,2,1,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',1,2,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',2,2,3,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',3,2,0,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Horizontal',0)) - SketchFeature.addConstraint(Sketcher.Constraint('Horizontal',2)) - SketchFeature.addConstraint(Sketcher.Constraint('Vertical',1)) - SketchFeature.addConstraint(Sketcher.Constraint('Vertical',3)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 0, 2, 1, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 1, 2, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 2, 2, 3, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 3, 2, 0, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Horizontal", 0)) + SketchFeature.addConstraint(Sketcher.Constraint("Horizontal", 2)) + SketchFeature.addConstraint(Sketcher.Constraint("Vertical", 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Vertical", 3)) # add dimensions - SketchFeature.addConstraint(Sketcher.Constraint('Distance',1,81.370787)) - SketchFeature.addConstraint(Sketcher.Constraint('Distance',0,187.573036)) + SketchFeature.addConstraint(Sketcher.Constraint("Distance", 1, 81.370787)) + SketchFeature.addConstraint(Sketcher.Constraint("Distance", 0, 187.573036)) + def CreateSlotPlateSet(SketchFeature): - SketchFeature.addGeometry(Part.LineSegment(App.Vector(60.029362,-30.279360,0),App.Vector(-120.376335,-30.279360,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Horizontal',0)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(-120.376335,-30.279360,0),App.Vector(-70.193062,38.113884,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',0,2,1,1)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(-70.193062,38.113884,0),App.Vector(60.241116,37.478645,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',1,2,2,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Horizontal',2)) - SketchFeature.addGeometry(Part.ArcOfCircle(Part.Circle(App.Vector(60.039921,3.811391,0),App.Vector(0,0,1),35.127132),-1.403763,1.419522)) - SketchFeature.addConstraint(Sketcher.Constraint('Tangent',2,2,3,2)) - SketchFeature.addConstraint(Sketcher.Constraint('Tangent',0,1,3,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Angle',0,2,1,1,0.947837)) - SketchFeature.addConstraint(Sketcher.Constraint('Distance',0,184.127425)) - SketchFeature.setDatum(7,200.000000) - SketchFeature.addConstraint(Sketcher.Constraint('Radius',3,38.424808)) - SketchFeature.setDatum(8,40.000000) - SketchFeature.setDatum(6,0.872665) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceX',0,2,0.0)) - SketchFeature.setDatum(9,0.000000) - SketchFeature.movePoint(0,2,App.Vector(-0.007829,-33.376450,0)) - SketchFeature.movePoint(0,2,App.Vector(-0.738149,-10.493386,0)) - SketchFeature.movePoint(0,2,App.Vector(-0.007829,2.165328,0)) - SketchFeature.addConstraint(Sketcher.Constraint('DistanceY',0,2,2.165328)) - SketchFeature.setDatum(10,0.000000) + SketchFeature.addGeometry( + Part.LineSegment( + App.Vector(60.029362, -30.279360, 0), App.Vector(-120.376335, -30.279360, 0) + ) + ) + SketchFeature.addConstraint(Sketcher.Constraint("Horizontal", 0)) + SketchFeature.addGeometry( + Part.LineSegment( + App.Vector(-120.376335, -30.279360, 0), App.Vector(-70.193062, 38.113884, 0) + ) + ) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 0, 2, 1, 1)) + SketchFeature.addGeometry( + Part.LineSegment(App.Vector(-70.193062, 38.113884, 0), App.Vector(60.241116, 37.478645, 0)) + ) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 1, 2, 2, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Horizontal", 2)) + SketchFeature.addGeometry( + Part.ArcOfCircle( + Part.Circle(App.Vector(60.039921, 3.811391, 0), App.Vector(0, 0, 1), 35.127132), + -1.403763, + 1.419522, + ) + ) + SketchFeature.addConstraint(Sketcher.Constraint("Tangent", 2, 2, 3, 2)) + SketchFeature.addConstraint(Sketcher.Constraint("Tangent", 0, 1, 3, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Angle", 0, 2, 1, 1, 0.947837)) + SketchFeature.addConstraint(Sketcher.Constraint("Distance", 0, 184.127425)) + SketchFeature.setDatum(7, 200.000000) + SketchFeature.addConstraint(Sketcher.Constraint("Radius", 3, 38.424808)) + SketchFeature.setDatum(8, 40.000000) + SketchFeature.setDatum(6, 0.872665) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceX", 0, 2, 0.0)) + SketchFeature.setDatum(9, 0.000000) + SketchFeature.movePoint(0, 2, App.Vector(-0.007829, -33.376450, 0)) + SketchFeature.movePoint(0, 2, App.Vector(-0.738149, -10.493386, 0)) + SketchFeature.movePoint(0, 2, App.Vector(-0.007829, 2.165328, 0)) + SketchFeature.addConstraint(Sketcher.Constraint("DistanceY", 0, 2, 2.165328)) + SketchFeature.setDatum(10, 0.000000) + def CreateSlotPlateInnerSet(SketchFeature): - SketchFeature.addGeometry(Part.Circle(App.Vector(195.055893,39.562252,0),App.Vector(0,0,1),29.846098)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(150.319031,13.449363,0),App.Vector(36.700474,13.139774,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Horizontal',5)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(36.700474,13.139774,0),App.Vector(77.566010,63.292927,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',5,2,6,1)) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(77.566010,63.292927,0),App.Vector(148.151917,63.602505,0))) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',6,2,7,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Horizontal',7)) - SketchFeature.addConstraint(Sketcher.Constraint('Parallel',1,6)) - SketchFeature.addGeometry(Part.ArcOfCircle(Part.Circle(App.Vector(192.422913,38.216347,0),App.Vector(0,0,1),45.315174),2.635158,3.602228)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',7,2,8,1)) - SketchFeature.addConstraint(Sketcher.Constraint('Coincident',8,2,5,1)) + SketchFeature.addGeometry( + Part.Circle(App.Vector(195.055893, 39.562252, 0), App.Vector(0, 0, 1), 29.846098) + ) + SketchFeature.addGeometry( + Part.LineSegment(App.Vector(150.319031, 13.449363, 0), App.Vector(36.700474, 13.139774, 0)) + ) + SketchFeature.addConstraint(Sketcher.Constraint("Horizontal", 5)) + SketchFeature.addGeometry( + Part.LineSegment(App.Vector(36.700474, 13.139774, 0), App.Vector(77.566010, 63.292927, 0)) + ) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 5, 2, 6, 1)) + SketchFeature.addGeometry( + Part.LineSegment(App.Vector(77.566010, 63.292927, 0), App.Vector(148.151917, 63.602505, 0)) + ) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 6, 2, 7, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Horizontal", 7)) + SketchFeature.addConstraint(Sketcher.Constraint("Parallel", 1, 6)) + SketchFeature.addGeometry( + Part.ArcOfCircle( + Part.Circle(App.Vector(192.422913, 38.216347, 0), App.Vector(0, 0, 1), 45.315174), + 2.635158, + 3.602228, + ) + ) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 7, 2, 8, 1)) + SketchFeature.addConstraint(Sketcher.Constraint("Coincident", 8, 2, 5, 1)) + def CreateThreeLinesWithCommonPoint(SketchFeature): - SketchFeature.addGeometry(Part.LineSegment(App.Vector(-55.965607,-9.864289,0),App.Vector(-55.600571,-9.387639,0)),False) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(-55.735817,-9.067246,0),App.Vector(-55.600571,-9.387639,0)),False) - SketchFeature.addGeometry(Part.LineSegment(App.Vector(-55.600571,-9.387639,0),App.Vector(-55.058266,-9.677831,0)),False) + SketchFeature.addGeometry( + Part.LineSegment( + App.Vector(-55.965607, -9.864289, 0), App.Vector(-55.600571, -9.387639, 0) + ), + False, + ) + SketchFeature.addGeometry( + Part.LineSegment( + App.Vector(-55.735817, -9.067246, 0), App.Vector(-55.600571, -9.387639, 0) + ), + False, + ) + SketchFeature.addGeometry( + Part.LineSegment( + App.Vector(-55.600571, -9.387639, 0), App.Vector(-55.058266, -9.677831, 0) + ), + False, + ) -#--------------------------------------------------------------------------- + +# --------------------------------------------------------------------------- # define the test cases to test the FreeCAD Sketcher module -#--------------------------------------------------------------------------- +# --------------------------------------------------------------------------- class TestSketcherSolver(unittest.TestCase): @@ -143,18 +225,18 @@ class TestSketcherSolver(unittest.TestCase): self.Doc = FreeCAD.newDocument("SketchSolverTest") def testBoxCase(self): - self.Box = self.Doc.addObject('Sketcher::SketchObject','SketchBox') + self.Box = self.Doc.addObject("Sketcher::SketchObject", "SketchBox") CreateBoxSketchSet(self.Box) self.Doc.recompute() # moving a point of the sketch - self.Box.movePoint(0,2,App.Vector(88.342697,28.174158,0)) + self.Box.movePoint(0, 2, App.Vector(88.342697, 28.174158, 0)) # fully constrain - self.Box.addConstraint(Sketcher.Constraint('DistanceX',1,2,90.0)) - self.Box.addConstraint(Sketcher.Constraint('DistanceY',1,2,-50.0)) + self.Box.addConstraint(Sketcher.Constraint("DistanceX", 1, 2, 90.0)) + self.Box.addConstraint(Sketcher.Constraint("DistanceY", 1, 2, -50.0)) self.Doc.recompute() def testSlotCase(self): - self.Slot = self.Doc.addObject('Sketcher::SketchObject','SketchSlot') + self.Slot = self.Doc.addObject("Sketcher::SketchObject", "SketchSlot") CreateSlotPlateSet(self.Slot) self.Doc.recompute() # test if all edges created @@ -165,56 +247,97 @@ class TestSketcherSolver(unittest.TestCase): def testIssue3245(self): self.Doc2 = FreeCAD.newDocument("Issue3245") - self.Doc2.addObject('Sketcher::SketchObject','Sketch') - self.Doc2.Sketch.Placement = App.Placement(App.Vector(0.000000,0.000000,0.000000),App.Rotation(0.000000,0.000000,0.000000,1.000000)) + self.Doc2.addObject("Sketcher::SketchObject", "Sketch") + self.Doc2.Sketch.Placement = App.Placement( + App.Vector(0.000000, 0.000000, 0.000000), + App.Rotation(0.000000, 0.000000, 0.000000, 1.000000), + ) self.Doc2.Sketch.MapMode = "Deactivated" - self.Doc2.Sketch.addGeometry(Part.LineSegment(App.Vector(-1.195999,56.041161,0),App.Vector(60.654316,56.382877,0)),False) - self.Doc2.Sketch.addConstraint(Sketcher.Constraint('PointOnObject',0,1,-2)) - self.Doc2.Sketch.addConstraint(Sketcher.Constraint('Horizontal',0)) - self.Doc2.Sketch.addGeometry(Part.LineSegment(App.Vector(0.512583,32.121155,0),App.Vector(60.654316,31.779440,0)),False) - self.Doc2.Sketch.addConstraint(Sketcher.Constraint('Horizontal',1)) - self.Doc2.Sketch.addGeometry(Part.LineSegment(App.Vector(0.170867,13.326859,0),App.Vector(61.679455,13.326859,0)),False) - self.Doc2.Sketch.addConstraint(Sketcher.Constraint('PointOnObject',2,1,-2)) - self.Doc2.Sketch.addConstraint(Sketcher.Constraint('Horizontal',2)) - self.Doc2.Sketch.addConstraint(Sketcher.Constraint('PointOnObject',1,1,-2)) - self.Doc2.Sketch.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,60.654316)) - self.Doc2.Sketch.setExpression('Constraints[6]', u'60') - self.Doc2.Sketch.addConstraint(Sketcher.Constraint('DistanceX',1,1,1,2,60.654316)) - self.Doc2.Sketch.setExpression('Constraints[7]', u'65') - self.Doc2.Sketch.addConstraint(Sketcher.Constraint('DistanceX',2,1,2,2,61.679455)) - self.Doc2.Sketch.setExpression('Constraints[8]', u'70') + self.Doc2.Sketch.addGeometry( + Part.LineSegment( + App.Vector(-1.195999, 56.041161, 0), App.Vector(60.654316, 56.382877, 0) + ), + False, + ) + self.Doc2.Sketch.addConstraint(Sketcher.Constraint("PointOnObject", 0, 1, -2)) + self.Doc2.Sketch.addConstraint(Sketcher.Constraint("Horizontal", 0)) + self.Doc2.Sketch.addGeometry( + Part.LineSegment( + App.Vector(0.512583, 32.121155, 0), App.Vector(60.654316, 31.779440, 0) + ), + False, + ) + self.Doc2.Sketch.addConstraint(Sketcher.Constraint("Horizontal", 1)) + self.Doc2.Sketch.addGeometry( + Part.LineSegment( + App.Vector(0.170867, 13.326859, 0), App.Vector(61.679455, 13.326859, 0) + ), + False, + ) + self.Doc2.Sketch.addConstraint(Sketcher.Constraint("PointOnObject", 2, 1, -2)) + self.Doc2.Sketch.addConstraint(Sketcher.Constraint("Horizontal", 2)) + self.Doc2.Sketch.addConstraint(Sketcher.Constraint("PointOnObject", 1, 1, -2)) + self.Doc2.Sketch.addConstraint(Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 60.654316)) + self.Doc2.Sketch.setExpression("Constraints[6]", "60") + self.Doc2.Sketch.addConstraint(Sketcher.Constraint("DistanceX", 1, 1, 1, 2, 60.654316)) + self.Doc2.Sketch.setExpression("Constraints[7]", "65") + self.Doc2.Sketch.addConstraint(Sketcher.Constraint("DistanceX", 2, 1, 2, 2, 61.679455)) + self.Doc2.Sketch.setExpression("Constraints[8]", "70") self.Doc2.recompute() self.Doc2.Sketch.delGeometry(2) values = d = {key: value for (key, value) in self.Doc2.Sketch.ExpressionEngine} - self.failUnless(values['Constraints[4]'] == u'60') - self.failUnless(values['Constraints[5]'] == u'65') + self.failUnless(values["Constraints[4]"] == "60") + self.failUnless(values["Constraints[5]"] == "65") FreeCAD.closeDocument("Issue3245") def testIssue3245_2(self): self.Doc2 = FreeCAD.newDocument("Issue3245") - ActiveSketch = self.Doc2.addObject('Sketcher::SketchObject','Sketch') - ActiveSketch.Placement = App.Placement(App.Vector(0.000000,0.000000,0.000000),App.Rotation(0.000000,0.000000,0.000000,1.000000)) + ActiveSketch = self.Doc2.addObject("Sketcher::SketchObject", "Sketch") + ActiveSketch.Placement = App.Placement( + App.Vector(0.000000, 0.000000, 0.000000), + App.Rotation(0.000000, 0.000000, 0.000000, 1.000000), + ) ActiveSketch.MapMode = "Deactivated" geoList = [] - geoList.append(Part.LineSegment(App.Vector(-23.574591,42.399727,0),App.Vector(81.949776,42.399727,0))) - geoList.append(Part.LineSegment(App.Vector(81.949776,42.399727,0),App.Vector(81.949776,-19.256901,0))) - geoList.append(Part.LineSegment(App.Vector(81.949776,-19.256901,0),App.Vector(-23.574591,-19.256901,0))) - geoList.append(Part.LineSegment(App.Vector(-23.574591,-19.256901,0),App.Vector(-23.574591,42.399727,0))) - ActiveSketch.addGeometry(geoList,False) + geoList.append( + Part.LineSegment( + App.Vector(-23.574591, 42.399727, 0), + App.Vector(81.949776, 42.399727, 0), + ) + ) + geoList.append( + Part.LineSegment( + App.Vector(81.949776, 42.399727, 0), + App.Vector(81.949776, -19.256901, 0), + ) + ) + geoList.append( + Part.LineSegment( + App.Vector(81.949776, -19.256901, 0), + App.Vector(-23.574591, -19.256901, 0), + ) + ) + geoList.append( + Part.LineSegment( + App.Vector(-23.574591, -19.256901, 0), + App.Vector(-23.574591, 42.399727, 0), + ) + ) + ActiveSketch.addGeometry(geoList, False) conList = [] - conList.append(Sketcher.Constraint('Coincident',0,2,1,1)) - conList.append(Sketcher.Constraint('Coincident',1,2,2,1)) - conList.append(Sketcher.Constraint('Coincident',2,2,3,1)) - conList.append(Sketcher.Constraint('Coincident',3,2,0,1)) - conList.append(Sketcher.Constraint('Horizontal',0)) - conList.append(Sketcher.Constraint('Horizontal',2)) - conList.append(Sketcher.Constraint('Vertical',1)) - conList.append(Sketcher.Constraint('Vertical',3)) + conList.append(Sketcher.Constraint("Coincident", 0, 2, 1, 1)) + conList.append(Sketcher.Constraint("Coincident", 1, 2, 2, 1)) + conList.append(Sketcher.Constraint("Coincident", 2, 2, 3, 1)) + conList.append(Sketcher.Constraint("Coincident", 3, 2, 0, 1)) + conList.append(Sketcher.Constraint("Horizontal", 0)) + conList.append(Sketcher.Constraint("Horizontal", 2)) + conList.append(Sketcher.Constraint("Vertical", 1)) + conList.append(Sketcher.Constraint("Vertical", 3)) ActiveSketch.addConstraint(conList) - ActiveSketch.addConstraint(Sketcher.Constraint('DistanceX',0,1,0,2,105.524367)) - ActiveSketch.setExpression('Constraints[8]', u'10 + 10') - ActiveSketch.addConstraint(Sketcher.Constraint('DistanceY',3,1,3,2,61.656628)) - ActiveSketch.setDatum(9,App.Units.Quantity('5.000000 mm')) + ActiveSketch.addConstraint(Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 105.524367)) + ActiveSketch.setExpression("Constraints[8]", "10 + 10") + ActiveSketch.addConstraint(Sketcher.Constraint("DistanceY", 3, 1, 3, 2, 61.656628)) + ActiveSketch.setDatum(9, App.Units.Quantity("5.000000 mm")) ActiveSketch.delConstraint(8) values = d = {key: value for (key, value) in self.Doc2.Sketch.ExpressionEngine} self.Doc2.recompute() @@ -223,68 +346,90 @@ class TestSketcherSolver(unittest.TestCase): def testBlockConstraintEllipse(self): self.Doc3 = FreeCAD.newDocument("BlockConstraintTests") - ActiveSketch = self.Doc3.addObject('Sketcher::SketchObject','Sketch') - ActiveSketch.Placement = App.Placement(App.Vector(0.000000,0.000000,0.000000),App.Rotation(0.000000,0.000000,0.000000,1.000000)) + ActiveSketch = self.Doc3.addObject("Sketcher::SketchObject", "Sketch") + ActiveSketch.Placement = App.Placement( + App.Vector(0.000000, 0.000000, 0.000000), + App.Rotation(0.000000, 0.000000, 0.000000, 1.000000), + ) ActiveSketch.MapMode = "Deactivated" - ActiveSketch.addGeometry(Part.Ellipse(App.Vector(-19.129438,14.345055,0),App.Vector(-33.806261,12.085921,0),App.Vector(-30.689360,7.107538,0)),False) + ActiveSketch.addGeometry( + Part.Ellipse( + App.Vector(-19.129438, 14.345055, 0), + App.Vector(-33.806261, 12.085921, 0), + App.Vector(-30.689360, 7.107538, 0), + ), + False, + ) ActiveSketch.solve() ActiveSketch.exposeInternalGeometry(0) ActiveSketch.solve() - ActiveSketch.movePoint(0,0,App.Vector(-26.266434,14.345055,0),0) + ActiveSketch.movePoint(0, 0, App.Vector(-26.266434, 14.345055, 0), 0) ActiveSketch.solve() - ActiveSketch.addConstraint(Sketcher.Constraint('Block',0)) # Block the Ellipse in place - ActiveSketch.addConstraint(Sketcher.Constraint('Block',1)) # Block the major axis in place (on purpose) + ActiveSketch.addConstraint(Sketcher.Constraint("Block", 0)) # Block the Ellipse in place + ActiveSketch.addConstraint( + Sketcher.Constraint("Block", 1) + ) # Block the major axis in place (on purpose) status = ActiveSketch.solve() - self.failUnless(status == 0) # no redundants/conflicts/convergence issues - ActiveSketch.addConstraint(Sketcher.Constraint('Distance',1,27.277350)) # Length of major axis - ActiveSketch.setDriving(6,True) # ensure length is driving (because pre-existing block constraint on major axis) - ActiveSketch.setDatum(6,App.Units.Quantity('28.000000 mm')) + self.failUnless(status == 0) # no redundants/conflicts/convergence issues + ActiveSketch.addConstraint( + Sketcher.Constraint("Distance", 1, 27.277350) + ) # Length of major axis + ActiveSketch.setDriving( + 6, True + ) # ensure length is driving (because pre-existing block constraint on major axis) + ActiveSketch.setDatum(6, App.Units.Quantity("28.000000 mm")) status = ActiveSketch.solve() - self.failUnless(status == 0) # no redundants/conflicts/convergence issues - ActiveSketch.addConstraint(Sketcher.Constraint('Distance',2,11.747233)) # Length of minor axis - ActiveSketch.setDatum(7,App.Units.Quantity('15.000000 mm')) + self.failUnless(status == 0) # no redundants/conflicts/convergence issues + ActiveSketch.addConstraint( + Sketcher.Constraint("Distance", 2, 11.747233) + ) # Length of minor axis + ActiveSketch.setDatum(7, App.Units.Quantity("15.000000 mm")) ActiveSketch.solve() - self.failUnless(status == 0) # no redundants/conflicts/convergence issues - ActiveSketch.addConstraint(Sketcher.Constraint('Block',2)) + self.failUnless(status == 0) # no redundants/conflicts/convergence issues + ActiveSketch.addConstraint(Sketcher.Constraint("Block", 2)) ActiveSketch.solve() - self.failUnless(status == 0) # no redundants/conflicts/convergence issues - ActiveSketch.addConstraint(Sketcher.Constraint('Horizontal',1)) # Make major axis horizontal (together with horizontal and length driving constraints) + self.failUnless(status == 0) # no redundants/conflicts/convergence issues + ActiveSketch.addConstraint( + Sketcher.Constraint("Horizontal", 1) + ) # Make major axis horizontal (together with horizontal and length driving constraints) ActiveSketch.solve() - self.failUnless(status == 0) # no redundants/conflicts/convergence issues - ActiveSketch.addConstraint(Sketcher.Constraint('DistanceX',0,3,-1,1,27.655024)) # Locate Ellipse center - ActiveSketch.addConstraint(Sketcher.Constraint('DistanceY',0,3,-1,1,-20.877021)) - ActiveSketch.setDatum(10,App.Units.Quantity('25.000000 mm')) - ActiveSketch.setDatum(11,App.Units.Quantity('-20.000000 mm')) + self.failUnless(status == 0) # no redundants/conflicts/convergence issues + ActiveSketch.addConstraint( + Sketcher.Constraint("DistanceX", 0, 3, -1, 1, 27.655024) + ) # Locate Ellipse center + ActiveSketch.addConstraint(Sketcher.Constraint("DistanceY", 0, 3, -1, 1, -20.877021)) + ActiveSketch.setDatum(10, App.Units.Quantity("25.000000 mm")) + ActiveSketch.setDatum(11, App.Units.Quantity("-20.000000 mm")) ActiveSketch.solve() - self.failUnless(status == 0) # no redundants/conflicts/convergence issues + self.failUnless(status == 0) # no redundants/conflicts/convergence issues FreeCAD.closeDocument(self.Doc3.Name) def testThreeLinesWithCoincidences_1(self): - sketch = self.Doc.addObject('Sketcher::SketchObject','Sketch') + sketch = self.Doc.addObject("Sketcher::SketchObject", "Sketch") CreateThreeLinesWithCommonPoint(sketch) - sketch.addConstraint(Sketcher.Constraint('Coincident',1,2,0,2)) - sketch.addConstraint(Sketcher.Constraint('Coincident',2,1,0,2)) + sketch.addConstraint(Sketcher.Constraint("Coincident", 1, 2, 0, 2)) + sketch.addConstraint(Sketcher.Constraint("Coincident", 2, 1, 0, 2)) self.assertEqual(sketch.detectMissingPointOnPointConstraints(0.0001), 0) # Same as in testThreeLinesWithCoincidences_1 but set the constraints on # different lines def testThreeLinesWithCoincidences_2(self): - sketch = self.Doc.addObject('Sketcher::SketchObject','Sketch') + sketch = self.Doc.addObject("Sketcher::SketchObject", "Sketch") CreateThreeLinesWithCommonPoint(sketch) - sketch.addConstraint(Sketcher.Constraint('Coincident',1,2,0,2)) - sketch.addConstraint(Sketcher.Constraint('Coincident',2,1,1,2)) + sketch.addConstraint(Sketcher.Constraint("Coincident", 1, 2, 0, 2)) + sketch.addConstraint(Sketcher.Constraint("Coincident", 2, 1, 1, 2)) self.assertEqual(sketch.detectMissingPointOnPointConstraints(0.0001), 0) def testCircleToLineDistance_Driving_Passant(self): - sketch = self.Doc.addObject('Sketcher::SketchObject','Sketch') + sketch = self.Doc.addObject("Sketcher::SketchObject", "Sketch") radius = 20 circle = Part.Circle(vec(0, 0), xy_normal, radius) - line = Part.LineSegment(vec(-radius, 2*radius), vec(radius, 2*radius)) + line = Part.LineSegment(vec(-radius, 2 * radius), vec(radius, 2 * radius)) c_idx = sketch.addGeometry(circle) l_idx = sketch.addGeometry(line) # use a positive distance, other than the initial distance of the line - wanted_distance = radius/2 - sketch.addConstraint(Sketcher.Constraint('Distance', c_idx, l_idx, wanted_distance)) + wanted_distance = radius / 2 + sketch.addConstraint(Sketcher.Constraint("Distance", c_idx, l_idx, wanted_distance)) self.assertSuccessfulSolve(sketch) c_shape = sketch.Geometry[c_idx].toShape() l_shape = sketch.Geometry[l_idx].toShape() @@ -292,40 +437,48 @@ class TestSketcherSolver(unittest.TestCase): @unittest.skip("Support for secants still under discussion, see comments in PR 9044") def testCircleToLineDistance_Driving_Secant(self): - sketch = self.Doc.addObject('Sketcher::SketchObject','Sketch') + sketch = self.Doc.addObject("Sketcher::SketchObject", "Sketch") radius = 20 c_idx = sketch.addGeometry(Part.Circle(vec(0, 0), xy_normal, radius)) - l_idx = sketch.addGeometry(Part.LineSegment(vec(-radius, 2*radius), vec(radius, 2*radius))) + l_idx = sketch.addGeometry( + Part.LineSegment(vec(-radius, 2 * radius), vec(radius, 2 * radius)) + ) # use a negative distance to tell "line is within the circle" - wanted_distance = -radius/2 - sketch.addConstraint(Sketcher.Constraint('Distance', c_idx, l_idx, wanted_distance)) + wanted_distance = -radius / 2 + sketch.addConstraint(Sketcher.Constraint("Distance", c_idx, l_idx, wanted_distance)) self.assertSuccessfulSolve(sketch) c_shape = sketch.Geometry[c_idx].toShape() l_shape = sketch.Geometry[l_idx].toShape() - self.assertShapeDistance(c_shape, l_shape, 0) # secant intersects circle, thus no distance + self.assertShapeDistance(c_shape, l_shape, 0) # secant intersects circle, thus no distance def testCircleToLineDistance_Reference_Secant(self): - sketch = self.Doc.addObject('Sketcher::SketchObject','Sketch') + sketch = self.Doc.addObject("Sketcher::SketchObject", "Sketch") radius = 20 c_idx = sketch.addGeometry(Part.Circle(vec(0, 0), xy_normal, radius)) - l_idx = sketch.addGeometry(Part.LineSegment(vec(-radius, radius/2), vec(radius, radius/2))) + l_idx = sketch.addGeometry( + Part.LineSegment(vec(-radius, radius / 2), vec(radius, radius / 2)) + ) # The block constraints are required to ensure the geometry does not move. # Without this, the solver may find another valid solution than what we assert. - sketch.addConstraint([ - Sketcher.Constraint('Block', c_idx), - Sketcher.Constraint('Block', l_idx)]) + sketch.addConstraint( + [Sketcher.Constraint("Block", c_idx), Sketcher.Constraint("Block", l_idx)] + ) # use a negative distance to tell "line is within the circle" - expected_distance = -radius/2 # note that we don't set this in the constraint below! + expected_distance = -radius / 2 # note that we don't set this in the constraint below! # TODO: addConstraint(constraint) triggers a solve (for godd reasons) however, this way # one cannot add non-driving constraints. In contrast, addConstraint(list(constraint)) # does not solve automatically, thus we use this "overload". # Much nicer would be an addConstraint(constraint, isReference=False), like addGeometry - dist_idx = sketch.addConstraint([Sketcher.Constraint('Distance', c_idx, l_idx, 0)])[0] + dist_idx = sketch.addConstraint([Sketcher.Constraint("Distance", c_idx, l_idx, 0)])[0] sketch.setDriving(dist_idx, False) self.assertSuccessfulSolve(sketch) actual_distance = sketch.Constraints[dist_idx].Value - self.assertAlmostEqual(expected_distance, actual_distance, delta=Precision.confusion(), - msg="Reference constraint did not return the expected distance.") + self.assertAlmostEqual( + expected_distance, + actual_distance, + delta=Precision.confusion(), + msg="Reference constraint did not return the expected distance.", + ) def assertSuccessfulSolve(self, sketch, msg=None): status = sketch.solve() @@ -334,11 +487,14 @@ class TestSketcherSolver(unittest.TestCase): def assertShapeDistance(self, shape1, shape2, expected_distance, msg=None): distance, _, _ = shape1.distToShape(shape2) - self.assertAlmostEqual(distance, expected_distance, + self.assertAlmostEqual( + distance, + expected_distance, delta=Precision.confusion(), - msg=msg or "The given shapes are not spaced by the expected distance.") + msg=msg or "The given shapes are not spaced by the expected distance.", + ) def tearDown(self): - #closing doc + # closing doc FreeCAD.closeDocument("SketchSolverTest") - #print ("omit closing document for debugging") + # print ("omit closing document for debugging")