Salome HOME
High level objects history implementation for Intersection and Compound features...
[modules/shaper.git] / src / Model / Model_ResultBody.cpp
index 9b3401290035a5711ffe328a4c91bb532f270801..3d28be7c668bdff13d28f9f393dc037bfbaf798b 100644 (file)
@@ -29,6 +29,7 @@
 #include <ModelAPI_Tools.h>
 #include <Model_Data.h>
 #include <Events_Loop.h>
+#include <GeomAPI_ShapeIterator.h>
 
 #include <TopoDS_Shape.hxx>
 #include <TopExp_Explorer.hxx>
@@ -52,43 +53,59 @@ Model_ResultBody::~Model_ResultBody()
   delete myBuilder;
 }
 
-void Model_ResultBody::loadAndOrientModifiedShapes(GeomAlgoAPI_MakeShape* theMS,
-    std::shared_ptr<GeomAPI_Shape>  theShapeIn, const int  theKindOfShape, const int  theTag,
-    const std::string& theName, GeomAPI_DataMapOfShapeShape& theSubShapes,
-    const bool theIsStoreSeparate,
-    const bool theIsStoreAsGenerated,
-    const bool theSplitInSubs)
+bool Model_ResultBody::generated(const GeomShapePtr& theNewShape,
+  const std::string& theName, const bool theCheckIsInResult)
 {
-  if (theSplitInSubs && mySubs.size()) { // consists of subs
+  bool aResult = false;
+  if (mySubs.size()) { // consists of subs
+    for (std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
+         aSubIter != mySubs.cend();
+         ++aSubIter)
+    {
+      const ResultBodyPtr& aSub = *aSubIter;
+      if (aSub->generated(theNewShape, theName, theCheckIsInResult))
+        aResult = true;
+    }
+  } else { // do for this directly
+    if (myBuilder->generated(theNewShape, theName, theCheckIsInResult))
+      aResult = true;
+  }
+  return aResult;
+}
+
+void Model_ResultBody::loadGeneratedShapes(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgo,
+                                           const GeomShapePtr& theOldShape,
+                                           const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
+                                           const std::string& theName)
+{
+  if (mySubs.size()) { // consists of subs
+    for (std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
+         aSubIter != mySubs.cend();
+         ++aSubIter)
+    {
+      const ResultBodyPtr& aSub = *aSubIter;
+      aSub->loadGeneratedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
+    }
+  } else { // do for this directly
+    myBuilder->loadGeneratedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
+  }
+}
+
+void Model_ResultBody::loadModifiedShapes(const std::shared_ptr<GeomAlgoAPI_MakeShape>& theAlgo,
+                                          const GeomShapePtr& theOldShape,
+                                          const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
+                                          const std::string& theName)
+{
+  if (mySubs.size()) { // consists of subs
+    // optimization of getting of new shapes for specific sub-result
+    if (!theAlgo->isNewShapesCollected(theOldShape, theShapeTypeToExplore))
+      theAlgo->collectNewShapes(theOldShape, theShapeTypeToExplore);
     std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
     for(; aSubIter != mySubs.cend(); aSubIter++) {
-      // check that sub-shape was also created as modification of ShapeIn
-      /* to find when it is needed later to enable: to store modification of sub-bodies not only as primitives
-      GeomShapePtr aSubGeomShape = (*aSubIter)->shape();
-      if (!theIsStoreAsGenerated && aSubGeomShape.get() && !aSubGeomShape->isNull()) {
-        TopoDS_Shape aSubShape = aSubGeomShape->impl<TopoDS_Shape>();
-        TopoDS_Shape aWholeIn = theShapeIn->impl<TopoDS_Shape>();
-        for(TopExp_Explorer anExp(aWholeIn, aSubShape.ShapeType()); anExp.More(); anExp.Next()) {
-          ListOfShape aHistory;
-          std::shared_ptr<GeomAPI_Shape> aSubIn(new GeomAPI_Shape());
-          aSubIn->setImpl((new TopoDS_Shape(anExp.Current())));
-          theMS->modified(aSubIn, aHistory);
-          std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator anIt = aHistory.begin();
-          for (; anIt != aHistory.end(); anIt++) {
-            if ((*anIt)->isSame(aSubGeomShape)) {
-              (*aSubIter)->storeModified(aSubIn, aSubGeomShape, -2); // -2 is to avoid clearing
-            }
-          }
-        }
-      }*/
-      (*aSubIter)->loadAndOrientModifiedShapes(
-        theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
-        theIsStoreAsGenerated, theSplitInSubs);
+      (*aSubIter)->loadModifiedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
     }
   } else { // do for this directly
-    myBuilder->loadAndOrientModifiedShapes(
-      theMS, theShapeIn, theKindOfShape, theTag, theName, theSubShapes, theIsStoreSeparate,
-        theIsStoreAsGenerated);
+    myBuilder->loadModifiedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
   }
 }
 
@@ -126,7 +143,6 @@ bool Model_ResultBody::setDisabled(std::shared_ptr<ModelAPI_Result> theThis, con
 {
   bool aChanged = ModelAPI_ResultBody::setDisabled(theThis, theFlag);
   if (aChanged) { // state is changed, so modifications are needed
-    myBuilder->evolutionToSelection(theFlag);
     updateSubs(shape(), false); // to set disabled/enabled
   }
   return aChanged;
@@ -210,6 +226,7 @@ void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisS
     TDF_Label aDataLab = std::dynamic_pointer_cast<Model_Data>(data())->label();
     if (!aDataLab.IsNull()) {
       TDataStd_UAttribute::Set(aDataLab, kUpdateConnectedTopology);
+      isConnectedTopology(); // to store this flag in transaction, #2630
     }
   }
   // iterate all sub-solids of compsolid to make sub-results synchronized with them
@@ -236,8 +253,16 @@ void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisS
       } else { // just update shape of this result
         aSub = mySubs[aSubIndex];
       }
-      if (!aShape->isEqual(aSub->shape())) {
-        aSub->store(aShape, false);
+      GeomShapePtr anOldSubShape = aSub->shape();
+      if (!aShape->isEqual(anOldSubShape)) {
+        if (myAlgo.get()) {
+          std::list<GeomShapePtr> anOldForSub;
+          computeOldForSub(aShape, myOlds, anOldForSub);
+          myIsGenerated ? aSub->storeGenerated(anOldForSub, aShape, myAlgo) :
+            aSub->storeModified(anOldForSub, aShape, myAlgo);
+        } else {
+          aSub->store(aShape, false);
+        }
         aECreator->sendUpdated(aSub, EVENT_DISP);
         aECreator->sendUpdated(aSub, EVENT_UPD);
       }
@@ -258,6 +283,7 @@ void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisS
       // redisplay this because result with and without subs are displayed differently
       aECreator->sendUpdated(data()->owner(), EVENT_DISP);
     }
+    cleanCash();
   } else if (!mySubs.empty()) { // erase all subs
     while(!mySubs.empty()) {
       ResultBodyPtr anErased = *(mySubs.rbegin());
@@ -274,20 +300,19 @@ void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisS
   }
 }
 
