From 47c0859c1b702b6c7d1dcf5922317c4f325f5d2e Mon Sep 17 00:00:00 2001 From: Abdullah Tahiri Date: Tue, 8 Sep 2015 20:08:47 +0200 Subject: [PATCH] Sketcher: Bug fixes: inability to create links to external geometry ================================================================= First bug: Inability to create links to external geometry as described here: http://forum.freecadweb.org/download/file.php?id=16668 Second bug: FC crashes on changing the support after having imported external geometry as described here: http://forum.freecadweb.org/viewtopic.php?f=10&t=12380 and solving this ticket: http://www.freecadweb.org/tracker/view.php?id=2225 Solution to first bug: If for some reason a sketch ends up having a list of external geometries (property) that can not be recreated (rebuilt), they remain latent, do not show the external elements in the elements widget or in the screen and prevent adding the elements again. In cases where the saved file contains invalid external geometry links (which will give raise to a handled exception that would prevent external geometry creation), this condition gets detected during restore and the invalid links are deleted before external geometry creation, so as to allow the rest of external links to be recreated. Solution to second bug: It is also related to invalid external links (the link was existing, but upon change on the support, it is possible that an external edge is no longer valid, reduction of edges in support). This situation is detected upon entering into edit mode, and the invalid ones are deleted. Note that there is still the possibility for the user to remap an invalid sketch BEFORE editing, if the remapping is successful, it may not be necessary to delete links (all depends on the specific case). --- src/Mod/Sketcher/App/SketchObject.cpp | 97 ++++++++++++++++++++- src/Mod/Sketcher/App/SketchObject.h | 4 + src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 4 + 3 files changed, 104 insertions(+), 1 deletion(-) diff --git a/src/Mod/Sketcher/App/SketchObject.cpp b/src/Mod/Sketcher/App/SketchObject.cpp index 7aaa2ab10..249616f1c 100644 --- a/src/Mod/Sketcher/App/SketchObject.cpp +++ b/src/Mod/Sketcher/App/SketchObject.cpp @@ -2763,6 +2763,98 @@ const Part::Geometry* SketchObject::getGeometry(int GeoId) const return 0; } +bool SketchObject::evaluateSupport(void) +{ + // returns false if the shape if broken, null or non-planar + Part::Feature *part = static_cast(Support.getValue()); + if (!part || !part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + return false; + + const std::vector &sub = Support.getSubValues(); + assert(sub.size()==1); + // get the selected sub shape (a Face) + const Part::TopoShape &shape = part->Shape.getShape(); + + if (shape._Shape.IsNull()) + return false; + + TopoDS_Shape sh; + try { + sh = shape.getSubShape(sub[0].c_str()); + } + catch (Standard_Failure) { + return false; + } + const TopoDS_Face &face = TopoDS::Face(sh); + if (face.IsNull()) + return false; + + BRepAdaptor_Surface adapt(face); + if (adapt.GetType() != GeomAbs_Plane) + return false; // No planar face + + return true; +} + +void SketchObject::validateExternalLinks(void) +{ + std::vector Objects = ExternalGeometry.getValues(); + std::vector SubElements = ExternalGeometry.getSubValues(); + + bool rebuild = false ; + + for (int i=0; i < int(Objects.size()); i++) { + const App::DocumentObject *Obj=Objects[i]; + const std::string SubElement=SubElements[i]; + + const Part::Feature *refObj=static_cast(Obj); + const Part::TopoShape& refShape=refObj->Shape.getShape(); + + TopoDS_Shape refSubShape; + try { + refSubShape = refShape.getSubShape(SubElement.c_str()); + } + catch (Standard_Failure) { + rebuild = true ; + Objects.erase(Objects.begin()+i); + SubElements.erase(SubElements.begin()+i); + + const std::vector< Constraint * > &constraints = Constraints.getValues(); + std::vector< Constraint * > newConstraints(0); + int GeoId = -3 - i; + for (std::vector::const_iterator it = constraints.begin(); + it != constraints.end(); ++it) { + if ((*it)->First != GeoId && (*it)->Second != GeoId && (*it)->Third != GeoId) { + Constraint *copiedConstr = (*it)->clone(); + if (copiedConstr->First < GeoId && + copiedConstr->First != Constraint::GeoUndef) + copiedConstr->First += 1; + if (copiedConstr->Second < GeoId && + copiedConstr->Second != Constraint::GeoUndef) + copiedConstr->Second += 1; + if (copiedConstr->Third < GeoId && + copiedConstr->Third != Constraint::GeoUndef) + copiedConstr->Third += 1; + + newConstraints.push_back(copiedConstr); + } + } + + Constraints.setValues(newConstraints); + i--; // we deleted an item, so the next one took its place + } + } + + if (rebuild) { + ExternalGeometry.setValues(Objects,SubElements); + rebuildExternalGeometry(); + Constraints.acceptGeometry(getCompleteGeometry()); + rebuildVertexIndex(); + solve(true); // we have to update this sketch and everything depending on it. + } + +} + void SketchObject::rebuildExternalGeometry(void) { // get the actual lists of the externals @@ -3570,7 +3662,10 @@ void SketchObject::onChanged(const App::Property* prop) void SketchObject::onDocumentRestored() { try { - rebuildExternalGeometry(); + if(Support.getValue()) { + validateExternalLinks(); + rebuildExternalGeometry(); + } Constraints.acceptGeometry(getCompleteGeometry()); } catch (...) { diff --git a/src/Mod/Sketcher/App/SketchObject.h b/src/Mod/Sketcher/App/SketchObject.h index 854921471..43061bce0 100644 --- a/src/Mod/Sketcher/App/SketchObject.h +++ b/src/Mod/Sketcher/App/SketchObject.h @@ -222,6 +222,10 @@ public: bool evaluateConstraints() const; /// Remove constraints with invalid indexes void validateConstraints(); + /// Checks if support is valid + bool evaluateSupport(void); + /// validate External Links (remove invalid external links) + void validateExternalLinks(void); /// gets DoF of last solver execution inline int getLastDoF() const {return lastDoF;} diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index c3859ec2b..5c5debe53 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -4223,6 +4223,10 @@ bool ViewProviderSketch::setEdit(int ModNum) // The false parameter indicates that the geometry of the SketchObject shall not be updateData // so as not to trigger an onChanged that would set the document as modified and trigger a recompute // if we just close the sketch without touching anything. + if(getSketchObject()->Support.getValue()) + if (!getSketchObject()->evaluateSupport()) + getSketchObject()->validateExternalLinks(); + getSketchObject()->solve(false); UpdateSolverInformation(); draw(false);