Salome HOME
Initial implementation of higher level objects history for partition
authormpv <mpv@opencascade.com>
Fri, 18 Jan 2019 15:00:22 +0000 (18:00 +0300)
committermpv <mpv@opencascade.com>
Fri, 18 Jan 2019 15:00:22 +0000 (18:00 +0300)
src/FeaturesPlugin/CMakeLists.txt
src/FeaturesPlugin/FeaturesPlugin_Partition.cpp
src/FeaturesPlugin/Test/Test1876.py [new file with mode: 0644]
src/Model/Model_AttributeSelection.cpp
src/Model/Model_BodyBuilder.cpp
src/Model/Model_BodyBuilder.h
src/Model/Model_ResultBody.cpp
src/Model/Model_ResultBody.h
src/ModelAPI/ModelAPI_BodyBuilder.h
src/ModelAPI/ModelAPI_ResultBody.cpp
src/ModelAPI/ModelAPI_ResultBody.h

index d0f0261a0316464e790e188b6da20bb48c919c75..0458345a1de6dfe0d108970fcd6f34e9320c0e55 100644 (file)
@@ -433,6 +433,7 @@ ADD_UNIT_TESTS(TestExtrusion.py
                TestScale1.py
                TestScale2.py
                Test1816.py
+               Test1876.py
                Test2631.py
                Test2650.py
                Test2681.py
index 43ae4130c0fa13b171c932b375b2cab4a6ec431b..8215f029374057be0ab4bc3eb9c3298c1685a1cd 100755 (executable)
@@ -172,37 +172,20 @@ void FeaturesPlugin_Partition::storeResult(
   const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
   const int theIndex)
 {
-  // Find base. The most complicated is the real modified object (#1799 if box is partitioned by
-  // two planes the box is the base, not planes, independently on the order in the list).
-  GeomShapePtr aBaseShape;
-  for(ListOfShape::const_iterator anIt = theObjects.cbegin(); anIt != theObjects.cend(); ++anIt) {
-    GeomShapePtr anObjectShape = *anIt;
-    GeomShapePtr aCandidate =
-      findBase(anObjectShape, theResultShape, GeomAPI_Shape::VERTEX, theMakeShape);
-    if(!aCandidate.get()) {
-      aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::EDGE, theMakeShape);
-    }
-    if (!aCandidate.get())
-      aCandidate = findBase(anObjectShape, theResultShape, GeomAPI_Shape::FACE, theMakeShape);
-
-    if(aCandidate.get()) {
-      if (!aBaseShape.get() || aBaseShape->shapeType() > aCandidate->shapeType()) {
-        aBaseShape = aCandidate;
-      }
-    }
-  }
-
   // Create result body.
   ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
 
-  // Store modified shape.
-  if(!aBaseShape.get() || aBaseShape->isEqual(theResultShape)) {
-    aResultBody->store(theResultShape, false);
-    setResult(aResultBody, theIndex);
-    return;
+  // if result is same as one of the base object, no modification was performed
+  for(ListOfShape::const_iterator anObj = theObjects.cbegin(); anObj != theObjects.cend(); ++anObj)
+  {
+    if (anObj->get() && (*anObj)->isSame(theResultShape)) {
+      aResultBody->store(theResultShape, false);
+      setResult(aResultBody, theIndex);
+      return;
+    }
   }
 
-  aResultBody->storeModified(aBaseShape, theResultShape);
+  aResultBody->storeModified(theObjects, theResultShape, theMakeShape);
 
   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
   theObjects.insert(theObjects.end(), thePlanes.begin(), thePlanes.end());
@@ -222,38 +205,6 @@ void FeaturesPlugin_Partition::storeResult(
 
 //=================     Auxiliary functions     ===================================================
 
-GeomShapePtr findBase(const GeomShapePtr theObjectShape,
-                      const GeomShapePtr theResultShape,
-                      const GeomAPI_Shape::ShapeType theShapeType,
-                      const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
-{
-  GeomShapePtr aBaseShape;
-  std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
-  for(GeomAPI_ShapeExplorer anObjectSubShapesExp(theObjectShape, theShapeType);
-      anObjectSubShapesExp.more();
-      anObjectSubShapesExp.next()) {
-    GeomShapePtr anObjectSubShape = anObjectSubShapesExp.current();
-    ListOfShape aModifiedShapes;
-    theMakeShape->modified(anObjectSubShape, aModifiedShapes);
-    for(ListOfShape::const_iterator
-        aModIt = aModifiedShapes.cbegin(); aModIt != aModifiedShapes.cend(); ++aModIt) {
-      GeomShapePtr aModShape = *aModIt;
-      if(aMapOfSubShapes->isBound(aModShape)) {
-        aModShape = aMapOfSubShapes->find(aModShape);
-      }
-      if(theResultShape->isSubShape(aModShape)) {
-        aBaseShape = theObjectShape;
-        break;
-      }
-    }
-    if(aBaseShape.get()) {
-      break;
-    }
-  }
-
-  return aBaseShape;
-}
-
 static CompsolidSubs::iterator findOrAdd(CompsolidSubs& theList, const GeomShapePtr& theCompsolid)
 {
   CompsolidSubs::iterator aFound = theList.begin();
diff --git a/src/FeaturesPlugin/Test/Test1876.py b/src/FeaturesPlugin/Test/Test1876.py
new file mode 100644 (file)
index 0000000..4b01039
--- /dev/null
@@ -0,0 +1,72 @@
+## Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+##
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this library; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+## See http:##www.salome-platform.org/ or
+## email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+##
+
+from salome.shaper import model
+from ModelAPI import *
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchLine_1 = Sketch_1.addLine(396.8373493975904, 115.9638554216867, -225.1506024096385, 115.9638554216867)
+SketchLine_2 = Sketch_1.addLine(-225.1506024096385, 115.9638554216867, -225.1506024096385, -149.0963855421687)
+SketchLine_3 = Sketch_1.addLine(-225.1506024096385, -149.0963855421687, 396.8373493975904, -149.0963855421687)
+SketchLine_4 = Sketch_1.addLine(396.8373493975904, -149.0963855421687, 396.8373493975904, 115.9638554216867)
+SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint())
+SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint())
+SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint())
+SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint())
+SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result())
+SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result())
+SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result())
+SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result())
+model.do()
+Sketch_2 = model.addSketch(Part_1_doc, model.defaultPlane("XOY"))
+SketchCircle_1 = Sketch_2.addCircle(-348.644578313253, 155.1204819277109, 207.6894050099908)
+model.do()
+Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchLine_1r-SketchLine_2f-SketchLine_3f-SketchLine_4f")], model.selection(), 100, 0)
+Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_2/Face-SketchCircle_1_2r")], model.selection(), 100, 0)
+Group_1 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_2_1")])
+Group_2 = model.addGroup(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")])
+Partition_1 = model.addPartition(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1")])
+model.end()
+
+# move groups
+model.begin()
+Part_1_doc.moveFeature(Group_1.feature(), Partition_1.feature())
+Part_1_doc.moveFeature(Group_2.feature(), Group_1.feature())
+model.end()
+
+# check each group contain two results: one is related to original body only, another - common part
+
+aFactory = ModelAPI_Session.get().validators()
+assert(aFactory.validate(Group_1.feature()))
+assert(aFactory.validate(Group_2.feature()))
+aList1 = Group_1.feature().selectionList("group_list")
+aList2 = Group_2.feature().selectionList("group_list")
+assert(aList1.size() == 2)
+assert(aList2.size() == 2)
+assert(aList1.value(0).value().shapeTypeStr() == "SOLID")
+assert(aList1.value(1).value().shapeTypeStr() == "SOLID")
+assert(aList2.value(0).value().shapeTypeStr() == "SOLID")
+assert(aList2.value(1).value().shapeTypeStr() == "SOLID")
+assert(aList1.value(0).value().isSame(aList2.value(0).value()) or aList1.value(1).value().isSame(aList2.value(0).value()) or
+aList1.value(1).value().isSame(aList2.value(0).value()) or aList1.value(1).value().isSame(aList2.value(1).value()))
index 00736a73ece411591afd7cc6d08e054c99c310f7..6940cdbe1e9cb54df8e1d517af4a6e40652b72ef 100644 (file)
@@ -1373,75 +1373,12 @@ void Model_AttributeSelection::updateInHistory()
         continue;
       }
 
-      ResultPtr aSetContext;
       if (aFirst) {
         setValue(*aNewCont, aValueShape);
-        aSetContext = context();
+        aFirst = false;
       } else if (myParent) {
         myParent->append(*aNewCont, aValueShape);
-        aSetContext = myParent->value(myParent->size() - 1)->context();
       }
-
-      // #2826 : error if context is concealed by new context where the value is not presented
-      if (aSetContext.get()) {
-        bool anError = false;
-        std::list<ResultPtr> allRes;
-        ResultPtr aCompContext;
-        ResultBodyPtr aCompBody = ModelAPI_Tools::bodyOwner(aSetContext, true);
-        if (aCompBody.get()) {
-          ModelAPI_Tools::allSubs(aCompBody, allRes);
-          allRes.push_back(aCompBody);
-          aCompContext = aCompBody;
-        }
-        if (allRes.empty())
-          allRes.push_back(aSetContext);
-
-        std::list<ResultPtr>::iterator aSub = allRes.begin();
-        for (; !anError && aSub != allRes.end(); aSub++) {
-          ResultPtr aResCont = *aSub;
-          ResultBodyPtr aResBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aResCont);
-          const std::set<AttributePtr>& aRefs = aResCont->data()->refsToMe();
-          std::set<AttributePtr>::const_iterator aRef = aRefs.begin();
-          for (; aRef != aRefs.end(); aRef++) {
-            if (!aRef->get() || !(*aRef)->owner().get())
-              continue;
-            // concealed attribute only
-            FeaturePtr aRefFeat = std::dynamic_pointer_cast<ModelAPI_Feature>((*aRef)->owner());
-            if (!aRefFeat.get())
-              continue;
-            if (!ModelAPI_Session::get()->validators()->isConcealed(
-              aRefFeat->getKind(), (*aRef)->id()))
-              continue;
-            // check the found feature is older than this attribute
-            if (aRefFeat == aThisFeature || aDoc->isLaterByDep(aRefFeat, aThisFeature))
-              continue;
-            // check the found feature don't have the value-shape
-            GeomShapePtr aValue = aFirst ? value() : myParent->value(myParent->size() - 1)->value();
-            if (aValue.get()) {
-              std::list<ResultPtr>::const_iterator aRefResults = aRefFeat->results().cbegin();
-              for(; aRefResults != aRefFeat->results().cend(); aRefResults++) {
-                if ((*aRefResults)->shape().get() &&
-                    !(*aRefResults)->shape()->isSubShape(aValue, false)) { // set error
-                  ResultPtr anEmptyContext;
-                  std::shared_ptr<GeomAPI_Shape> anEmptyShape;
-                  if (aFirst) {
-                    setValue(anEmptyContext, anEmptyShape); // nullify the selection
-                  } else {
-                    myParent->value(myParent->size() - 1)->setValue(anEmptyContext, anEmptyShape);
-                  }
-                  Events_InfoMessage("Model_AttributeSelection",
-                    "Selection of sub-shape of already modified result").send();
-                  anError = true;
-                  break;
-                }
-              }
-              if (anError)
-                break;
-            }
-          }
-        }
-      }
-      aFirst = false;
     }
     if (aFirst) { // nothing was added, all results were deleted
       ResultPtr anEmptyContext;
index 7efd13fe8b9d08712b089ebde70366ec7d8af4da..893b4fc1cdbd35a0a8d177274b941c3c4844cb28 100755 (executable)
@@ -166,13 +166,14 @@ void Model_BodyBuilder::store(const GeomShapePtr& theShape,
 }
 
 void Model_BodyBuilder::storeGenerated(const GeomShapePtr& theFromShape,
-  const GeomShapePtr& theToShape)
+  const GeomShapePtr& theToShape, const bool theIsCleanStored)
 {
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
   if (aData) {
     TDF_Label aShapeLab = aData->shapeLab();
     // clean builders
-    clean();
+    if (theIsCleanStored)
+      clean();
     // store the new shape as primitive
     TNaming_Builder aBuilder(aShapeLab);
     if (!theFromShape || !theToShape)
@@ -199,6 +200,31 @@ void Model_BodyBuilder::storeGenerated(const GeomShapePtr& theFromShape,
   }
 }
 
+void Model_BodyBuilder::storeGenerated(const std::list<GeomShapePtr>& theFromShapes,
+  const GeomShapePtr& theToShape, const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
+{
+  bool aStored = false;
+  std::list<GeomShapePtr>::const_iterator anOldIter = theFromShapes.cbegin();
+  for(; anOldIter != theFromShapes.cend(); anOldIter++) {
+    ListOfShape aNews; // check this old really generates theToShape
+    theMakeShape->generated(*anOldIter, aNews);
+    ListOfShape::iterator aNewIter = aNews.begin();
+    for(; aNewIter != aNews.end(); aNewIter++) {
+      if (theToShape->isSame(*aNewIter))
+        break;
+    }
+    if (aNewIter != aNews.end()) {
+      storeGenerated(*anOldIter, theToShape, !aStored);
+      TNaming_Builder* aBuilder = builder(0);
+      aStored = !aBuilder->NamedShape()->IsEmpty();
+    }
+  }
+  if (!aStored) { // store as PRIMITIVE, but clean in any way
+    store(theToShape);
+    return;
+  }
+}
+
 TNaming_Builder* Model_BodyBuilder::builder(const int theTag)
 {
   std::map<int, TNaming_Builder*>::iterator aFind = myBuilders.find(theTag);
@@ -232,7 +258,7 @@ void Model_BodyBuilder::storeModified(const GeomShapePtr& theOldShape,
     aBuilder->Modify(aShapeOld, aShapeNew);
     if(!aBuilder->NamedShape()->IsEmpty()) {
       Handle(TDataStd_Name) anAttr;
-      if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
+      if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) {
         std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
         if(!aName.empty()) {
           std::shared_ptr<Model_Document> aDoc =
@@ -244,6 +270,31 @@ void Model_BodyBuilder::storeModified(const GeomShapePtr& theOldShape,
   }
 }
 
+void Model_BodyBuilder::storeModified(const std::list<GeomShapePtr>& theOldShapes,
+  const GeomShapePtr& theNewShape, const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
+{
+  bool aStored = false;
+  std::list<GeomShapePtr>::const_iterator anOldIter = theOldShapes.cbegin();
+  for(; anOldIter != theOldShapes.cend(); anOldIter++) {
+    ListOfShape aNews; // check this old really modifies theNewShape
+    theMakeShape->modified(*anOldIter, aNews);
+    ListOfShape::iterator aNewIter = aNews.begin();
+    for(; aNewIter != aNews.end(); aNewIter++) {
+      if (theNewShape->isSame(*aNewIter))
+        break;
+    }
+    if (aNewIter != aNews.end()) {
+      storeModified(*anOldIter, theNewShape, !aStored);
+      TNaming_Builder* aBuilder = builder(0);
+      aStored = !aBuilder->NamedShape()->IsEmpty();
+    }
+  }
+  if (!aStored) { // store as PRIMITIVE, but clean in any way
+    store(theNewShape);
+    return;
+  }
+}
+
 void Model_BodyBuilder::clean()
 {
   TDF_Label aLab = std::dynamic_pointer_cast<Model_Data>(data())->shapeLab();
@@ -528,44 +579,18 @@ void Model_BodyBuilder::loadModifiedShapes(const GeomMakeShapePtr& theAlgo,
 
       bool aNewShapeIsSameAsOldShape = anOldSubShape->isSame(aNewShape);
       bool aNewShapeIsNotInResultShape = !aResultShape->isSubShape(aNewShape, false);
-      if (aNewShapeIsSameAsOldShape
-          || aNewShapeIsNotInResultShape)
-      {
+      if (aNewShapeIsSameAsOldShape || aNewShapeIsNotInResultShape)
         continue;
-      }
 
-      TNaming_Builder* aBuilder;
-      if (aResultShape->isSame(aNewShape)) {
-        // keep the modification evolution on the root level (2241 - history propagation issue)
-        aBuilder = builder(0);
-        TDF_Label aShapeLab = aBuilder->NamedShape()->Label();
-        Handle(TDF_Reference) aRef;
-        if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
-          // Store only in case if it does not have reference.
-          continue;
-        }
-
-        // Check if new shape was already stored.
-        if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) continue;
-
-        if (!aBuilder->NamedShape().IsNull() &&
-            ((isGenerated && aBuilder->NamedShape()->Evolution() != TNaming_GENERATED)
-              || (!isGenerated && aBuilder->NamedShape()->Evolution() != TNaming_MODIFY)))
-        {
-          myBuilders.erase(0); // clear old builder to avoid different evolutions crash
-          aBuilder = builder(0);
-        }
-      } else {
-        int aTag = isGenerated ? getGenerationTag(aNewShape_)
-                               : getModificationTag(aNewShape_);
-        aBuilder = builder(aTag);
+      if (aResultShape->isSame(aNewShape))
+        continue; // it is stored on the root level (2241 - history propagation issue)
 
-        // Check if new shape was already stored.
-        if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) continue;
-
-        buildName(aTag, theName);
-      }
+      int aTag = isGenerated ? getGenerationTag(aNewShape_) : getModificationTag(aNewShape_);
+      TNaming_Builder*aBuilder = builder(aTag);
+      if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_))
+        continue; // new shape was already stored.
 
+      buildName(aTag, theName);
       isGenerated ? aBuilder->Generated(anOldSubShape_, aNewShape_)
                   : aBuilder->Modify(anOldSubShape_, aNewShape_);
       // store information about the external document reference to restore old shape on open
@@ -632,25 +657,6 @@ void Model_BodyBuilder::loadGeneratedShapes(const GeomMakeShapePtr& theAlgo,
           storeExternalReference(anOriginalLabel, builder(aTag)->NamedShape()->Label());
         }
         buildName(aTag, theName);
-      } if (aResultShape->isSame(aNewShape)) {
-        // keep the generation evolution on the root level (2397 - for intersection feature)
-        TNaming_Builder* aBuilder = builder(0);
-        TDF_Label aShapeLab = aBuilder->NamedShape()->Label();
-        Handle(TDF_Reference) aRef;
-        if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
-          // Store only in case if it does not have reference.
-          continue;
-        }
-
-        // Check if new shape was already stored.
-        if (isAlreadyStored(aBuilder, anOldSubShape_, aNewShape_)) continue;
-
-        if (!aBuilder->NamedShape().IsNull() &&
-            aBuilder->NamedShape()->Evolution() != TNaming_GENERATED) {
-          myBuilders.erase(0); // clear old builder to avoid different evolutions crash
-          aBuilder = builder(0);
-        }
-        aBuilder->Generated(anOldSubShape_, aNewShape_);
       } else {
         int aTag = getGenerationTag(aNewShape_);
         if (aTag == INVALID_TAG) return;
index 8487a6b818720f69e1c0efbe00a53abadb6b8c63..17e7635ea379e539f18371247cac54f9f0e5548c 100755 (executable)
@@ -42,21 +42,34 @@ class Model_BodyBuilder : public ModelAPI_BodyBuilder
 public:
   /// Stores the shape (called by the execution method).
   MODEL_EXPORT virtual void store(const GeomShapePtr& theShape,
-                                  const bool theIsStoreSameShapes = true);
+                                  const bool theIsStoreSameShapes = true) override;
 
   /// Stores the generated shape (called by the execution method).
   MODEL_EXPORT virtual void storeGenerated(const GeomShapePtr& theFromShape,
-                                           const GeomShapePtr& theToShape);
+                                           const GeomShapePtr& theToShape,
+                                           const bool theIsCleanStored = true) override;
+
+  /// Stores the root generated shapes (called by the execution method).
+  MODEL_EXPORT virtual void storeGenerated(const std::list<GeomShapePtr>& theFromShapes,
+    const GeomShapePtr& theToShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape) override;
 
   /// Stores the modified shape (called by the execution method).
   /// \param theOldShape shape that produces result
   /// \param theNewShape resulting shape
