From 30a93b648bba43733cc102346371de86ff503ae3 Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Fri, 12 Feb 2021 07:25:20 +0100 Subject: [PATCH] Sketcher: Coverity fix in Sketch::analyseBlockedGeometry ======================================================== Users chennes and hyarion made me aware of this covereity issue: Fixes Coverity: geoit can be end() when dereferenced https://github.com/FreeCAD/FreeCAD/pull/4429/files# When analysing the block where the dereferrencing appears, it appears that it is a left-over that no longer makes sense: - The algorithm classifies block constraints into those that are not affected by any other driving constraint and those that are affected by other driving constraints. - The offending block deals with internal aligned geometry, thus per definition has a driving internal alignment constraint, for which the previous block already set the need of post-analysis. - No matter what, the geometries, the complex one and the internal one will have at least the driving internal alignment constraint, so they cannot become "not affected by any other driving constraint". - If the geometry had a block constraint on it, it was already added for post-analysis in the previous block. If it did not have one block constraint, the fact that it is internal aligned geometry is an irrelevant consideration. Probably there was a point during development when this made sense, but with the current post-analysis, it does not appear to make sense anymore. So the block was removed. This commit adds a unit test for blocked geometry (new block constraint). --- src/Mod/Sketcher/App/Sketch.cpp | 51 +-- .../SketcherTests/TestSketcherSolver.py | 341 ++++++++++-------- 2 files changed, 199 insertions(+), 193 deletions(-) diff --git a/src/Mod/Sketcher/App/Sketch.cpp b/src/Mod/Sketcher/App/Sketch.cpp index 86a21cb61c..f783918c27 100644 --- a/src/Mod/Sketcher/App/Sketch.cpp +++ b/src/Mod/Sketcher/App/Sketch.cpp @@ -138,7 +138,9 @@ bool Sketch::analyseBlockedGeometry( const std::vector &intern std::vector &onlyblockedGeometry, std::vector &blockedGeoIds) const { - bool isSomethingBlocked = false; + // To understand this function read the documentation in Sketch.h + // It is important that "onlyblockedGeometry" ONLY identifies blocked geometry + // that is not affected by any other driving constraint bool doesBlockAffectOtherConstraints = false; int geoindex = 0; @@ -152,7 +154,7 @@ bool Sketch::analyseBlockedGeometry( const std::vector &intern // is block driving if( c->Type == Sketcher::Block && c->isDriving && c->First == geoindex) blockisDriving = true; - + // We have another driving constraint (which may be InternalAlignment) if( c->Type != Sketcher::Block && c->isDriving && (c->First == geoindex || c->Second == geoindex || c->Third == geoindex) ) blockOnly = false; @@ -161,12 +163,10 @@ bool Sketch::analyseBlockedGeometry( const std::vector &intern if(blockisDriving) { if(blockOnly) { onlyblockedGeometry[geoindex] = true; // we pre-fix this geometry - isSomethingBlocked = true; } else { // we will have to pos-analyse the first diagnose result for these geometries // in order to avoid redundant constraints - isSomethingBlocked = true; doesBlockAffectOtherConstraints = true; blockedGeoIds.push_back(geoindex); } @@ -176,39 +176,6 @@ bool Sketch::analyseBlockedGeometry( const std::vector &intern geoindex++; } - if(isSomethingBlocked) { - - // look for internal geometry linked IAs - for(auto c : constraintList) { - if(c->Type == InternalAlignment) { - - auto geoit = std::find(blockedGeoIds.begin(),blockedGeoIds.end(),c->Second); - - if(geoit != blockedGeoIds.end() || onlyblockedGeometry[c->Second]) { // internal alignment geometry found, add to list - // check if pre-fix or post-analyses - bool blockAffectedOnly = true; - - for(auto ic : constraintList) { - // there is another driving constraint - if( ic->Type != Sketcher::Block && ic->isDriving && - (ic->First == c->First || ic->Second == c->First || ic->Third == c->First)) - blockAffectedOnly = false; - } - - if(blockAffectedOnly) { - onlyblockedGeometry[c->Second] = true; // we pre-fix this geometry - } - else { - // we will have to post-analyse the first diagnose result for these geometries - // in order to avoid redundant constraints - doesBlockAffectOtherConstraints = true; - blockedGeoIds.push_back(*geoit); - } - } - } - } - } - return doesBlockAffectOtherConstraints; } @@ -247,19 +214,23 @@ int Sketch::setUpSketch(const std::vector &GeoList, Base::Console().Log("\nOnlyBlocked GeoIds:"); size_t i = 0; + bool found = false; for(; i < onlyBlockedGeometry.size(); i++) { - if(onlyBlockedGeometry[i]) + if(onlyBlockedGeometry[i]) { Base::Console().Log("\n GeoId=%d", i); + found = true; + } } - if( i == 0) + if(found) Base::Console().Log("\n None"); Base::Console().Log("\nNotOnlyBlocked GeoIds:"); i = 0; for(; i < blockedGeoIds.size(); i++) Base::Console().Log("\n GeoId=%d", blockedGeoIds[i]); - if( i == 0) + if(i == 0) Base::Console().Log("\n None"); + Base::Console().Log("\n"); #endif //DEBUG_BLOCK_CONSTRAINT addGeometry(intGeoList,onlyBlockedGeometry); diff --git a/src/Mod/Sketcher/SketcherTests/TestSketcherSolver.py b/src/Mod/Sketcher/SketcherTests/TestSketcherSolver.py index 90a0e42cf0..9b99266dbb 100644 --- a/src/Mod/Sketcher/SketcherTests/TestSketcherSolver.py +++ b/src/Mod/Sketcher/SketcherTests/TestSketcherSolver.py @@ -35,92 +35,90 @@ def CreateRectangleSketch(SketchFeature, corner, lengths): 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.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))) - # 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)) - # add dimensions - SketchFeature.addConstraint(Sketcher.Constraint('Distance',1,81.370787)) - SketchFeature.addConstraint(Sketcher.Constraint('Distance',0,187.573036)) + 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)) + # add dimensions + 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)) #--------------------------------------------------------------------------- # define the test cases to test the FreeCAD Sketcher module @@ -128,89 +126,126 @@ def CreateSlotPlateInnerSet(SketchFeature): class TestSketcherSolver(unittest.TestCase): - def setUp(self): - self.Doc = FreeCAD.newDocument("SketchSolverTest") + def setUp(self): + self.Doc = FreeCAD.newDocument("SketchSolverTest") - def testBoxCase(self): - 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)) - # fully constrain - 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') - CreateSlotPlateSet(self.Slot) - self.Doc.recompute() - # test if all edges created - self.failUnless(len(self.Slot.Shape.Edges) == 4) - CreateSlotPlateInnerSet(self.Slot) - self.Doc.recompute() - self.failUnless(len(self.Slot.Shape.Edges) == 9) + def testBoxCase(self): + 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)) + # fully constrain + self.Box.addConstraint(Sketcher.Constraint('DistanceX',1,2,90.0)) + self.Box.addConstraint(Sketcher.Constraint('DistanceY',1,2,-50.0)) + self.Doc.recompute() - 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.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.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') - FreeCAD.closeDocument("Issue3245") + def testSlotCase(self): + self.Slot = self.Doc.addObject('Sketcher::SketchObject','SketchSlot') + CreateSlotPlateSet(self.Slot) + self.Doc.recompute() + # test if all edges created + self.failUnless(len(self.Slot.Shape.Edges) == 4) + CreateSlotPlateInnerSet(self.Slot) + self.Doc.recompute() + self.failUnless(len(self.Slot.Shape.Edges) == 9) - 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.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) - 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)) - 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.delConstraint(8) - values = d = {key: value for (key, value) in self.Doc2.Sketch.ExpressionEngine} - self.Doc2.recompute() - self.failUnless(len(values) == 0) - FreeCAD.closeDocument("Issue3245") - - def tearDown(self): - #closing doc - FreeCAD.closeDocument("SketchSolverTest") - #print ("omit closing document for debugging") + 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.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.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') + 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.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) + 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)) + 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.delConstraint(8) + values = d = {key: value for (key, value) in self.Doc2.Sketch.ExpressionEngine} + self.Doc2.recompute() + self.failUnless(len(values) == 0) + FreeCAD.closeDocument("Issue3245") + + 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.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.solve() + ActiveSketch.exposeInternalGeometry(0) + ActiveSketch.solve() + 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) + 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')) + 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')) + ActiveSketch.solve() + 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) + 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')) + ActiveSketch.solve() + self.failUnless(status == 0) # no redundants/conflicts/convergence issues + + def tearDown(self): + #closing doc + FreeCAD.closeDocument("SketchSolverTest") + #print ("omit closing document for debugging")