Salome HOME
Useful commits from master and V8_5_0
[modules/shaper.git] / src / Model / Model_BodyBuilder.cpp
index 623ed23edd1b63dba50b24df9d64a17ecc13fcfa..1a8ea5507f9518ca3810ac4bb6ba615e21bbfe6d 100755 (executable)
@@ -215,7 +215,8 @@ void Model_BodyBuilder::storeModified(const std::shared_ptr<GeomAPI_Shape>& theO
   if (aData) {
     TDF_Label& aShapeLab = aData->shapeLab();
     // clean builders
-    clean();
+    if (theDecomposeSolidsTag != -2)
+      clean();
     // store the new shape as primitive
     TNaming_Builder aBuilder(aShapeLab);
     if (!theOldShape || !theNewShape)
@@ -359,17 +360,63 @@ void Model_BodyBuilder::loadDeletedShapes (GeomAlgoAPI_MakeShape* theMS,
   TopoDS_Shape aShapeIn = theShapeIn->impl<TopoDS_Shape>();
   TopTools_MapOfShape aView;
   TopExp_Explorer ShapeExplorer (aShapeIn, (TopAbs_ShapeEnum)theKindOfShape);
+  GeomShapePtr aResultShape = shape();
   for (; ShapeExplorer.More(); ShapeExplorer.Next ()) {
     const TopoDS_Shape& aRoot = ShapeExplorer.Current ();
     if (!aView.Add(aRoot)) continue;
     std::shared_ptr<GeomAPI_Shape> aRShape(new GeomAPI_Shape());
     aRShape->setImpl((new TopoDS_Shape(aRoot)));
     if (theMS->isDeleted (aRShape)) {
-      builder(theTag)->Delete(aRoot);
+      if (!aResultShape->isSubShape(aRShape, false)) {
+          ListOfShape aHist;
+          theMS->modified(aRShape, aHist);
+          if (aHist.size() == 0 || (aHist.size() == 1 && aHist.front()->isSame(aRShape)))
+            builder(theTag)->Delete(aRoot);
+      }
     }
   }
 }
 
+// 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>();
+    bool aSkip = aNewShape.IsNull() ||
+      (aNewShape.ShapeType() == TopAbs_EDGE && BRep_Tool::Degenerated(TopoDS::Edge(aNewShape)));
+    if (aSkip || 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;
+    }
+  }
+}
+
+// returns an ancestor shape-type thaty used for naming-definition of the sub-type
+TopAbs_ShapeEnum typeOfAncestor(const TopAbs_ShapeEnum theSubType) {
+  if (theSubType == TopAbs_VERTEX)
+    return TopAbs_EDGE;
+  if (theSubType == TopAbs_EDGE)
+    return TopAbs_FACE;
+  return TopAbs_VERTEX; // bad case
+}
+
 void Model_BodyBuilder::loadAndOrientModifiedShapes (
   GeomAlgoAPI_MakeShape* theMS,
   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
@@ -388,16 +435,24 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
   GeomShapePtr aResultShape = shape();
   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);
   for (; aShapeExplorer.More(); aShapeExplorer.Next ()) {
     const TopoDS_Shape& aRoot = aShapeExplorer.Current ();
     if (!aView.Add(aRoot)) continue;
-    if (TNaming_Tool::NamedShape(aRoot, builder(theTag)->NamedShape()->Label()).IsNull())
-      continue; // there is no sense to write history if old shape does not exist in the document
+
+    bool aNotInTree =
+      TNaming_Tool::NamedShape(aRoot, aData->shapeLab()).IsNull();
+    if (aNotInTree && !theIsStoreSeparate) {
+      // there is no sense to write history if old shape does not exist in the document
+      continue; // but if it is stored separately, it will be builded as a primitive
+    }
     ListOfShape aList;
     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);
 
@@ -416,34 +471,83 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
       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)
+        if (!theIsStoreSeparate) {
           aSameParentShapes++;
+        } else if (aNotInTree) { // check this new shape can not be represented as
+          // a sub-shape of higher level sub-shapes
+          TopAbs_ShapeEnum aNewType = aNewShape.ShapeType();
+          TopAbs_ShapeEnum anAncestorType = typeOfAncestor(aNewType);
+          if (anAncestorType != TopAbs_VERTEX) {
+            bool aFound = false;
+            TopoDS_Shape aResultTShape = aResultShape->impl<TopoDS_Shape>();
+            TopExp_Explorer anAncestorExp(aResultTShape, anAncestorType);
+            for(; anAncestorExp.More() && !aFound; anAncestorExp.Next()) {
+              if (aResultTShape.IsSame(anAncestorExp.Current()))
+                continue;
+              TopExp_Explorer aSubExp(anAncestorExp.Current(), aNewType);
+              for(; aSubExp.More(); aSubExp.Next()) {
+                if (aNewShape.IsSame(aSubExp.Current())) {
+                  aFound = true;
+                  break;
+                }
+              }
+            }
+            if (aFound) {
+              continue; // not need to store this shape in the BRep structure
+            }
+          }
+        }
+
+        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);
+        } else if (aNotInTree) {
+          // not in tree -> store as primitive (stored as separated)
+          builder(aBuilderTag)->Generated(aNewShape);
+        } else if (aNewShape.ShapeType() > aRoot.ShapeType()) {
+           // if lower-level type is produced, make it as generated
+          builder(aBuilderTag)->Generated(aRoot, aNewShape);
         } else {
           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++;
@@ -460,27 +564,6 @@ void Model_BodyBuilder::loadAndOrientModifiedShapes (
   }
 }
 
-// Keep only the shapes with minimal shape type
-static void keepTopLevelShapes(ListOfShape& theShapes)
-{
-  GeomAPI_Shape::ShapeType aKeepShapeType = GeomAPI_Shape::SHAPE;
-  ListOfShape::iterator anIt = theShapes.begin();
-  while (anIt != theShapes.end()) {
-    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::loadAndOrientGeneratedShapes (
   GeomAlgoAPI_MakeShape* theMS,
   std::shared_ptr<GeomAPI_Shape>  theShapeIn,
@@ -502,7 +585,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);
+    keepTopLevelShapes(aList, aRoot);
     std::list<std::shared_ptr<GeomAPI_Shape> >::const_iterator
       anIt = aList.begin(), aLast = aList.end();
     for (; anIt != aLast; anIt++) {