-  /// \param theDecomposeSolidsTag tag for starting of solids sub-elements placement in case
-  ///          theNewShape is compound of solids, if zero it is not used
+  /// \param theIsCleanStored erases all previous data structure of this body if true
   MODEL_EXPORT virtual void storeModified(const GeomShapePtr& theOldShape,
                                           const GeomShapePtr& theNewShape,
                                           const bool theIsCleanStored = true) override;
 
+  /// Stores the root modified shape (called by the execution method).
+  /// \param theOldShapes all shapes that produce result
+  /// \param theNewShape resulting shape
+  /// \param theIsCleanStored erases all previous data structure of this body if true
+  MODEL_EXPORT virtual void storeModified(const std::list<GeomShapePtr>& theOldShapes,
+    const GeomShapePtr& theNewShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape) override;
+
   /// Returns the shape-result produced by this feature
   MODEL_EXPORT virtual GeomShapePtr shape();
 
index 4acd17d8fa0a3732d69c6da75779ca9ee9aea54a..8368220f942ce1eae62c42e4b1a70bf5d6f7a7c3 100644 (file)
@@ -95,31 +95,12 @@ void Model_ResultBody::loadModifiedShapes(const std::shared_ptr<GeomAlgoAPI_Make
                                           const GeomAPI_Shape::ShapeType theShapeTypeToExplore,
                                           const std::string& theName)
 {
-  if (/*theSplitInSubs &&*/ mySubs.size()) { // consists of subs
+  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)->loadModifiedShapes(theAlgo, theOldShape, theShapeTypeToExplore, theName);
     }
   } else { // do for this directly
@@ -273,7 +254,14 @@ void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisS
       }
       GeomShapePtr anOldSubShape = aSub->shape();
       if (!aShape->isEqual(anOldSubShape)) {
-        aSub->store(aShape, false);
+        if (myAlgo.get()) {
+          std::list<GeomShapePtr> anOldForSub;
+          computeOldForSub(aShape, 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);
       }
@@ -311,6 +299,19 @@ void Model_ResultBody::updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisS
   }
 }
 
