Salome HOME
Several improvements mostly for automatic update of result
authormpv <mikhail.ponikarov@opencascade.com>
Mon, 30 Jun 2014 09:25:26 +0000 (13:25 +0400)
committermpv <mikhail.ponikarov@opencascade.com>
Mon, 30 Jun 2014 09:25:26 +0000 (13:25 +0400)
src/GeomAlgoAPI/GeomAlgoAPI_SketchBuilder.cpp
src/Model/CMakeLists.txt
src/Model/Model_AttributeRefList.cpp
src/Model/Model_Events.h
src/Model/Model_Update.cpp [new file with mode: 0644]
src/Model/Model_Update.h [new file with mode: 0644]
src/PartSetPlugin/PartSetPlugin_Part.cpp
src/SketchPlugin/SketchPlugin_Circle.cpp
src/SketchPlugin/SketchPlugin_Sketch.cpp
src/SketchSolver/CMakeLists.txt

index 5941efbec62f9f9085b84df486587b98e3936733..fc2f9b98dfb06800345c0fa4002addd505dcddd1 100644 (file)
@@ -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>();
   gp_Dir aDirY = theDirY->impl<gp_Dir>();
index bb12daaadbd2e87fb940b2bef2dc57f9049816b3..d6ce96bdf08ce2c7a4cdade265939f25aaa3807a 100644 (file)
@@ -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 
index 9e4dc839688cda9f7ec6d7f6326337220641eaa4..cc19ba6cafa5083d5ac6880d4a65db925b1d95e1 100644 (file)
@@ -33,7 +33,7 @@ int Model_AttributeRefList::size()
   return myRef->Extent();
 }
 
