Salome HOME
Fix for #19754: EDF 21721 - Problems with a study
[modules/shaper.git] / src / Model / Model_BodyBuilder.cpp
index 5c89b7cc31fa069cdcfb89defed73961c4f32af1..21e27c86918fb91874aa629c03b39a8fa2a517bf 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2020  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
@@ -19,6 +19,8 @@
 
 #include <Model_BodyBuilder.h>
 
+#include <Locale_Convert.h>
+
 #include <Model_Data.h>
 #include <Model_Document.h>
 #include <ModelAPI_Session.h>
@@ -79,6 +81,7 @@ static int getGenerationTag(const TopoDS_Shape& theShape) {
     case TopAbs_VERTEX: return GENERATED_VERTICES_TAG;
     case TopAbs_EDGE:   return GENERATED_EDGES_TAG;
     case TopAbs_FACE:   return GENERATED_FACES_TAG;
+    default: break; // [to avoid compilation warning]
   }
 
   return INVALID_TAG;
@@ -90,6 +93,7 @@ static int getModificationTag(const TopoDS_Shape& theShape) {
     case TopAbs_VERTEX: return MODIFIED_VERTICES_TAG;
     case TopAbs_EDGE:   return MODIFIED_EDGES_TAG;
     case TopAbs_FACE:   return MODIFIED_FACES_TAG;
+    default: break; // [to avoid compilation warning]
   }
 
   return INVALID_TAG;