+void Model_ResultBody::updateSubs(
+  const GeomShapePtr& theThisShape, const std::list<GeomShapePtr>& theOlds,
+  const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape, const bool isGenerated)
+{
+  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();
@@ -339,3 +340,19 @@ void Model_ResultBody::cleanCash()
     aSub->cleanCash();
   }
 }
+
+void Model_ResultBody::computeOldForSub(
+  const GeomShapePtr& theSubShape, std::list<GeomShapePtr>& theOldForSub)
+{
+  std::list<GeomShapePtr>::iterator aRootOlds = myOlds.begin();
+  for(; aRootOlds != myOlds.end(); aRootOlds++) {
+    ListOfShape aNews;
+    myIsGenerated ? myAlgo->generated(*aRootOlds, aNews) : myAlgo->modified(*aRootOlds, aNews);
+    for(ListOfShape::iterator aNewIter = aNews.begin(); aNewIter != aNews.end(); aNewIter++) {
+      if (theSubShape->isSame(*aNewIter)) { // found old that was used for new theSubShape creation
+        theOldForSub.push_back(*aRootOlds);
+        break;
+      }
+    }
+  }
+}
index 09824971fb842b2d53223bde2e8ec6354c1b6227..e34d1989b842d1fd1e630c5a18f67db71a0a40d8 100644 (file)
@@ -43,6 +43,12 @@ class Model_ResultBody : public ModelAPI_ResultBody
   std::map<ObjectPtr, int> mySubsMap;
   /// Keeps the last state of the concealment flag in order to update it when needed.
   bool myLastConcealed;