-bool Model_ResultBody::isLatestEqual(const std::shared_ptr<GeomAPI_Shape>& theShape)
+void Model_ResultBody::updateSubs(
+  const GeomShapePtr& theThisShape, const std::list<GeomShapePtr>& theOlds,
+  const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape, const bool isGenerated)
 {
-  if (myBuilder->isLatestEqual(theShape))
-    return true;
-  // also check that it is asked for sub-elements
-  std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
-  for(; aSubIter != mySubs.cend(); aSubIter++) {
-    if (aSubIter->get() && (*aSubIter)->isLatestEqual(theShape)) {
-      return true;
-    }
-  }
-  return false;
+  myAlgo = theMakeShape;
+  myOlds = theOlds;
+  myIsGenerated = isGenerated;
+  updateSubs(theThisShape, true);
+  myAlgo.reset();
+  myOlds.clear();
 }
 
+
 bool Model_ResultBody::isConnectedTopology()
 {
   TDF_Label aDataLab = std::dynamic_pointer_cast<Model_Data>(data())->label();
@@ -305,3 +330,42 @@ bool Model_ResultBody::isConnectedTopology()
   }
   return false; // invalid case
 }
+
+void Model_ResultBody::cleanCash()
+{
+  myBuilder->cleanCash();
+  for (std::vector<ResultBodyPtr>::const_iterator aSubIter = mySubs.cbegin();
+    aSubIter != mySubs.cend(); ++aSubIter)
+  {
+    const ResultBodyPtr& aSub = *aSubIter;
+    aSub->cleanCash();
+  }
+}
+
+void Model_ResultBody::computeOldForSub(const GeomShapePtr& theSub,
+  const std::list<GeomShapePtr>& theAllOlds, std::list<GeomShapePtr>& theOldForSub)
+{
+  std::list<GeomShapePtr>::const_iterator aRootOlds = theAllOlds.cbegin();
+  for(; aRootOlds != theAllOlds.cend(); aRootOlds++) {
+    ListOfShape aNews;
+    myIsGenerated ? myAlgo->generated(*aRootOlds, aNews) : myAlgo->modified(*aRootOlds, aNews);
+    // MakeShape may return alone old shape if there is no history information for this input
+    if (aNews.size() == 1 && aNews.front()->isEqual(*aRootOlds))
+      aNews.clear();
+    if (aNews.empty()) { // try to iterate to sub-elements (for intersection of solids this is face)
+      std::list<GeomShapePtr> theAllSubOlds;
+      for(GeomAPI_ShapeIterator aSubOld(*aRootOlds); aSubOld.more(); aSubOld.next()) {
+        GeomShapePtr aSub = aSubOld.current();
+        if (aSub.get() && !aSub->isNull())
+          theAllSubOlds.push_back(aSub);
+      }
+      computeOldForSub(theSub, theAllSubOlds, theOldForSub);
+    }
+    for(ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) {
+      if (theSub->isSame(*aNewIter)) { // found old that was used for new theSubShape creation
+        theOldForSub.push_back(*aRootOlds);
+        break;
+      }
+    }
+  }
+}