Salome HOME
Change algorithm of placing to data model's labels of shapes which have several parts...
[modules/shaper.git] / src / Model / Model_BodyBuilder.cpp
index c25d5dfa538c52cf1fa493bc27fa6db2956e46ed..d17fb8bd6424573b95794572ae72b03796f42b79 100755 (executable)
@@ -49,6 +49,7 @@
 #include <BRep_Tool.hxx>
 #include <GeomAPI_Shape.h>
 #include <GeomAlgoAPI_MakeShape.h>
+#include <GeomAlgoAPI_SortListOfShapes.h>
 #include <Config_PropManager.h>
 // DEB
 //#include <TCollection_AsciiString.hxx>
@@ -284,7 +285,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(aData->shapeLab().FindChild(theTag));
+    myBuilders[theTag] = new TNaming_Builder(
+      theTag == 0 ? aData->shapeLab() : aData->shapeLab().FindChild(theTag));
     aFind = myBuilders.find(theTag);
   }
   return aFind->second;
@@ -368,6 +370,35 @@ void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS,
   }
 }
 
+// Keep only the shapes with minimal shape type
+static void keepTopLevelShapes(ListOfShape& theShapes, const TopoDS_Shape& theRoot,
+  const GeomShapePtr& theResultShape = GeomShapePtr())
+{
+  GeomAPI_Shape::ShapeType aKeepShapeType = GeomAPI_Shape::SHAPE;
+  ListOfShape::iterator anIt = theShapes.begin();
+  while (anIt != theShapes.end()) {
+    TopoDS_Shape aNewShape = (*anIt)->impl<TopoDS_Shape>();
+    if (theRoot.IsSame(aNewShape) || (theResultShape &&
+        (!theResultShape->isSubShape(*anIt, false) || theResultShape->isSame(*anIt)))) {
+      ListOfShape::iterator aRemoveIt = anIt++;
+      theShapes.erase(aRemoveIt);
+    } else {
+      GeomAPI_Shape::ShapeType aType = (*anIt)->shapeType();
+      if (aType < aKeepShapeType) {
+        // found a shape with lesser shape type => remove all previous shapes
+        aKeepShapeType = aType;
+        theShapes.erase(theShapes.begin(), anIt);
+        ++anIt;
+      } else if (aType > aKeepShapeType) {
+        // shapes with greater shape type should be removed from the list
+        ListOfShape::iterator aRemoveIt = anIt++;
+        theShapes.erase(aRemoveIt);
+      } else
+        ++anIt;
+    }
+  }
+}
+
 void Model_BodyBuilder::loadAndOrientModifiedShapes (
   GeomAlgoAPI_MakeShape* theMS,
   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
@@ -396,6 +427,11 @@ 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);
+    // sort the list of images before naming
+    GeomAlgoAPI_SortListOfShapes::sort(aList);
+
     // to trace situation where several objects are produced by one parent (#2317)
     int aSameParentShapes = -1;
     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator
@@ -408,40 +444,67 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
       }
       GeomShapePtr aGeomNewShape(new GeomAPI_Shape());
       aGeomNewShape->setImpl(new TopoDS_Shape(aNewShape));
-      if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(aGeomNewShape, false)) {
+      if(!aRoot.IsSame(aNewShape) && aResultShape->isSubShape(aGeomNewShape, false) &&
+         !aResultShape->isSame(*anIt)) { // to avoid put of same shape on main label and sub
         int aBuilderTag = aTag;
         if (!theIsStoreSeparate)
           aSameParentShapes++;
+
+        static const int THE_ANCHOR_TAG = 100000;
+        int aCurShapeType = (int)((*anIt)->shapeType());
+        bool needSuffix = false; // suffix for the name based on the shape type
         if (aSameParentShapes > 0) { // store in other label
-          aBuilderTag = 100000 - aSameParentShapes * 10 - aTag;
+          aBuilderTag = THE_ANCHOR_TAG - aSameParentShapes * 10 - aCurShapeType;
+          needSuffix = true;
+        } else if (aCurShapeType != theKindOfShape) {
+          // modified shape has different type => set another tag
+          // to avoid shapes of different types on the same label
+          aBuilderTag = THE_ANCHOR_TAG - aCurShapeType;
+          needSuffix = true;
+        }
+        std::string aSuffix;
+        if (needSuffix) {
+          switch (aCurShapeType) {
+          case GeomAPI_Shape::VERTEX: aSuffix = "_v"; break;
+          case GeomAPI_Shape::EDGE:   aSuffix = "_e"; break;
+          case GeomAPI_Shape::FACE:   aSuffix = "_f"; break;
+          default: break;
+          }
         }
+
         if(theIsStoreAsGenerated) {
           // Here we store shapes as generated, to avoid problem when one parent shape produce
           // several child shapes. In this case naming could not determine which shape to select.
-          builder(aBuilderTag)->Generated(aRoot,aNewShape);
+          builder(aBuilderTag)->Generated(aRoot, aNewShape);
         } else {
-          builder(aBuilderTag)->Modify(aRoot,aNewShape);
+          builder(aBuilderTag)->Modify(aRoot, aNewShape);
         }
         if(isBuilt) {
-          if(theIsStoreSeparate) {
-            aStream.str(std::string());
-            aStream.clear();
-            aStream << theName << "_" << anIndex++;
-            aName = aStream.str();
-          }
+          aStream.str(std::string());
+          aStream.clear();
+          aStream << theName;
+          if(theIsStoreSeparate)
+             aStream << "_" << anIndex++;
+
           if (aSameParentShapes > 0) {
             aStream.str(std::string());
             aStream.clear();
             aStream << aName << "_" << aSameParentShapes << "divided";
-            std::string aNameDiv = aStream.str();
-            buildName(aBuilderTag, aNameDiv);
-          } else {
-            buildName(aBuilderTag, aName);
           }
+
+          aStream << aSuffix;
+          buildName(aBuilderTag, aStream.str());
         }
         if(theIsStoreSeparate) {
           aTag++;
         }
+      } else if (aResultShape->isSame(*anIt)) {
+        // keep the modification evolution on the root level (2241 - history propagation issue)
+        if(theIsStoreAsGenerated) {
+          builder(0)->Generated(aRoot, aNewShape);
+        } else {
+          builder(0)->Modify(aRoot, aNewShape);
+        }
       }
     }
   }
@@ -468,6 +531,7 @@ void Model_BodyBuilder::loadAndOrientGeneratedShapes (
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
     theMS->generated(aRShape, aList);
+    keepTopLevelShapes(aList, aRoot);
     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator
       anIt = aList.begin(), aLast = aList.end();
     for (; anIt != aLast; anIt++) {