+  /// History information for update subs
+  std::shared_ptr<GeomAlgoAPI_MakeShape> myAlgo;
+  /// All old shapes used for the root result construction
+  std::list<GeomShapePtr> myOlds;
+  /// Information about the kind of the history information: modified or generated
+  bool myIsGenerated;
 
 public:
 
@@ -109,9 +115,17 @@ protected:
   void updateSubs(const std::shared_ptr<GeomAPI_Shape>& theThisShape,
                   const bool theShapeChanged = true);
 
+  /// Updates the sub-bodies in accordance to the algorithm history information
+  void updateSubs(
+    const GeomShapePtr& theThisShape, const std::list<GeomShapePtr>& theOlds,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape, const bool isGenerated);
+
   // Checks the state of children and parents to send events of creation/erase when needed
   void updateConcealment();
 
+  /// Adds to theOldForSub only old shapes that where used for theSubShape creation
+  void computeOldForSub(const GeomShapePtr& theSubShape, std::list<GeomShapePtr>& theOldForSub);
+
   friend class Model_Objects;
 };
 
index f72202360adc13f33d0ef7addd1e0fe45490dfdc..7fce455c697370fa72de1f2746787090e2d233cb 100755 (executable)
@@ -47,13 +47,22 @@ public:
 
   /// Stores the generated shape (called by the execution method).
   virtual void storeGenerated(const GeomShapePtr& theFromShape,
-                              const GeomShapePtr& theToShape) = 0;
+                              const GeomShapePtr& theToShape,
+                              const bool theIsCleanStored = true) = 0;
+
+  /// Stores the root generated shapes (called by the execution method).
+  virtual void storeGenerated(const std::list<GeomShapePtr>& theFromShapes,
+    const GeomShapePtr& theToShape, const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape) = 0;
 
   /// Stores the modified shape (called by the execution method).
   virtual void storeModified(const GeomShapePtr& theOldShape,
                              const GeomShapePtr& theNewShape,
                              const bool theIsCleanStored = true) = 0;
 
