From 18183bc79bb22adbde2e0dd6b36f03da75e16a28 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 15 Jun 2019 15:07:52 +0200 Subject: [PATCH] extend ShapeBinder to also handle Origin features --- src/Mod/PartDesign/App/ShapeBinder.cpp | 128 ++++++++++++------ src/Mod/PartDesign/App/ShapeBinder.h | 4 +- src/Mod/PartDesign/Gui/TaskShapeBinder.cpp | 6 +- .../Gui/ViewProviderShapeBinder.cpp | 12 +- 4 files changed, 96 insertions(+), 54 deletions(-) diff --git a/src/Mod/PartDesign/App/ShapeBinder.cpp b/src/Mod/PartDesign/App/ShapeBinder.cpp index b428083c1b..dbb3c89c94 100644 --- a/src/Mod/PartDesign/App/ShapeBinder.cpp +++ b/src/Mod/PartDesign/App/ShapeBinder.cpp @@ -25,13 +25,17 @@ #ifndef _PreComp_ # include # include +# include +# include # include +# include # include #endif #include "ShapeBinder.h" #include #include +#include #include #ifndef M_PI @@ -69,13 +73,14 @@ short int ShapeBinder::mustExecute(void) const { App::DocumentObjectExecReturn* ShapeBinder::execute(void) { if (!this->isRestoring()) { - Part::Feature* obj = nullptr; + App::GeoFeature* obj = nullptr; std::vector subs; ShapeBinder::getFilteredReferences(&Support, obj, subs); + //if we have a link we rebuild the shape, but we change nothing if we are a simple copy if (obj) { - Part::TopoShape shape = ShapeBinder::buildShapeFromReferences(obj, subs); + Part::TopoShape shape(ShapeBinder::buildShapeFromReferences(obj, subs)); //now, shape is in object's CS, and includes local Placement of obj but nothing else. if (TraceSupport.getValue()) { @@ -96,7 +101,7 @@ App::DocumentObjectExecReturn* ShapeBinder::execute(void) { return Part::Feature::execute(); } -void ShapeBinder::getFilteredReferences(App::PropertyLinkSubList* prop, Part::Feature*& obj, +void ShapeBinder::getFilteredReferences(App::PropertyLinkSubList* prop, App::GeoFeature*& obj, std::vector< std::string >& subobjects) { obj = nullptr; @@ -111,63 +116,96 @@ void ShapeBinder::getFilteredReferences(App::PropertyLinkSubList* prop, Part::Fe //we only allow one part feature, so get the first one we find size_t index = 0; - while (index < objs.size() && !objs[index]->isDerivedFrom(Part::Feature::getClassTypeId())) + for (auto* it : objs) { + if (it && it->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { + obj = static_cast(it); + break; + } index++; - - //do we have any part feature? - if (index >= objs.size()) - return; - - obj = static_cast(objs[index]); - - //if we have no subshpape we use the whole shape - if (subs[index].empty()) { - return; } - //collect all subshapes for the object - index = 0; - for (std::string sub : subs) { + //do we have any part feature? + if (obj) { + //if we have no subshpape we use the whole shape + if (subs[index].empty()) { + return; + } - //we only allow subshapes from a single Part::Feature - if (objs[index] != obj) - continue; + //collect all subshapes for the object + for (index = 0; index < objs.size(); index++) { + //we only allow subshapes from a single Part::Feature + if (objs[index] != obj) + continue; - //in this mode the full shape is not allowed, as we already started the subshape - //processing - if (sub.empty()) - continue; + //in this mode the full shape is not allowed, as we already started the subshape + //processing + if (subs[index].empty()) + continue; - subobjects.push_back(sub); + subobjects.push_back(subs[index]); + } + } + else { + // search for Origin features + for (auto* it : objs) { + if (it && it->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) { + obj = static_cast(it); + break; + } + else if (it && it->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) { + obj = static_cast(it); + break; + } + } } } -Part::TopoShape ShapeBinder::buildShapeFromReferences( Part::Feature* obj, std::vector< std::string > subs) { +Part::TopoShape ShapeBinder::buildShapeFromReferences(App::GeoFeature* obj, std::vector< std::string > subs) { if (!obj) return TopoDS_Shape(); - if (subs.empty()) - return obj->Shape.getShape(); + if (obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { + Part::Feature* part = static_cast(obj); + if (subs.empty()) + return part->Shape.getValue(); - std::vector shapes; - for (std::string sub : subs) { - shapes.push_back(obj->Shape.getShape().getSubShape(sub.c_str())); - } - - if (shapes.size() == 1){ - //single subshape. Return directly. - return shapes[0]; - } else { - //multiple subshapes. Make a compound. - BRep_Builder builder; - TopoDS_Compound cmp; - builder.MakeCompound(cmp); - for(const TopoDS_Shape& sh : shapes){ - builder.Add(cmp, sh); + std::vector shapes; + for (std::string sub : subs) { + shapes.push_back(part->Shape.getShape().getSubShape(sub.c_str())); + } + + if (shapes.size() == 1) { + //single subshape. Return directly. + return shapes[0]; + } + else { + //multiple subshapes. Make a compound. + BRep_Builder builder; + TopoDS_Compound cmp; + builder.MakeCompound(cmp); + for(const TopoDS_Shape& sh : shapes){ + builder.Add(cmp, sh); + } + return cmp; } - return cmp; } + else if (obj->getTypeId().isDerivedFrom(App::Line::getClassTypeId())) { + gp_Lin line; + BRepBuilderAPI_MakeEdge mkEdge(line); + Part::TopoShape shape(mkEdge.Shape()); + shape.setPlacement(obj->Placement.getValue()); + return shape; + } + else if (obj->getTypeId().isDerivedFrom(App::Plane::getClassTypeId())) { + gp_Pln plane; + BRepBuilderAPI_MakeFace mkFace(plane); + Part::TopoShape shape(mkFace.Shape()); + shape.setPlacement(obj->Placement.getValue()); + return shape; + } + + return TopoDS_Shape(); } void ShapeBinder::handleChangedPropertyType(Base::XMLReader &reader, const char *TypeName, App::Property *prop) @@ -199,7 +237,7 @@ void ShapeBinder::slotChangedObject(const App::DocumentObject& Obj, const App::P if (!Prop.getTypeId().isDerivedFrom(App::PropertyPlacement::getClassTypeId())) return; - Part::Feature* obj = nullptr; + App::GeoFeature* obj = nullptr; std::vector subs; ShapeBinder::getFilteredReferences(&Support, obj, subs); if (obj) { diff --git a/src/Mod/PartDesign/App/ShapeBinder.h b/src/Mod/PartDesign/App/ShapeBinder.h index b5908e75f3..89484ad1fa 100644 --- a/src/Mod/PartDesign/App/ShapeBinder.h +++ b/src/Mod/PartDesign/App/ShapeBinder.h @@ -51,8 +51,7 @@ public: App::PropertyLinkSubListGlobal Support; App::PropertyBool TraceSupport; - static void getFilteredReferences(App::PropertyLinkSubList* prop, Part::Feature*& object, std::vector< std::string >& subobjects); - static Part::TopoShape buildShapeFromReferences(Feature* obj, std::vector< std::string > subs); + static void getFilteredReferences(App::PropertyLinkSubList* prop, App::GeoFeature*& object, std::vector< std::string >& subobjects); const char* getViewProviderName(void) const { return "PartDesignGui::ViewProviderShapeBinder"; @@ -66,6 +65,7 @@ protected: private: void slotChangedObject(const App::DocumentObject& Obj, const App::Property& Prop); virtual void onSettingDocument(); + static Part::TopoShape buildShapeFromReferences(App::GeoFeature* obj, std::vector< std::string > subs); typedef boost::signals2::connection Connection; Connection connectDocumentChangedObject; diff --git a/src/Mod/PartDesign/Gui/TaskShapeBinder.cpp b/src/Mod/PartDesign/Gui/TaskShapeBinder.cpp index 3a75e00533..a8eee96342 100644 --- a/src/Mod/PartDesign/Gui/TaskShapeBinder.cpp +++ b/src/Mod/PartDesign/Gui/TaskShapeBinder.cpp @@ -79,7 +79,7 @@ TaskShapeBinder::TaskShapeBinder(ViewProviderShapeBinder *view, bool /*newObj*/, vp = view; //add initial values - Part::Feature* obj = nullptr; + App::GeoFeature* obj = nullptr; std::vector subs; PartDesign::ShapeBinder::getFilteredReferences(&static_cast(vp->getObject())->Support, obj, subs); @@ -227,9 +227,9 @@ bool TaskShapeBinder::referenceSelected(const SelectionChanges& msg) const { std::string subName(msg.pSubName); Part::Feature* selectedObj = nullptr; - Part::Feature* obj = nullptr; + App::GeoFeature* obj = nullptr; std::vector refs; - + PartDesign::ShapeBinder::getFilteredReferences(&static_cast(vp->getObject())->Support, obj, refs); // get selected object diff --git a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp index c29be1c023..e69bc34fdd 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderShapeBinder.cpp @@ -124,14 +124,18 @@ void ViewProviderShapeBinder::unsetEdit(int ModNum) { void ViewProviderShapeBinder::highlightReferences(const bool on, bool /*auxiliary*/) { - Part::Feature* obj; + App::GeoFeature* obj = nullptr; std::vector subs; - if(getObject()->isDerivedFrom(PartDesign::ShapeBinder::getClassTypeId())) + if (getObject()->isDerivedFrom(PartDesign::ShapeBinder::getClassTypeId())) PartDesign::ShapeBinder::getFilteredReferences(&static_cast(getObject())->Support, obj, subs); else return; + // stop if not a Part feature was found + if (!obj || !obj->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) + return; + PartGui::ViewProviderPart* svp = dynamic_cast( Gui::Application::Instance->getViewProvider(obj)); if (svp == NULL) return; @@ -139,12 +143,12 @@ void ViewProviderShapeBinder::highlightReferences(const bool on, bool /*auxiliar if (on) { if (!subs.empty() && originalLineColors.empty()) { TopTools_IndexedMapOfShape eMap; - TopExp::MapShapes(obj->Shape.getValue(), TopAbs_EDGE, eMap); + TopExp::MapShapes(static_cast(obj)->Shape.getValue(), TopAbs_EDGE, eMap); originalLineColors = svp->LineColorArray.getValues(); std::vector lcolors = originalLineColors; lcolors.resize(eMap.Extent(), svp->LineColor.getValue()); - TopExp::MapShapes(obj->Shape.getValue(), TopAbs_FACE, eMap); + TopExp::MapShapes(static_cast(obj)->Shape.getValue(), TopAbs_FACE, eMap); originalFaceColors = svp->DiffuseColor.getValues(); std::vector fcolors = originalFaceColors; fcolors.resize(eMap.Extent(), svp->ShapeColor.getValue());