From a27497e7383dc1ab66d2775d6383778873a31831 Mon Sep 17 00:00:00 2001 From: mpv Date: Mon, 30 Jun 2014 13:25:26 +0400 Subject: [PATCH] Several improvements mostly for automatic update of result --- src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp | 2 + src/Model/CMakeLists.txt | 3 + src/Model/Model_AttributeRefList.cpp | 2 +- src/Model/Model_Events.h | 2 +- src/Model/Model_Update.cpp | 82 +++++++++++++++++++ src/Model/Model_Update.h | 39 +++++++++ src/PartSetPlugin/PartSetPlugin_Part.cpp | 3 +- src/SketchPlugin/SketchPlugin_Circle.cpp | 6 +- src/SketchPlugin/SketchPlugin_Sketch.cpp | 2 + src/SketchSolver/CMakeLists.txt | 2 - 10 files changed, 135 insertions(+), 8 deletions(-) create mode 100644 src/Model/Model_Update.cpp create mode 100644 src/Model/Model_Update.h diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp index 5941efbec..fc2f9b98d 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp @@ -128,6 +128,8 @@ void GeomAlgoAPI_SketchBuilder::createFaces( BOPCol_IndexedDataMapOfShapeListOfShape aMapVE; // map between vertexes and edges BOPTools::MapShapesAndAncestors(aFeaturesCompound, TopAbs_VERTEX, TopAbs_EDGE, aMapVE); + if (aMapVE.IsEmpty()) // in case of not-initialized circle + return; gp_Dir aDirX = theDirX->impl(); gp_Dir aDirY = theDirY->impl(); diff --git a/src/Model/CMakeLists.txt b/src/Model/CMakeLists.txt index bb12daaad..d6ce96bdf 100644 --- a/src/Model/CMakeLists.txt +++ b/src/Model/CMakeLists.txt @@ -14,6 +14,7 @@ SET(PROJECT_HEADERS Model_AttributeRefList.h Model_AttributeBoolean.h Model_Events.h + Model_Update.h ) SET(PROJECT_SOURCES @@ -29,7 +30,9 @@ SET(PROJECT_SOURCES Model_AttributeRefList.cpp Model_AttributeBoolean.cpp Model_Events.cpp + Model_Update.cpp ) + SET(PROJECT_LIBRARIES ModelAPI Events diff --git a/src/Model/Model_AttributeRefList.cpp b/src/Model/Model_AttributeRefList.cpp index 9e4dc8396..cc19ba6ca 100644 --- a/src/Model/Model_AttributeRefList.cpp +++ b/src/Model/Model_AttributeRefList.cpp @@ -33,7 +33,7 @@ int Model_AttributeRefList::size() return myRef->Extent(); } -list Model_AttributeRefList::list() +list Model_AttributeRefList::list() { std::list< FeaturePtr > aResult; boost::shared_ptr aDoc = diff --git a/src/Model/Model_Events.h b/src/Model/Model_Events.h index 1fbf1980e..68b277b94 100644 --- a/src/Model/Model_Events.h +++ b/src/Model/Model_Events.h @@ -36,7 +36,7 @@ public: {if (theFeature) myFeatures.insert(theFeature);} /// Returns the feature that has been updated - std::set features() const {return myFeatures;} + std::set features() const {return myFeatures;} //! Creates a new empty group (to store it in the loop before flush) virtual Events_MessageGroup* newEmpty() { diff --git a/src/Model/Model_Update.cpp b/src/Model/Model_Update.cpp new file mode 100644 index 000000000..595579b08 --- /dev/null +++ b/src/Model/Model_Update.cpp @@ -0,0 +1,82 @@ +// File: Model_Update.cxx +// Created: 25 Jun 2014 +// Author: Mikhail PONIKAROV + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +Model_Update MY_INSTANCE; /// the only one instance initialized on load of the library + +Model_Update::Model_Update() +{ + Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_FEATURE_UPDATED)); +} + +void Model_Update::processEvent(const Events_Message* theMessage) +{ + const Model_FeatureUpdatedMessage* aMsg = + dynamic_cast(theMessage); + myInitial = aMsg->features(); + // collect all documents involved into the update + set > aDocs; + set >::iterator aFIter = myInitial.begin(); + for(; aFIter != myInitial.end(); aFIter++) { + aDocs.insert((*aFIter)->document()); + } + // iterate all features of features-documents to update them + set >::iterator aDIter = aDocs.begin(); + for(; aDIter != aDocs.end(); aDIter++) { + int aNbFeatures = (*aDIter)->size(FEATURES_GROUP); + for(int aFIndex = 0; aFIndex < aNbFeatures; aFIndex++) { + boost::shared_ptr aFeature = (*aDIter)->feature(FEATURES_GROUP, aFIndex); + if (aFeature) + updateFeature(aFeature); + } + } + myUpdated.clear(); +} + +bool Model_Update::updateFeature(boost::shared_ptr theFeature) +{ + // check it is already processed + if (myUpdated.find(theFeature) != myUpdated.end()) + return myUpdated[theFeature]; + // check all features this feature depended on (recursive call of updateFeature) + bool aMustbeUpdated = myInitial.find(theFeature) != myInitial.end(); + // references + list > aRefs = + theFeature->data()->attributes(ModelAPI_AttributeReference::type()); + list >::iterator aRefsIter = aRefs.begin(); + for(; aRefsIter != aRefs.end(); aRefsIter++) { + boost::shared_ptr aSub = + boost::dynamic_pointer_cast(*aRefsIter)->value(); + if (aSub && aSub != theFeature && updateFeature(aSub)) + aMustbeUpdated = true; + } + // lists of references + aRefs = theFeature->data()->attributes(ModelAPI_AttributeRefList::type()); + for(aRefsIter = aRefs.begin(); aRefsIter != aRefs.end(); aRefsIter++) { + list aListRef = + boost::dynamic_pointer_cast(*aRefsIter)->list(); + list::iterator aListIter = aListRef.begin(); + for(; aListIter != aListRef.end(); aListIter++) { + boost::shared_ptr aSub = *aListIter; + if (aSub && updateFeature(aSub)) + aMustbeUpdated = true; + } + } + // execute feature if it must be updated + bool anExecute = aMustbeUpdated || myInitial.find(theFeature) != myInitial.end(); + if (anExecute) { + theFeature->execute(); + } + myUpdated[theFeature] = anExecute; + return anExecute; +} diff --git a/src/Model/Model_Update.h b/src/Model/Model_Update.h new file mode 100644 index 000000000..d49c1c01e --- /dev/null +++ b/src/Model/Model_Update.h @@ -0,0 +1,39 @@ +// File: Model_Update.hxx +// Created: 25 Jun 2014 +// Author: Mikhail PONIKAROV + +#ifndef Model_Update_HeaderFile +#define Model_Update_HeaderFile + +#include "Model.h" +#include "Events_Listener.h" +#include +#include +#include + +class ModelAPI_Feature; + +/**\class Model_Update + * \ingroup DataModel + * \brief Updates the results of features when it is needed. + */ +class Model_Update : public Events_Listener +{ + ///< initial set of updated features that must be processed + std::set > myInitial; + ///< already updated and processed features and modificated feature flag + std::map, bool> myUpdated; +public: + /// Is called only once, on startup of the application + Model_Update(); + + /// Processes the feature argument update: executes the results + MODEL_EXPORT virtual void processEvent(const Events_Message* theMessage); + +protected: + /// Recoursively checks and updates the feature if needed + /// Returns true if feature was updated. + bool updateFeature(boost::shared_ptr theFeature); +}; + +#endif diff --git a/src/PartSetPlugin/PartSetPlugin_Part.cpp b/src/PartSetPlugin/PartSetPlugin_Part.cpp index 0fd91d969..628435a95 100644 --- a/src/PartSetPlugin/PartSetPlugin_Part.cpp +++ b/src/PartSetPlugin/PartSetPlugin_Part.cpp @@ -23,7 +23,8 @@ void PartSetPlugin_Part::execute() { boost::shared_ptr aDocRef = data()->docRef(PART_ATTR_DOC_REF); if (!aDocRef->value()) { // create a document if not yet created - boost::shared_ptr aPartSetDoc = ModelAPI_PluginManager::get()->rootDocument(); + boost::shared_ptr aPartSetDoc = + ModelAPI_PluginManager::get()->rootDocument(); aDocRef->setValue(aPartSetDoc->subDocument(data()->getName())); } } diff --git a/src/SketchPlugin/SketchPlugin_Circle.cpp b/src/SketchPlugin/SketchPlugin_Circle.cpp index cca6599bb..37c0fb3fe 100644 --- a/src/SketchPlugin/SketchPlugin_Circle.cpp +++ b/src/SketchPlugin/SketchPlugin_Circle.cpp @@ -41,7 +41,9 @@ const boost::shared_ptr& SketchPlugin_Circle::preview() // compute a circle point in 3D view boost::shared_ptr aCenterAttr = boost::dynamic_pointer_cast(data()->attribute(CIRCLE_ATTR_CENTER)); - if (aCenterAttr->isInitialized()) { + AttributeDoublePtr aRadiusAttr = + boost::dynamic_pointer_cast(data()->attribute(CIRCLE_ATTR_RADIUS)); + if (aCenterAttr->isInitialized() && aRadiusAttr->isInitialized()) { boost::shared_ptr aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y())); // make a visible point boost::shared_ptr aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter); @@ -54,8 +56,6 @@ const boost::shared_ptr& SketchPlugin_Circle::preview() if (aHasPlane) { boost::shared_ptr aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z())); // compute the circle radius - AttributeDoublePtr aRadiusAttr = - boost::dynamic_pointer_cast(data()->attribute(CIRCLE_ATTR_RADIUS)); double aRadius = aRadiusAttr->value(); boost::shared_ptr aCircleShape = diff --git a/src/SketchPlugin/SketchPlugin_Sketch.cpp b/src/SketchPlugin/SketchPlugin_Sketch.cpp index 81ead9d7d..9a4f1f1c4 100644 --- a/src/SketchPlugin/SketchPlugin_Sketch.cpp +++ b/src/SketchPlugin/SketchPlugin_Sketch.cpp @@ -70,6 +70,8 @@ void SketchPlugin_Sketch::execute() aFeaturesPreview.push_back(aPreview); } + if (aFeaturesPreview.empty()) + return ; std::list< boost::shared_ptr > aLoops; std::list< boost::shared_ptr > aWires; GeomAlgoAPI_SketchBuilder::createFaces(anOrigin->pnt(), aDirX->dir(), aDirY->dir(), aNorm->dir(), diff --git a/src/SketchSolver/CMakeLists.txt b/src/SketchSolver/CMakeLists.txt index 2178882ab..8964c31f8 100644 --- a/src/SketchSolver/CMakeLists.txt +++ b/src/SketchSolver/CMakeLists.txt @@ -20,13 +20,11 @@ SET(PROJECT_LIBRARIES ${SLVS_LIBRARIES} Events ModelAPI - Model ) INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/SketchPlugin ${PROJECT_SOURCE_DIR}/src/ModelAPI - ${PROJECT_SOURCE_DIR}/src/Model ${PROJECT_SOURCE_DIR}/src/GeomAPI ${PROJECT_SOURCE_DIR}/src/GeomDataAPI ${PROJECT_SOURCE_DIR}/src/Events -- 2.39.2