-list<FeaturePtr > Model_AttributeRefList::list()
+list<FeaturePtr> Model_AttributeRefList::list()
 {
   std::list< FeaturePtr > aResult;
   boost::shared_ptr<Model_Document> aDoc = 
index 1fbf1980e1481b40ab2c1ef50340bf6131fc09f7..68b277b94c03f9084f0dc79d3add800be884319c 100644 (file)
@@ -36,7 +36,7 @@ public:
   {if (theFeature) myFeatures.insert(theFeature);}
 
   /// Returns the feature that has been updated
-  std::set<FeaturePtr > features() const {return myFeatures;}
+  std::set<FeaturePtr> 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 (file)
index 0000000..595579b
--- /dev/null
@@ -0,0 +1,82 @@
+// File:        Model_Update.cxx
+// Created:     25 Jun 2014
+// Author:      Mikhail PONIKAROV
+
+#include <Model_Update.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Document.h>
+#include <Model_Events.h>
+#include <ModelAPI_AttributeReference.h>
+#include <ModelAPI_AttributeRefList.h>
+
+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<const Model_FeatureUpdatedMessage*>(theMessage);
+  myInitial = aMsg->features();
+  // collect all documents involved into the update
+  set<boost::shared_ptr<ModelAPI_Document> > aDocs;
+  set<boost::shared_ptr<ModelAPI_Feature> >::iterator aFIter = myInitial.begin();
+  for(; aFIter != myInitial.end(); aFIter++) {
+    aDocs.insert((*aFIter)->document());
+  }
+  // iterate all features of features-documents to update them
+  set<boost::shared_ptr<ModelAPI_Document> >::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<ModelAPI_Feature> aFeature = (*aDIter)->feature(FEATURES_GROUP, aFIndex);
+      if (aFeature)
+        updateFeature(aFeature);
+    }
+  }
+  myUpdated.clear();
+}
+
+bool Model_Update::updateFeature(boost::shared_ptr<ModelAPI_Feature> 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<boost::shared_ptr<ModelAPI_Attribute> > aRefs = 
+    theFeature->data()->attributes(ModelAPI_AttributeReference::type());
+  list<boost::shared_ptr<ModelAPI_Attribute> >::iterator aRefsIter = aRefs.begin();
+  for(; aRefsIter != aRefs.end(); aRefsIter++) {
+    boost::shared_ptr<ModelAPI_Feature> aSub =
+      boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(*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<FeaturePtr> aListRef = 
+      boost::dynamic_pointer_cast<ModelAPI_AttributeRefList>(*aRefsIter)->list();
+    list<FeaturePtr>::iterator aListIter = aListRef.begin();
+    for(; aListIter != aListRef.end(); aListIter++) {
+      boost::shared_ptr<ModelAPI_Feature> 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 (file)
index 0000000..d49c1c0
--- /dev/null
@@ -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 <boost/shared_ptr.hpp>
+#include <set>
+#include <map>
+
+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<boost::shared_ptr<ModelAPI_Feature> > myInitial;
+  ///< already updated and processed features and modificated feature flag
+  std::map<boost::shared_ptr<ModelAPI_Feature>, 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<ModelAPI_Feature> theFeature);
+};
+
+#endif
index 0fd91d96958458e2a292ef214608d854586eb12f..628435a95aa198edd6fa76fe20186162afef5880 100644 (file)
@@ -23,7 +23,8 @@ void PartSetPlugin_Part::execute()
 {
   boost::shared_ptr<ModelAPI_AttributeDocRef> aDocRef = data()->docRef(PART_ATTR_DOC_REF);
   if (!aDocRef->value()) { // create a document if not yet created
-    boost::shared_ptr<ModelAPI_Document> aPartSetDoc = ModelAPI_PluginManager::get()->rootDocument();
+    boost::shared_ptr<ModelAPI_Document> aPartSetDoc = 
+      ModelAPI_PluginManager::get()->rootDocument();
     aDocRef->setValue(aPartSetDoc->subDocument(data()->getName()));
   }
 }
index cca6599bb9ca0f2172e71de0b1f650ceb1aa5831..37c0fb3fec68b16ec85985f087f50f55969eff62 100644 (file)
@@ -41,7 +41,9 @@ const boost::shared_ptr<GeomAPI_Shape>& SketchPlugin_Circle::preview()
     // compute a circle point in 3D view
     boost::shared_ptr<GeomDataAPI_Point2D> aCenterAttr = 
       boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(data()->attribute(CIRCLE_ATTR_CENTER));
-    if (aCenterAttr->isInitialized()) {
+    AttributeDoublePtr aRadiusAttr = 
+      boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(data()->attribute(CIRCLE_ATTR_RADIUS));
+    if (aCenterAttr->isInitialized() && aRadiusAttr->isInitialized()) {
       boost::shared_ptr<GeomAPI_Pnt> aCenter(aSketch->to3D(aCenterAttr->x(), aCenterAttr->y()));
       // make a visible point
       boost::shared_ptr<GeomAPI_Shape> aCenterPointShape = GeomAlgoAPI_PointBuilder::point(aCenter);
@@ -54,8 +56,6 @@ const boost::shared_ptr<GeomAPI_Shape>& SketchPlugin_Circle::preview()
       if (aHasPlane) {
         boost::shared_ptr<GeomAPI_Dir> aNormal(new GeomAPI_Dir(aNDir->x(), aNDir->y(), aNDir->z()));
         // compute the circle radius
-        AttributeDoublePtr aRadiusAttr = 
-          boost::dynamic_pointer_cast<ModelAPI_AttributeDouble>(data()->attribute(CIRCLE_ATTR_RADIUS));
         double aRadius = aRadiusAttr->value();
 
         boost::shared_ptr<GeomAPI_Shape> aCircleShape = 
index 81ead9d7ded55fffa4dd660608b21e10f8e138dd..9a4f1f1c4d7a2ce9e2e9888170f3dd3b79a47fdd 100644 (file)
@@ -70,6 +70,8 @@ void SketchPlugin_Sketch::execute()
       aFeaturesPreview.push_back(aPreview);
   }
 
+  if (aFeaturesPreview.empty())
+    return ;
   std::list< boost::shared_ptr<GeomAPI_Shape> > aLoops;
   std::list< boost::shared_ptr<GeomAPI_Shape> > aWires;
   GeomAlgoAPI_SketchBuilder::createFaces(anOrigin->pnt(), aDirX->dir(), aDirY->dir(), aNorm->dir(),
index 2178882ab38bd4b4dde62176b40f446b2d63d084..8964c31f8c012b4a22a45141a3a98ef22ff7a18f 100644 (file)
@@ -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