diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index cd43d8d1e9..0324c54a20 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -266,9 +266,11 @@ App::DocumentObjectExecReturn* SketchObject::execute() Constraints.acceptGeometry(getCompleteGeometry()); } catch (const Base::Exception& e) { - Base::Console().Error("%s\nClear constraints to external geometry\n", e.what()); + // 9/16/24: We used to clear the constraints here, but we no longer want to do that + // as missing reference geometry is not considered an error while we sort out sketcher UI. + // Base::Console().Error("%s\nClear constraints to external geometry\n", e.what()); // we cannot trust the constraints of external geometries, so remove them - delConstraintsToExternal(); + // delConstraintsToExternal(); } // This includes a regular solve including full geometry update, except when an error diff --git a/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp b/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp index 72912cfb53..02ba759674 100644 --- a/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp +++ b/src/Mod/Sketcher/Gui/EditModeGeometryCoinManager.cpp @@ -44,6 +44,7 @@ #include "EditModeGeometryCoinConverter.h" #include "EditModeGeometryCoinManager.h" #include "ViewProviderSketchCoinAttorney.h" +#include "Mod/Sketcher/App/ExternalGeometryFacade.h" using namespace SketcherGui; @@ -414,7 +415,15 @@ void EditModeGeometryCoinManager::updateGeometryColor(const GeoListFacade& geoli } } else if (geometryLayerParameters.isExternalSubLayer(t)) { - color[i] = drawingParameters.CurveExternalColor; + auto geom = geolistfacade.getGeometryFacadeFromGeoId(GeoId); + auto egf = ExternalGeometryFacade::getFacade(geom->clone()); + auto ref = egf->getRef(); + if (egf->testFlag(ExternalGeometryExtension::Missing)) { + color[i] = drawingParameters.InvalidSketchColor; + } + else { + color[i] = drawingParameters.CurveExternalColor; + } for (int k = j; j < k + indexes; j++) { verts[j].getValue(x, y, z); verts[j] = SbVec3f(x, y, viewOrientationFactor * zExtLine); diff --git a/src/Mod/Sketcher/SketcherTests/TestSketchValidateCoincidents.py b/src/Mod/Sketcher/SketcherTests/TestSketchValidateCoincidents.py index 682206a53d..afada0404c 100644 --- a/src/Mod/Sketcher/SketcherTests/TestSketchValidateCoincidents.py +++ b/src/Mod/Sketcher/SketcherTests/TestSketchValidateCoincidents.py @@ -128,6 +128,85 @@ class TestSketchValidateCoincidents(unittest.TestCase): del geo0, geo1 del sketch, c + def testExternalGeoDeletion(self): + """Make sure that we don't remove External Geometry references to deleted geometry. + See https://github.com/FreeCAD/FreeCAD/issues/16361""" + doc = App.ActiveDocument + doc.addObject("PartDesign::Body", "Body") + doc.Body.Label = "Body" + doc.recompute() + doc.Body.newObject("Sketcher::SketchObject", "Sketch") + doc.Sketch.AttachmentSupport = (doc.XY_Plane, [""]) + doc.Sketch.MapMode = "FlatFace" + doc.recompute() + geoList = [] + geoList.append( + Part.LineSegment( + App.Vector(7.548310, 5.193216, 0.000000), App.Vector(31.461353, 5.193216, 0.000000) + ) + ) + geoList.append( + Part.LineSegment( + App.Vector(31.461353, 5.193216, 0.000000), + App.Vector(31.461353, 20.652151, 0.000000), + ) + ) + geoList.append( + Part.LineSegment( + App.Vector(31.461353, 20.652151, 0.000000), + App.Vector(7.548310, 20.652151, 0.000000), + ) + ) + geoList.append( + Part.LineSegment( + App.Vector(7.548310, 20.652151, 0.000000), App.Vector(7.548310, 5.193216, 0.000000) + ) + ) + doc.Sketch.addGeometry(geoList, False) + del geoList + constraintList = [] + constraintList.append(Sketcher.Constraint("Coincident", 0, 2, 1, 1)) + constraintList.append(Sketcher.Constraint("Coincident", 1, 2, 2, 1)) + constraintList.append(Sketcher.Constraint("Coincident", 2, 2, 3, 1)) + constraintList.append(Sketcher.Constraint("Coincident", 3, 2, 0, 1)) + constraintList.append(Sketcher.Constraint("Horizontal", 0)) + constraintList.append(Sketcher.Constraint("Horizontal", 2)) + constraintList.append(Sketcher.Constraint("Vertical", 1)) + constraintList.append(Sketcher.Constraint("Vertical", 3)) + doc.Sketch.addConstraint(constraintList) + del constraintList + constraintList = [] + doc.recompute() + doc.Body.newObject("Sketcher::SketchObject", "Sketch001") + doc.Sketch001.AttachmentSupport = (doc.XY_Plane, [""]) + doc.Sketch001.MapMode = "FlatFace" + doc.recompute() + doc.Sketch001.addExternal("Sketch", "Edge3") + geoList = [] + geoList.append( + Part.LineSegment( + App.Vector(33.192780, 22.530144, 0.000000), + App.Vector(38.493977, 32.289181, 0.000000), + ) + ) + doc.Sketch001.addGeometry(geoList, False) + del geoList + constraintList = [] + doc.Sketch001.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -3, 1)) + doc.recompute() + doc.Sketch.delGeometries([1]) + doc.Sketch.delGeometries([1]) + doc.recompute() + doc.Sketch001.addConstraint(Sketcher.Constraint("Coincident", 0, 1, -3, 1)) + doc.recompute() + # Assert + self.assertEqual(len(doc.Sketch001.Constraints), 2) # Still have the constraints + self.assertEqual(len(doc.Sketch001.ExternalGeometry), 0) + self.assertEqual(len(doc.Sketch001.Geometry), 1) + self.assertEqual( + len(doc.Sketch001.ExternalGeo), 3 + ) # Two axis, plus one the reference to deleted geometry + def tearDown(self): # closing doc FreeCAD.closeDocument(self.Doc.Name)