Salome HOME
Fix for the issue #1647 : problem with OB when sub-features are created.
[modules/shaper.git] / src / Model / Model_SelectionNaming.cpp
index fe623ef2e009b2380a8f3f6c420f72f0d2d8ad8d..5bf2d58c9f71c9e010ad0bb56de1f4f5e05bd124 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "Model_SelectionNaming.h"
 #include "Model_Document.h"
+#include "Model_Objects.h"
 #include <ModelAPI_Feature.h>
 #include <Events_InfoMessage.h>
 #include <ModelAPI_Session.h>
@@ -33,6 +34,7 @@
 #include <TDataStd_Name.hxx>
 #include <TColStd_MapOfTransient.hxx>
 #include <algorithm>
+#include <stdexcept>
 
 #ifdef DEB_NAMING
 #include <BRepTools.hxx>
@@ -44,7 +46,8 @@ Model_SelectionNaming::Model_SelectionNaming(TDF_Label theSelectionLab)
 }
 
 std::string Model_SelectionNaming::getShapeName(
-  std::shared_ptr<Model_Document> theDoc, const TopoDS_Shape& theShape)
+  std::shared_ptr<Model_Document> theDoc, const TopoDS_Shape& theShape,
+  const bool theAddContextName)
 {
   std::string aName;
   // check if the subShape is already in DF
@@ -53,8 +56,9 @@ std::string Model_SelectionNaming::getShapeName(
   if(!aNS.IsNull() && !aNS->IsEmpty()) { // in the document    
     if(aNS->Label().FindAttribute(TDataStd_Name::GetID(), anAttr)) {
       aName = TCollection_AsciiString(anAttr->Get()).ToCString();
-      if(!aName.empty()) {         
-        const TDF_Label& aLabel = theDoc->findNamingName(aName);
+      // indexes are added to sub-shapes not primitives (primitives must not be located at the same label)
+      if(!aName.empty() && aNS->Evolution() != TNaming_PRIMITIVE && theAddContextName) {
+        const TDF_Label& aLabel = aNS->Label();//theDoc->findNamingName(aName);
         static const std::string aPostFix("_");
         TNaming_Iterator anItL(aNS);
         for(int i = 1; anItL.More(); anItL.Next(), i++) {
@@ -64,7 +68,18 @@ std::string Model_SelectionNaming::getShapeName(
             break;
           }
         }
-      }        
+      }
+      if (theAddContextName && aName.find("/") == std::string::npos) { // searching for the context object
+        for(TDF_Label anObjL = aNS->Label(); anObjL.Depth() > 4; anObjL = anObjL.Father()) {
+          int aDepth = anObjL.Depth();
+          if (aDepth == 5 || aDepth == 7) {
+            ObjectPtr anObj = theDoc->objects()->object(anObjL);
+            if (anObj) {
+              aName = anObj->data()->name() + "/" + aName;
+            }
+          }
+        }
+      }
     }
   }
   return aName;
@@ -112,9 +127,17 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
 #endif
   std::shared_ptr<Model_Document> aDoc = 
     std::dynamic_pointer_cast<Model_Document>(theContext->document());
+  if (theContext->groupName() == ModelAPI_ResultPart::group()) {
+    ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(theContext);
+    int anIndex;
+    return aPart->data()->name() + "/" + aPart->nameInPart(theSubSh, anIndex);
+  }
+
+  // add the result name to the name of the shape (it was in BodyBuilder, but did not work on Result rename)
+  bool isNeedContextName = theContext->shape().get() && !theContext->shape()->isEqual(theSubSh);
 
   // check if the subShape is already in DF
-  aName = getShapeName(aDoc, aSubShape);
+  aName = getShapeName(aDoc, aSubShape, isNeedContextName);
   if(aName.empty() ) { // not in the document!
     TopAbs_ShapeEnum aType = aSubShape.ShapeType();
     switch (aType) {
@@ -161,7 +184,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
         // build name of the sub-shape Edge
         for(int i=1; i <= aSMap.Extent(); i++) {
           const TopoDS_Shape& aFace = aSMap.FindKey(i);
-          std::string aFaceName = getShapeName(aDoc, aFace);
+          std::string aFaceName = getShapeName(aDoc, aFace, isNeedContextName);
           if(i == 1)
             aName = aFaceName;
           else 
@@ -169,7 +192,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
         }
         TopTools_ListIteratorOfListOfShape itl(aListOfNbs);
         for (;itl.More();itl.Next()) {
-          std::string aFaceName = getShapeName(aDoc, itl.Value());
+          std::string aFaceName = getShapeName(aDoc, itl.Value(), isNeedContextName);
           aName += "&" + aFaceName;
         }                
       }
@@ -218,7 +241,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
             TopTools_ListIteratorOfListOfShape itl(aListE);
             for (int i = 1;itl.More();itl.Next(),i++) {
               const TopoDS_Shape& anEdge = itl.Value();
-              std::string anEdgeName = getShapeName(aDoc, anEdge);
+              std::string anEdgeName = getShapeName(aDoc, anEdge, isNeedContextName);
               if (anEdgeName.empty()) { // edge is not in DS, trying by faces anyway
                 isByFaces = true;
                 aName.clear();
@@ -238,7 +261,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
           TopTools_ListIteratorOfListOfShape itl(aList);
           for (int i = 1;itl.More();itl.Next(),i++) {
             const TopoDS_Shape& aFace = itl.Value();
-            std::string aFaceName = getShapeName(aDoc, aFace);
+            std::string aFaceName = getShapeName(aDoc, aFace, isNeedContextName);
             if(i == 1)
               aName = aFaceName;
             else 
@@ -248,10 +271,8 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
       }
       break;
     }
-    // register name                   
-    // aDoc->addNamingName(selectionLabel(), aName);
-    // the selected sub-shape will not be shared and as result it will not require registration
   }
+
   return aName;
 }
 
@@ -308,9 +329,13 @@ const TopoDS_Shape getShapeFromNS(
   if (n == std::string::npos) n = 0;
   std::string aSubString = theSubShapeName.substr(n + 1);
   n = aSubString.rfind('_');
-  if (n == std::string::npos) return aSelection;
-  aSubString = aSubString.substr(n+1);
-  int indx = atoi(aSubString.c_str());
+  int indx;
+  if (n == std::string::npos) {// for primitives this is a first 
+    indx = 1;
+  } else {
+    aSubString = aSubString.substr(n+1);
+    indx = atoi(aSubString.c_str());
+  }
 
   TNaming_Iterator anItL(theNS);
   for(int i = 1; anItL.More(); anItL.Next(), i++) {
@@ -325,18 +350,19 @@ const TopoDS_Shape findFaceByName(
   const std::string& theSubShapeName, std::shared_ptr<Model_Document> theDoc)
 {
   TopoDS_Shape aFace;
-  std::string::size_type n, nb = theSubShapeName.rfind('/');                   
-  if (nb == std::string::npos) nb = 0;
-  std::string aSubString = theSubShapeName.substr(nb + 1);
-  n = aSubString.rfind('_');
-  if (n != std::string::npos) {
-    std::string aSubStr2 = aSubString.substr(0, n);
-    aSubString  = theSubShapeName.substr(0, nb + 1);
-    aSubString = aSubString + aSubStr2;        
-  } else
-    aSubString = theSubShapeName;
-
-  const TDF_Label& aLabel = theDoc->findNamingName(aSubString);
+  //std::string::size_type n, nb = theSubShapeName.rfind('/');                 
+  //if (nb == std::string::npos) nb = 0;
+  //std::string aSubString = theSubShapeName.substr(nb + 1);
+  std::string aSubString = theSubShapeName;
+
+  TDF_Label aLabel = theDoc->findNamingName(aSubString);
+  if (aLabel.IsNull()) { // try to remove additional artificial suffix
+    std::string::size_type n = aSubString.rfind('_');
+    if (n != std::string::npos) {
+      aSubString = aSubString.substr(0, n);
+       aLabel = theDoc->findNamingName(aSubString);
+    }
+  }
   if(aLabel.IsNull()) return aFace;
   Handle(TNaming_NamedShape) aNS;
   if(aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
@@ -488,17 +514,18 @@ bool parseSubIndices(CompositeFeaturePtr theComp, //< to iterate names
     } else {
       int anOrientation = 1; // default
       if (theOriented) { // here must be a symbol in the end of digit 'f' or 'r'
-        const char aSymbol = anID.back();
-        if (aSymbol == 'r') anOrientation = -1;
-        anID.pop_back();
+        std::string::iterator aSymbol = anID.end() - 1;
+        if (*aSymbol == 'r') anOrientation = -1;
+        anID.erase(aSymbol); // remove last symbol
       }
       // check start/end symbols
-      if (anID.back() == 's') {
+      std::string::iterator aBack = anID.end() - 1;
+      if (*aBack == 's') {
         anOrientation *= 2;
-        anID.pop_back();
-      } else if (anID.back() == 'e') {
+        anID.erase(aBack); // remove last symbol
+      } else if (*aBack == 'e') {
         anOrientation *= 3;
-        anID.pop_back();
+        anID.erase(aBack); // remove last symbol
       }
 
       if (aNames.find(anID) != aNames.end()) {
@@ -581,9 +608,12 @@ std::string Model_SelectionNaming::shortName(
   aName.erase(std::remove(aName.begin(), aName.end(), '&'), aName.end());
   // remove the last 's', 'e', 'f' and 'r' symbols: they are used as markers of start/end/forward/rewersed indicators
   static const std::string aSyms("sefr");
-  while(aSyms.find(aName.back()) != std::string::npos) {
-    aName.pop_back();
+  std::string::iterator aSuffix = aName.end() - 1;
+  while(aSyms.find(*aSuffix) != std::string::npos) {
+    --aSuffix;
   }
+  aName.erase(aSuffix + 1, aName.end());
+
   if (theEdgeVertexPos == 1) {
     aName += "s"; // start
   } else if (theEdgeVertexPos == 2) {
@@ -629,7 +659,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
    // possible this is body where postfix is added to distinguish several shapes on the same label
   int aSubShapeId = -1; // -1 means sub shape not found
   // for result body the name wihtout "_" has higher priority than with it: it is always added
-  if ((!aCont.get() || (aCont->groupName() == ModelAPI_ResultBody::group())) && 
+  if ((!aCont.get()/* || (aCont->groupName() == ModelAPI_ResultBody::group())*/) && 
        aContName == aSubShapeName) {
     size_t aPostIndex = aContName.rfind('_');
     if (aPostIndex != std::string::npos) {
@@ -694,7 +724,7 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
         return true;
       } else if (aSubShapeId > 0) { // try to find sub-shape by the index
         TopExp_Explorer anExp(aCont->shape()->impl<TopoDS_Shape>(), aType);
-        for(; aSubShapeId > 0 && anExp.More(); aSubShapeId--) {
+        for(; aSubShapeId > 1 && anExp.More(); aSubShapeId--) {
           anExp.Next();
         }
         if (anExp.More()) {
@@ -741,7 +771,8 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
     if (aConstr.get() && aConstr->groupName() == ModelAPI_ResultConstruction::group()) {
       theCont = aConstr;
       if (isFullName) {
-        theShapeToBeSelected = aConstr->shape();
+        // For the full construction selection shape must be empty.
+        //theShapeToBeSelected = aConstr->shape();
         return true;
       }
       // for sketch sub-elements selected