Salome HOME
Additional fix for the #2659 optimization
[modules/shaper.git] / src / Model / Model_BodyBuilder.cpp
index ab2c1dec6e37483221a8f54ac486cc68fd8cf729..8428157d31ca889add69f292514427f879f1dbcd 100755 (executable)
@@ -129,7 +129,7 @@ static void evolutionToSelectionRec(TDF_Label theLab, const bool theFlag) {
 void Model_BodyBuilder::evolutionToSelection(const bool theFlag)
 {
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
-  if (!aData) // unknown case
+  if (!aData || !aData->isValid()) // unknown case
     return;
   TDF_Label& aShapeLab = aData->shapeLab();
   evolutionToSelectionRec(aShapeLab, theFlag);
@@ -213,6 +213,18 @@ void Model_BodyBuilder::storeGenerated(const std::shared_ptr<GeomAPI_Shape>& the
   }
 }
 
+TNaming_Builder* Model_BodyBuilder::builder(const int theTag)
+{
+  std::map<int, TNaming_Builder*>::iterator aFind = myBuilders.find(theTag);
+  if (aFind == myBuilders.end()) {
+    std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+    myBuilders[theTag] = new TNaming_Builder(
+      theTag == 0 ? aData->shapeLab() : aData->shapeLab().FindChild(theTag));
+    aFind = myBuilders.find(theTag);
+  }
+  return aFind->second;
+}
+
 void Model_BodyBuilder::storeModified(const std::shared_ptr<GeomAPI_Shape>& theOldShape,
   const std::shared_ptr<GeomAPI_Shape>& theNewShape, const int theDecomposeSolidsTag)
 {
@@ -223,7 +235,7 @@ void Model_BodyBuilder::storeModified(const std::shared_ptr<GeomAPI_Shape>& theO
     if (theDecomposeSolidsTag != -2)
       clean();
     // store the new shape as primitive
-    TNaming_Builder aBuilder(aShapeLab);
+    TNaming_Builder* aBuilder = builder(0);
     if (!theOldShape || !theNewShape)
       return;  // bad shape
     TopoDS_Shape aShapeOld = theOldShape->impl<TopoDS_Shape>();
@@ -232,15 +244,15 @@ void Model_BodyBuilder::storeModified(const std::shared_ptr<GeomAPI_Shape>& theO
     TopoDS_Shape aShapeNew = theNewShape->impl<TopoDS_Shape>();
     if (aShapeNew.IsNull())
       return;  // null shape inside
-    aBuilder.Modify(aShapeOld, aShapeNew);
-    if(!aBuilder.NamedShape()->IsEmpty()) {
+    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 =
             std::dynamic_pointer_cast<Model_Document>(document());
-          aDoc->addNamingName(aBuilder.NamedShape()->Label(), aName);
+          aDoc->addNamingName(aBuilder->NamedShape()->Label(), aName);
         }
       }
     }
@@ -290,18 +302,6 @@ Model_BodyBuilder::~Model_BodyBuilder()
   clean();
 }
 
-TNaming_Builder* Model_BodyBuilder::builder(const int theTag)
-{
-  std::map<int, TNaming_Builder*>::iterator aFind = myBuilders.find(theTag);
-  if (aFind == myBuilders.end()) {
-    std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
-    myBuilders[theTag] = new TNaming_Builder(
-      theTag == 0 ? aData->shapeLab() : aData->shapeLab().FindChild(theTag));
-    aFind = myBuilders.find(theTag);
-  }
-  return aFind->second;
-}
-
 void Model_BodyBuilder::buildName(const int theTag, const std::string& theName)
 {
   std::shared_ptr<Model_Document> aDoc = std::dynamic_pointer_cast<Model_Document>(document());
@@ -364,7 +364,8 @@ void Model_BodyBuilder::deleted(const std::shared_ptr<GeomAPI_Shape>& theOldShap
 void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS,
   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
   const int  theKindOfShape,
-  const int  theTag)
+  const int  theTag,
+  const GeomShapePtr theShapes)
 {
   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
   TopTools_MapOfShape aView;
@@ -375,15 +376,17 @@ void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS,
     if (!aView.Add(aRoot)) continue;
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
-    if (theMS->isDeleted (aRShape)) {
-      if (!aResultShape->isSubShape(aRShape, false)) {
-          ListOfShape aHist;
-          if (BRepTools_History::IsSupportedType(aRoot)) // to avoid crash in #2572
-            theMS->modified(aRShape, aHist);
-          if (aHist.size() == 0 || (aHist.size() == 1 && aHist.front()->isSame(aRShape)))
-            builder(theTag)->Delete(aRoot);
-      }
+    if (!theMS->isDeleted(aRShape)
+        || aResultShape->isSubShape(aRShape, false)
+        || (theShapes.get() && theShapes->isSubShape(aRShape, false))) {
+      continue;
     }
+
+    ListOfShape aHist;
+    if (BRepTools_History::IsSupportedType(aRoot)) // to avoid crash in #2572
+      theMS->modified(aRShape, aHist);
+    if (aHist.size() == 0 || (aHist.size() == 1 && aHist.front()->isSame(aRShape)))
+      builder(theTag)->Delete(aRoot);
   }
 }
 
@@ -464,7 +467,18 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
   TopTools_MapOfShape aView;
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
-  TopExp_Explorer aShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
+
+  TopoDS_Shape aShapeToIterate;
+  if (theMS->newShapesCollected(theShapeIn, theKindOfShape)) {
+    // use optimized set of old shapes for this
+    GeomShapePtr aCompound = theMS->oldShapesForNew(theShapeIn, aResultShape, theKindOfShape);
+    if (aCompound.get())
+      aShapeToIterate = aCompound->impl<TopoDS_Shape>();
+  } else {
+    aShapeToIterate = aShapeIn;
+  }
+
+  TopExp_Explorer aShapeExplorer (aShapeToIterate, (TopAbs_ShapeEnum)theKindOfShape);
   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
     if (!aView.Add(aRoot)) continue;
@@ -479,6 +493,7 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
     theMS->modified(aRShape, aList);
+
     if (!theIsStoreSeparate) {
       //keepTopLevelShapes(aList, aRoot, aResultShape);
       removeBadShapes(aList);
@@ -687,8 +702,18 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
         // Store only in case if it does not have reference.
         if (!aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {
           if (theIsStoreAsGenerated) {
+            TNaming_Builder* aBuilder = builder(0);
+            if (!aBuilder->NamedShape().IsNull() &&
+                aBuilder->NamedShape()->Evolution() != TNaming_GENERATED) {
+              myBuilders.erase(0); // clear old builder to avoid different evolutions crash
+            }
             builder(0)->Generated(aRoot, aNewShape);
           } else {
+            TNaming_Builder* aBuilder = builder(0);
+            if (!aBuilder->NamedShape().IsNull() &&
+              aBuilder->NamedShape()->Evolution() != TNaming_MODIFY) {
+              myBuilders.erase(0); // clear old builder to avoid different evolutions crash
+            }
             builder(0)->Modify(aRoot, aNewShape);
           }
         }
@@ -1107,7 +1132,7 @@ void Model_BodyBuilder::loadDisconnectedVertexes(std::shared_ptr<GeomAPI_Shape>
 std::shared_ptr<GeomAPI_Shape> Model_BodyBuilder::shape()
 {
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
-  if (aData) {
+  if (aData && aData->isValid()) {
     TDF_Label aShapeLab = aData->shapeLab();
     Handle(TDF_Reference) aRef;
     if (aShapeLab.FindAttribute(TDF_Reference::GetID(), aRef)) {