diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 875f04cd4..716597e2b 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -134,6 +134,7 @@ void PartExport initPart() Part::TopoShape ::init(); Part::PropertyPartShape ::init(); Part::PropertyGeometryList ::init(); + Part::PropertyShapeHistory ::init(); Part::PropertyFilletEdges ::init(); Part::Feature ::init(); diff --git a/src/Mod/Part/App/FeaturePartBoolean.cpp b/src/Mod/Part/App/FeaturePartBoolean.cpp index 7418db97a..1a2608797 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.cpp +++ b/src/Mod/Part/App/FeaturePartBoolean.cpp @@ -24,7 +24,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include -#include +# include #endif #include "FeaturePartBoolean.h" @@ -35,10 +35,13 @@ using namespace Part; PROPERTY_SOURCE_ABSTRACT(Part::Boolean, Part::Feature) -Boolean::Boolean(void) : myBoolOp(0) +Boolean::Boolean(void) { ADD_PROPERTY(Base,(0)); ADD_PROPERTY(Tool,(0)); + ADD_PROPERTY_TYPE(History,(ShapeHistory()), "Boolean", (App::PropertyType) + (App::Prop_Output|App::Prop_Transient|App::Prop_Hidden), "Shape history"); + History.setSize(0); } short Boolean::mustExecute() const @@ -77,14 +80,15 @@ App::DocumentObjectExecReturn *Boolean::execute(void) return new App::DocumentObjectExecReturn("Resulting shape is invalid"); } - // tmp. set boolean operation pointer - this->myBoolOp = mkBool.get(); + std::vector history; + history.push_back(buildHistory(*mkBool.get(), TopAbs_FACE, resShape, BaseShape)); + history.push_back(buildHistory(*mkBool.get(), TopAbs_FACE, resShape, ToolShape)); + this->Shape.setValue(resShape); - this->myBoolOp = 0; + this->History.setValues(history); return App::DocumentObject::StdReturn; } catch (...) { - this->myBoolOp = 0; return new App::DocumentObjectExecReturn("A fatal error occurred when running boolean operation"); } } diff --git a/src/Mod/Part/App/FeaturePartBoolean.h b/src/Mod/Part/App/FeaturePartBoolean.h index 13305dffe..2730af82f 100644 --- a/src/Mod/Part/App/FeaturePartBoolean.h +++ b/src/Mod/Part/App/FeaturePartBoolean.h @@ -41,6 +41,7 @@ public: App::PropertyLink Base; App::PropertyLink Tool; + PropertyShapeHistory History; /** @name methods overide Feature */ //@{ @@ -53,13 +54,9 @@ public: const char* getViewProviderName(void) const { return "PartGui::ViewProviderBoolean"; } - BRepAlgoAPI_BooleanOperation* getBooleanOperation() const { return myBoolOp; } protected: virtual BRepAlgoAPI_BooleanOperation* makeOperation(const TopoDS_Shape&, const TopoDS_Shape&) const = 0; - -private: - BRepAlgoAPI_BooleanOperation* myBoolOp; }; } diff --git a/src/Mod/Part/App/FeaturePartCommon.cpp b/src/Mod/Part/App/FeaturePartCommon.cpp index 1835cdfc1..ea4be0edd 100644 --- a/src/Mod/Part/App/FeaturePartCommon.cpp +++ b/src/Mod/Part/App/FeaturePartCommon.cpp @@ -56,6 +56,9 @@ MultiCommon::MultiCommon(void) { ADD_PROPERTY(Shapes,(0)); Shapes.setSize(0); + ADD_PROPERTY_TYPE(History,(ShapeHistory()), "Boolean", (App::PropertyType) + (App::Prop_Output|App::Prop_Transient|App::Prop_Hidden), "Shape history"); + History.setSize(0); } short MultiCommon::mustExecute() const @@ -78,6 +81,7 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void) } if (s.size() >= 2) { + std::vector history; TopoDS_Shape res = s.front(); for (std::vector::iterator it = s.begin()+1; it != s.end(); ++it) { // Let's call algorithm computing a fuse operation: @@ -86,10 +90,13 @@ App::DocumentObjectExecReturn *MultiCommon::execute(void) if (!mkCommon.IsDone()) throw Base::Exception("Intersection failed"); res = mkCommon.Shape(); + history.push_back(buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape1())); + history.push_back(buildHistory(mkCommon, TopAbs_FACE, res, mkCommon.Shape2())); } if (res.IsNull()) throw Base::Exception("Resulting shape is invalid"); this->Shape.setValue(res); + this->History.setValues(history); } else { throw Base::Exception("Not enough shape objects linked"); diff --git a/src/Mod/Part/App/FeaturePartCommon.h b/src/Mod/Part/App/FeaturePartCommon.h index 19df8cdeb..ccb568aed 100644 --- a/src/Mod/Part/App/FeaturePartCommon.h +++ b/src/Mod/Part/App/FeaturePartCommon.h @@ -53,6 +53,7 @@ public: MultiCommon(); App::PropertyLinkList Shapes; + PropertyShapeHistory History; /** @name methods override feature */ //@{ diff --git a/src/Mod/Part/App/FeaturePartFuse.cpp b/src/Mod/Part/App/FeaturePartFuse.cpp index ea25450fc..8493b7b88 100644 --- a/src/Mod/Part/App/FeaturePartFuse.cpp +++ b/src/Mod/Part/App/FeaturePartFuse.cpp @@ -56,6 +56,9 @@ MultiFuse::MultiFuse(void) { ADD_PROPERTY(Shapes,(0)); Shapes.setSize(0); + ADD_PROPERTY_TYPE(History,(ShapeHistory()), "Boolean", (App::PropertyType) + (App::Prop_Output|App::Prop_Transient|App::Prop_Hidden), "Shape history"); + History.setSize(0); } short MultiFuse::mustExecute() const @@ -79,6 +82,7 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void) if (s.size() >= 2) { try { + std::vector history; TopoDS_Shape res = s.front(); for (std::vector::iterator it = s.begin()+1; it != s.end(); ++it) { // Let's call algorithm computing a fuse operation: @@ -87,10 +91,13 @@ App::DocumentObjectExecReturn *MultiFuse::execute(void) if (!mkFuse.IsDone()) throw Base::Exception("Fusion failed"); res = mkFuse.Shape(); + history.push_back(buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape1())); + history.push_back(buildHistory(mkFuse, TopAbs_FACE, res, mkFuse.Shape2())); } if (res.IsNull()) throw Base::Exception("Resulting shape is invalid"); this->Shape.setValue(res); + this->History.setValues(history); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); diff --git a/src/Mod/Part/App/FeaturePartFuse.h b/src/Mod/Part/App/FeaturePartFuse.h index 7e2e88d32..f1c83bb6f 100644 --- a/src/Mod/Part/App/FeaturePartFuse.h +++ b/src/Mod/Part/App/FeaturePartFuse.h @@ -54,6 +54,7 @@ public: MultiFuse(); App::PropertyLinkList Shapes; + PropertyShapeHistory History; /** @name methods override feature */ //@{ diff --git a/src/Mod/Part/App/PartFeature.cpp b/src/Mod/Part/App/PartFeature.cpp index c9483f37c..e71edcc7d 100644 --- a/src/Mod/Part/App/PartFeature.cpp +++ b/src/Mod/Part/App/PartFeature.cpp @@ -26,6 +26,10 @@ #ifndef _PreComp_ # include # include +# include +# include +# include +# include #endif @@ -128,6 +132,57 @@ TopLoc_Location Feature::getLocation() const return TopLoc_Location(trf); } +ShapeHistory Feature::buildHistory(BRepBuilderAPI_MakeShape& mkShape, TopAbs_ShapeEnum type, + const TopoDS_Shape& newS, const TopoDS_Shape& oldS) +{ + ShapeHistory history; + history.type = type; + + TopTools_IndexedMapOfShape newM, oldM; + TopExp::MapShapes(newS, type, newM); + TopExp::MapShapes(oldS, type, oldM); + + for (int i=1; i<=oldM.Extent(); i++) { + bool modified=false, generated=false; + TopTools_ListIteratorOfListOfShape it; + for (it.Initialize(mkShape.Modified(oldM(i))); it.More(); it.Next()) { + modified = true; + for (int j=1; j<=newM.Extent(); j++) { + if (newM(j).IsPartner(it.Value())) { + history.modified[i-1].push_back(j-1); + break; + } + } + } + + for (it.Initialize(mkShape.Generated(oldM(i))); it.More(); it.Next()) { + generated = true; + for (int j=1; j<=newM.Extent(); j++) { + if (newM(j).IsPartner(it.Value())) { + history.generated[i-1].push_back(j-1); + break; + } + } + } + + if (!modified && !generated) { + if (mkShape.IsDeleted(oldM(i))) { + history.deleted.insert(i-1); + } + else { + for (int j=1; j<=newM.Extent(); j++) { + if (newM(j).IsPartner(oldM(i))) { + history.accepted[i-1] = j-1; + break; + } + } + } + } + } + + return history; +} + /// returns the type name of the ViewProvider const char* Feature::getViewProviderName(void) const { return "PartGui::ViewProviderPart"; diff --git a/src/Mod/Part/App/PartFeature.h b/src/Mod/Part/App/PartFeature.h index efa0b7a83..159f0473e 100644 --- a/src/Mod/Part/App/PartFeature.h +++ b/src/Mod/Part/App/PartFeature.h @@ -30,6 +30,8 @@ #include #include +class BRepBuilderAPI_MakeShape; + namespace Part { @@ -63,9 +65,9 @@ public: protected: void onChanged(const App::Property* prop); - -protected: TopLoc_Location getLocation() const; + ShapeHistory buildHistory(BRepBuilderAPI_MakeShape&, TopAbs_ShapeEnum type, + const TopoDS_Shape& newS, const TopoDS_Shape& oldS); }; class FilletBase : public Part::Feature diff --git a/src/Mod/Part/App/PropertyTopoShape.cpp b/src/Mod/Part/App/PropertyTopoShape.cpp index d0cc3981c..f3e83a809 100644 --- a/src/Mod/Part/App/PropertyTopoShape.cpp +++ b/src/Mod/Part/App/PropertyTopoShape.cpp @@ -343,6 +343,72 @@ void PropertyPartShape::RestoreDocFile(Base::Reader &reader) // ------------------------------------------------------------------------- +TYPESYSTEM_SOURCE(Part::PropertyShapeHistory , App::PropertyLists); + +PropertyShapeHistory::PropertyShapeHistory() +{ +} + +PropertyShapeHistory::~PropertyShapeHistory() +{ +} + +void PropertyShapeHistory::setValue(const ShapeHistory& sh) +{ + aboutToSetValue(); + _lValueList.resize(1); + _lValueList[0] = sh; + hasSetValue(); +} + +void PropertyShapeHistory::setValues(const std::vector& values) +{ + aboutToSetValue(); + _lValueList = values; + hasSetValue(); +} + +PyObject *PropertyShapeHistory::getPyObject(void) +{ + return Py::new_reference_to(Py::None()); +} + +void PropertyShapeHistory::setPyObject(PyObject *value) +{ +} + +void PropertyShapeHistory::Save (Base::Writer &writer) const +{ +} + +void PropertyShapeHistory::Restore(Base::XMLReader &reader) +{ +} + +void PropertyShapeHistory::SaveDocFile (Base::Writer &writer) const +{ +} + +void PropertyShapeHistory::RestoreDocFile(Base::Reader &reader) +{ +} + +App::Property *PropertyShapeHistory::Copy(void) const +{ + PropertyShapeHistory *p= new PropertyShapeHistory(); + p->_lValueList = _lValueList; + return p; +} + +void PropertyShapeHistory::Paste(const Property &from) +{ + aboutToSetValue(); + _lValueList = dynamic_cast(from)._lValueList; + hasSetValue(); +} + +// ------------------------------------------------------------------------- + TYPESYSTEM_SOURCE(Part::PropertyFilletEdges , App::PropertyLists); PropertyFilletEdges::PropertyFilletEdges() diff --git a/src/Mod/Part/App/PropertyTopoShape.h b/src/Mod/Part/App/PropertyTopoShape.h index 3113ed456..190a82d2a 100644 --- a/src/Mod/Part/App/PropertyTopoShape.h +++ b/src/Mod/Part/App/PropertyTopoShape.h @@ -21,12 +21,15 @@ ***************************************************************************/ -#ifndef PROPERTYTOPOSHAPE_H -#define PROPERTYTOPOSHAPE_H +#ifndef PART_PROPERTYTOPOSHAPE_H +#define PART_PROPERTYTOPOSHAPE_H #include "TopoShape.h" +#include #include #include +#include +#include namespace Part { @@ -95,6 +98,59 @@ private: TopoShape _Shape; }; +struct PartExport ShapeHistory { + TopAbs_ShapeEnum type; + std::map > modified; + std::map > generated; + std::map accepted; + std::set deleted; +}; + +class PartExport PropertyShapeHistory : public App::PropertyLists +{ + TYPESYSTEM_HEADER(); + +public: + PropertyShapeHistory(); + ~PropertyShapeHistory(); + + virtual void setSize(int newSize) { + _lValueList.resize(newSize); + } + virtual int getSize(void) const { + return _lValueList.size(); + } + + /** Sets the property + */ + void setValue(const ShapeHistory&); + + void setValues (const std::vector& values); + + const std::vector &getValues(void) const { + return _lValueList; + } + + virtual PyObject *getPyObject(void); + virtual void setPyObject(PyObject *); + + virtual void Save (Base::Writer &writer) const; + virtual void Restore(Base::XMLReader &reader); + + virtual void SaveDocFile (Base::Writer &writer) const; + virtual void RestoreDocFile(Base::Reader &reader); + + virtual Property *Copy(void) const; + virtual void Paste(const Property &from); + + virtual unsigned int getMemSize (void) const { + return _lValueList.size() * sizeof(ShapeHistory); + } + +private: + std::vector _lValueList; +}; + /** A property class to store hash codes and two radii for the fillet algorithm. * @author Werner Mayer */ @@ -151,4 +207,4 @@ private: } //namespace Part -#endif // PROPERTYTOPOSHAPE_H +#endif // PART_PROPERTYTOPOSHAPE_H diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.cpp b/src/Mod/Part/Gui/ViewProviderBoolean.cpp index d35cd0dde..46c85bb65 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.cpp +++ b/src/Mod/Part/Gui/ViewProviderBoolean.cpp @@ -77,80 +77,69 @@ QIcon ViewProviderBoolean::getIcon(void) const return ViewProviderPart::getIcon(); } -void findFaces(BRepAlgoAPI_BooleanOperation* mkBool, - const TopTools_IndexedMapOfShape& M1, - const TopTools_IndexedMapOfShape& M3, - const std::vector& colBase, - std::vector& colBool) +void applyColor(const Part::ShapeHistory& hist, + const std::vector& colBase, + std::vector& colBool) { - for (int i=1; i<=M1.Extent(); i++) { - bool modified=false, generated=false; - TopTools_ListIteratorOfListOfShape it; - for (it.Initialize(mkBool->Modified(M1(i))); it.More(); it.Next()) { - modified = true; - for (int j=1; j<=M3.Extent(); j++) { - if (M3(j).IsPartner(it.Value())) { - colBool[j-1] = colBase[i-1]; - break; - } - } + std::map >::const_iterator jt; + // apply color from modified faces + for (jt = hist.modified.begin(); jt != hist.modified.end(); ++jt) { + std::vector::const_iterator kt; + for (kt = jt->second.begin(); kt != jt->second.end(); ++kt) { + colBool[*kt] = colBase[jt->first]; } - - for (it.Initialize(mkBool->Generated(M1(i))); it.More(); it.Next()) { - generated = true; - for (int j=1; j<=M3.Extent(); j++) { - if (M3(j).IsPartner(it.Value())) { - colBool[j-1] = colBase[i-1]; - break; - } - } - } - - if (!modified && !generated && !mkBool->IsDeleted(M1(i))) { - for (int j=1; j<=M3.Extent(); j++) { - if (M3(j).IsPartner(M1(i))) { - colBool[j-1] = colBase[i-1]; - break; - } - } + } + // apply color from generated faces + for (jt = hist.generated.begin(); jt != hist.generated.end(); ++jt) { + std::vector::const_iterator kt; + for (kt = jt->second.begin(); kt != jt->second.end(); ++kt) { + colBool[*kt] = colBase[jt->first]; } } + // apply data from accepted faces + for (std::map::const_iterator kt = hist.accepted.begin(); kt != hist.accepted.end(); ++kt) { + colBool[kt->second] = colBase[kt->first]; + } } void ViewProviderBoolean::updateData(const App::Property* prop) { PartGui::ViewProviderPart::updateData(prop); - if (prop->getTypeId() == Part::PropertyPartShape::getClassTypeId()) { + if (prop->getTypeId() == Part::PropertyShapeHistory::getClassTypeId()) { + const std::vector& hist = static_cast + (prop)->getValues(); + if (hist.size() != 2) + return; Part::Boolean* objBool = dynamic_cast(getObject()); Part::Feature* objBase = dynamic_cast(objBool->Base.getValue()); Part::Feature* objTool = dynamic_cast(objBool->Tool.getValue()); - - BRepAlgoAPI_BooleanOperation* mkBool = objBool->getBooleanOperation(); - if (mkBool && objBase && objTool) { + if (objBase && objTool) { const TopoDS_Shape& baseShape = objBase->Shape.getValue(); const TopoDS_Shape& toolShape = objTool->Shape.getValue(); const TopoDS_Shape& boolShape = objBool->Shape.getValue(); - TopTools_IndexedMapOfShape M1, M2, M3; - TopExp::MapShapes(baseShape, TopAbs_FACE, M1); - TopExp::MapShapes(toolShape, TopAbs_FACE, M2); - TopExp::MapShapes(boolShape, TopAbs_FACE, M3); + TopTools_IndexedMapOfShape baseMap, toolMap, boolMap; + TopExp::MapShapes(baseShape, TopAbs_FACE, baseMap); + TopExp::MapShapes(toolShape, TopAbs_FACE, toolMap); + TopExp::MapShapes(boolShape, TopAbs_FACE, boolMap); + Gui::ViewProvider* vpBase = Gui::Application::Instance->getViewProvider(objBase); Gui::ViewProvider* vpTool = Gui::Application::Instance->getViewProvider(objTool); std::vector colBase = static_cast(vpBase)->DiffuseColor.getValues(); std::vector colTool = static_cast(vpTool)->DiffuseColor.getValues(); std::vector colBool; - colBool.resize(M3.Extent(), this->ShapeColor.getValue()); - bool applyColor=false; - if (colBase.size() == M1.Extent()) { - findFaces(mkBool, M1, M3, colBase, colBool); - applyColor = true; + colBool.resize(boolMap.Extent(), this->ShapeColor.getValue()); + + bool setColor=false; + if (colBase.size() == baseMap.Extent()) { + applyColor(hist[0], colBase, colBool); + setColor = true; } - if (colTool.size() == M2.Extent()) { - findFaces(mkBool, M2, M3, colTool, colBool); - applyColor = true; + if (colTool.size() == toolMap.Extent()) { + applyColor(hist[1], colTool, colBool); + setColor = true; } - if (applyColor) + if (setColor) this->DiffuseColor.setValues(colBool); } } @@ -176,6 +165,46 @@ QIcon ViewProviderMultiFuse::getIcon(void) const return Gui::BitmapFactory().pixmap("Part_Fuse"); } +void ViewProviderMultiFuse::updateData(const App::Property* prop) +{ + PartGui::ViewProviderPart::updateData(prop); + if (prop->getTypeId() == Part::PropertyShapeHistory::getClassTypeId()) { + const std::vector& hist = static_cast + (prop)->getValues(); + Part::MultiFuse* objBool = dynamic_cast(getObject()); + std::vector sources = objBool->Shapes.getValues(); + if (hist.size() != sources.size()) + return; + + const TopoDS_Shape& boolShape = objBool->Shape.getValue(); + TopTools_IndexedMapOfShape boolMap; + TopExp::MapShapes(boolShape, TopAbs_FACE, boolMap); + + std::vector colBool; + colBool.resize(boolMap.Extent(), this->ShapeColor.getValue()); + + bool setColor=false; + int index=0; + for (std::vector::iterator it = sources.begin(); it != sources.end(); ++it, ++index) { + Part::Feature* objBase = dynamic_cast(*it); + const TopoDS_Shape& baseShape = objBase->Shape.getValue(); + + TopTools_IndexedMapOfShape baseMap; + TopExp::MapShapes(baseShape, TopAbs_FACE, baseMap); + + Gui::ViewProvider* vpBase = Gui::Application::Instance->getViewProvider(objBase); + std::vector colBase = static_cast(vpBase)->DiffuseColor.getValues(); + if (colBase.size() == baseMap.Extent()) { + applyColor(hist[index], colBase, colBool); + setColor = true; + } + } + + if (setColor) + this->DiffuseColor.setValues(colBool); + } +} + PROPERTY_SOURCE(PartGui::ViewProviderMultiCommon,PartGui::ViewProviderPart) @@ -196,3 +225,43 @@ QIcon ViewProviderMultiCommon::getIcon(void) const { return Gui::BitmapFactory().pixmap("Part_Common"); } + +void ViewProviderMultiCommon::updateData(const App::Property* prop) +{ + PartGui::ViewProviderPart::updateData(prop); + if (prop->getTypeId() == Part::PropertyShapeHistory::getClassTypeId()) { + const std::vector& hist = static_cast + (prop)->getValues(); + Part::MultiCommon* objBool = dynamic_cast(getObject()); + std::vector sources = objBool->Shapes.getValues(); + if (hist.size() != sources.size()) + return; + + const TopoDS_Shape& boolShape = objBool->Shape.getValue(); + TopTools_IndexedMapOfShape boolMap; + TopExp::MapShapes(boolShape, TopAbs_FACE, boolMap); + + std::vector colBool; + colBool.resize(boolMap.Extent(), this->ShapeColor.getValue()); + + bool setColor=false; + int index=0; + for (std::vector::iterator it = sources.begin(); it != sources.end(); ++it, ++index) { + Part::Feature* objBase = dynamic_cast(*it); + const TopoDS_Shape& baseShape = objBase->Shape.getValue(); + + TopTools_IndexedMapOfShape baseMap; + TopExp::MapShapes(baseShape, TopAbs_FACE, baseMap); + + Gui::ViewProvider* vpBase = Gui::Application::Instance->getViewProvider(objBase); + std::vector colBase = static_cast(vpBase)->DiffuseColor.getValues(); + if (colBase.size() == baseMap.Extent()) { + applyColor(hist[index], colBase, colBool); + setColor = true; + } + } + + if (setColor) + this->DiffuseColor.setValues(colBool); + } +} diff --git a/src/Mod/Part/Gui/ViewProviderBoolean.h b/src/Mod/Part/Gui/ViewProviderBoolean.h index 0a34127b1..29c531109 100644 --- a/src/Mod/Part/Gui/ViewProviderBoolean.h +++ b/src/Mod/Part/Gui/ViewProviderBoolean.h @@ -59,6 +59,7 @@ public: /// grouping handling std::vector claimChildren(void) const; QIcon getIcon(void) const; + void updateData(const App::Property*); }; /// ViewProvider for the MultiFuse feature @@ -75,6 +76,7 @@ public: /// grouping handling std::vector claimChildren(void) const; QIcon getIcon(void) const; + void updateData(const App::Property*); };