+  /// Stores the root modified shapes (called by the execution method).
+  virtual void storeModified(const std::list<GeomShapePtr>& theOldShapes,
+    const GeomShapePtr& theNewShape, const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)=0;
+
   /// Returns the shape-result produced by this feature
   virtual GeomShapePtr shape() = 0;
 
index ab0e703e757950db86317e19fd13e542311f0ac2..00e6ad9efa66564f465359655a4ae76fdbf5eb0e 100644 (file)
@@ -67,6 +67,21 @@ void ModelAPI_ResultBody::storeGenerated(const GeomShapePtr& theFromShape,
   updateSubs(theToShape);
 }
 
+void ModelAPI_ResultBody::storeGenerated(
+  const std::list<GeomShapePtr>& theFromShapes, const GeomShapePtr& theToShape,
+  const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
+{
+  myBuilder->storeGenerated(theFromShapes, theToShape, theMakeShape);
+  myConnect = ConnectionNotComputed;
+
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+  aECreator->sendUpdated(data()->owner(), aRedispEvent);
+
+  updateSubs(theToShape, theFromShapes, theMakeShape, true);
+}
+
 void ModelAPI_ResultBody::storeModified(const GeomShapePtr& theOldShape,
                                         const GeomShapePtr& theNewShape,
                                         const bool theIsCleanStored)
@@ -82,6 +97,21 @@ void ModelAPI_ResultBody::storeModified(const GeomShapePtr& theOldShape,
   updateSubs(theNewShape);
 }
 
+void ModelAPI_ResultBody::storeModified(
+  const std::list<GeomShapePtr>& theOldShapes, const GeomShapePtr& theNewShape,
+  const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
+{
+  myBuilder->storeModified(theOldShapes, theNewShape, theMakeShape);
+  myConnect = ConnectionNotComputed;
+
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+  aECreator->sendUpdated(data()->owner(), aRedispEvent);
+
+  updateSubs(theNewShape, theOldShapes, theMakeShape, false);
+}
+
 GeomShapePtr ModelAPI_ResultBody::shape()
 {
   return myBuilder->shape();
index 20e0879f24f880a48337e4a02acdb3e2b39b803c..dc9ed31da298af7c779aefba7e4bd9e2b2b2fb95 100644 (file)
@@ -102,11 +102,21 @@ public:
   MODELAPI_EXPORT virtual void storeGenerated(const GeomShapePtr& theFromShape,
                                               const GeomShapePtr& theToShape);
 
+  /// Stores the root modified shapes (called by the execution method).
+  MODELAPI_EXPORT virtual void storeGenerated(
+    const std::list<GeomShapePtr>& theFromShapes, const GeomShapePtr& theToShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape);
+
   /// Stores the modified shape (called by the execution method).
   MODELAPI_EXPORT virtual void storeModified(const GeomShapePtr& theOldShape,
                                              const GeomShapePtr& theNewShape,
                                              const bool theIsCleanStored = true);
 
+  /// Stores the root modified shapes (called by the execution method).
+  MODELAPI_EXPORT virtual void storeModified(
+    const std::list<GeomShapePtr>& theOldShapes, const GeomShapePtr& theNewShape,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape);
+
   /// Returns the shape-result produced by this feature
   MODELAPI_EXPORT virtual GeomShapePtr shape();
 
@@ -165,6 +175,11 @@ public:
   MODELAPI_EXPORT virtual void updateSubs(const GeomShapePtr& theThisShape,
     const bool theShapeChanged = true) = 0;
 
+  /// Updates the sub-bodies in accordance to the algorithm history information
+  MODELAPI_EXPORT virtual void updateSubs(
+    const GeomShapePtr& theThisShape, const std::list<GeomShapePtr>& theOlds,
+    const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape, const bool isGenerated) = 0;
+
   /// Cleans cash related to the already stored elements
   MODELAPI_EXPORT virtual void cleanCash() = 0;