@@ -183,7 +187,9 @@ void Model_BodyBuilder::store(const GeomShapePtr& theShape,
       return;  // null shape inside
 
     if(!theIsStoreSameShapes) {
-      Handle(TNaming_NamedShape) aNS = TNaming_Tool::NamedShape(aShape, aShapeLab);
+      Handle(TNaming_NamedShape) aNS;
+      if (TNaming_Tool::HasLabel(aShapeLab, aShape))
+        aNS = TNaming_Tool::NamedShape(aShape, aShapeLab);
       // the last condition is for the issue 2751 : existing shape may be found in compound-NS
       if(!aNS.IsNull() && !aNS->IsEmpty() && aNS->Get().IsSame(aShape)) {
         // This shape is already in document, store reference instead of shape;
@@ -200,7 +206,7 @@ void Model_BodyBuilder::store(const GeomShapePtr& theShape,
     if(!aBuilder.NamedShape()->IsEmpty()) {
       Handle(TDataStd_Name) anAttr;
       if(aBuilder.NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
-        std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
+        std::wstring aName = Locale::Convert::toWString(anAttr->Get().ToExtString());
         if(!aName.empty()) {
           std::shared_ptr<Model_Document> aDoc =
             std::dynamic_pointer_cast<Model_Document>(document());
@@ -216,7 +222,6 @@ void Model_BodyBuilder::storeGenerated(const GeomShapePtr& theFromShape,
 {
   std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
   if (aData) {
-    TDF_Label aShapeLab = aData->shapeLab();
     // clean builders
     if (theIsCleanStored)
       clean();
@@ -253,7 +258,7 @@ void Model_BodyBuilder::storeGenerated(const GeomShapePtr& theFromShape,
     if(!aBuilder->NamedShape()->IsEmpty()) {
       Handle(TDataStd_Name) anAttr;
       if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(),anAttr)) {
-        std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
+        std::wstring aName = Locale::Convert::toWString(anAttr->Get().ToExtString());
         if(!aName.empty()) {
           std::shared_ptr<Model_Document> aDoc =
             std::dynamic_pointer_cast<Model_Document>(document());
@@ -298,8 +303,8 @@ 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));
+    TDF_Label aLab = theTag == 0 ? aData->shapeLab() : aData->shapeLab().FindChild(theTag);
+    myBuilders[theTag] = new TNaming_Builder(aLab);
     aFind = myBuilders.find(theTag);
   }
   return aFind->second;
@@ -345,7 +350,7 @@ void Model_BodyBuilder::storeModified(const GeomShapePtr& theOldShape,
     if(!aBuilder->NamedShape()->IsEmpty()) {
       Handle(TDataStd_Name) anAttr;
       if(aBuilder->NamedShape()->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) {
-        std::string aName (TCollection_AsciiString(anAttr->Get()).ToCString());
+        std::wstring aName = Locale::Convert::toWString(anAttr->Get().ToExtString());
         if(!aName.empty()) {
           std::shared_ptr<Model_Document> aDoc =
             std::dynamic_pointer_cast<Model_Document>(document());
@@ -363,7 +368,8 @@ void Model_BodyBuilder::storeModified(const std::list<GeomShapePtr>& theOldShape
   std::list<GeomShapePtr>::const_iterator anOldIter = theOldShapes.cbegin();
   for(; anOldIter != theOldShapes.cend(); anOldIter++) {
     // compounds may cause crash if call "modified"
-    bool aStore = (*anOldIter)->isCompound() || (*anOldIter)->isShell() || (*anOldIter)->isWire();
+    bool aStore = (*anOldIter)->isCompound() || (*anOldIter)->isShell() || (*anOldIter)->isWire() ||
+               (*anOldIter)->isCompSolid();
     if (!aStore) {
       ListOfShape aNews; // check this old really modifies theNewShape
       theMakeShape->modified(*anOldIter, aNews);
@@ -380,8 +386,26 @@ void Model_BodyBuilder::storeModified(const std::list<GeomShapePtr>& theOldShape
       aStored = !aBuilder->NamedShape()->IsEmpty();
     }
   }
-  if (!aStored) { // store as PRIMITIVE, but clean in any way
-    store(theNewShape);
+  if (!aStored) {
+    // check the new shape is already in the tree, so, no need to store primitive, just reference
+    std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(data());
+    if (aData.get()) {
+      TDF_Label aShapeLab = aData->shapeLab();
+      TopoDS_Shape aShapeNew = theNewShape->impl<TopoDS_Shape>();
+      Handle(TNaming_NamedShape) aNS;
+      if (TNaming_Tool::HasLabel(aShapeLab, aShapeNew))
+        aNS = TNaming_Tool::NamedShape(aShapeNew, aShapeLab);
+      // the last condition is for the issue 2751 : existing shape may be found in compound-NS
+      if (!aNS.IsNull() && !aNS->IsEmpty() && aNS->Get().IsSame(aShapeNew)) {
+        // This shape is already in document, store reference instead of shape;
+        const TDF_Label aFoundLabel = aNS->Label();
+        TDF_Reference::Set(aShapeLab, aFoundLabel);
+        myBuilders.erase(0);
+        aShapeLab.ForgetAttribute(TNaming_NamedShape::GetID());
+        return;
+      }
+    }
+    store(theNewShape); // store as PRIMITIVE, but clean in any way
     return;
   }
 }
@@ -407,6 +431,11 @@ void Model_BodyBuilder::clean()
   for(; anEntriesIter.More(); anEntriesIter.Next()) {
     anEntriesIter.Value()->Label().ForgetAttribute(kEXTERNAL_SHAPE_REF);
   }
+  // to clear old shapes in all sub-labels (they may be left without builders on Open)
+  TDF_ChildIDIterator aNSIter(aLab, TNaming_NamedShape::GetID(), true);
+  for(; aNSIter.More(); aNSIter.Next()) {
+    aNSIter.Value()->Label().ForgetAttribute(aNSIter.Value());
+  }
 }
 
 void Model_BodyBuilder::cleanCash()
@@ -915,8 +944,12 @@ int findAmbiguities(const TopoDS_Shape&           theShapeIn,
 //=======================================================================
 void Model_BodyBuilder::loadFirstLevel(GeomShapePtr theShape, const std::string& theName)
 {
-  if(theShape->isNull()) return;
-  TopoDS_Shape aShape = theShape->impl<TopoDS_Shape>();
+  GeomShapePtr aShapePtr = shape();
+  if (theShape->isNull() || !aShapePtr.get())
+    return;
+  TopoDS_Shape aShape = shape()->impl<TopoDS_Shape>();
+  if (aShape.IsNull())
+    return;
   std::string aName;
   if (aShape.ShapeType() == TopAbs_COMPOUND || aShape.ShapeType() == TopAbs_COMPSOLID) {
     TopoDS_Iterator itr(aShape);