Salome HOME
Merge commit 'f709219506b7cd587e94abc5ebed18d629df92d8'
[modules/shaper.git] / src / Selector / Selector_Modify.cpp
index 149a8e89dd61d57c6d843b73a5ee13e179345d44..536412e52f2ef9be90c6c59ac8b47a3fc7b4317b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2019  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2022  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
@@ -22,6 +22,8 @@
 #include <Selector_NameGenerator.h>
 #include <Selector_NExplode.h>
 
+#include <Locale_Convert.h>
+
 #include <TNaming_NamedShape.hxx>
 #include <TNaming_Iterator.hxx>
 #include <TNaming_SameShapeIterator.hxx>
@@ -40,6 +42,7 @@
 Selector_Modify::Selector_Modify() : Selector_Algo()
 {
   myWeakIndex = -1; // no index by default
+  myRecomputeWeakIndex = false;
 }
 
 // adds to theResult all labels that contain initial shapes for theValue located in theFinal
@@ -149,17 +152,18 @@ bool Selector_Modify::select(NCollection_List<Handle(TNaming_NamedShape)>& theMo
   const TopoDS_Shape theContext, const TopoDS_Shape theValue)
 {
   if (theModifList.Extent() > 1) { // searching for the best modification result: by context
+    bool isFound = false;
     Handle(TNaming_NamedShape) aCandidate;
     NCollection_List<Handle(TNaming_NamedShape)>::Iterator aModIter(theModifList);
-    for (; !theModifList.IsEmpty() && aModIter.More(); aModIter.Next()) {
+    for (; aModIter.More() && !isFound; aModIter.Next()) {
       aCandidate = aModIter.Value();
       TDF_Label aFatherLab = aCandidate->Label().Father();
       Handle(TNaming_NamedShape) aFatherNS;
       if (aFatherLab.FindAttribute(TNaming_NamedShape::GetID(), aFatherNS)) {
-        for (TNaming_Iterator anIter(aFatherNS); anIter.More(); anIter.Next()) {
+        for (TNaming_Iterator anIter(aFatherNS);
+             anIter.More() && !isFound; anIter.Next()) {
           if (theContext.IsSame(anIter.NewShape())) { // found the best modification
-            theModifList.Clear();
-            break;
+            isFound = true;
           }
         }
       }
@@ -243,29 +247,62 @@ bool Selector_Modify::restore()
 TDF_Label Selector_Modify::restoreByName(std::wstring theName,
   const TopAbs_ShapeEnum theShapeType, Selector_NameGenerator* theNameGenerator)
 {
+  typedef NCollection_DataMap<TopoDS_Shape, bool, TopTools_ShapeMapHasher> MapOfCompsolids;
+  MapOfCompsolids aWrongSubsCompsolids;
+
   TDF_Label aContext;
-  for(size_t anEnd, aStart = 0; aStart != std::string::npos; aStart = anEnd) {
+  for(size_t anEnd, aStart = 0; aStart != std::wstring::npos; aStart = anEnd) {
     if (aStart != 0)
       aStart++;
-    anEnd = theName.find('&', aStart);
+    anEnd = theName.find(L'&', aStart);
     std::wstring aSubStr =
-      theName.substr(aStart, anEnd == std::string::npos ? anEnd : anEnd - aStart);
-    if (aSubStr.find(weakNameID()) == 0) { // weak name identifier
-      std::wstring aWeakIndex = aSubStr.substr(weakNameID().size());
-      myWeakIndex = std::stoi(aWeakIndex.c_str());
+      theName.substr(aStart, anEnd == std::wstring::npos ? anEnd : anEnd - aStart);
+    size_t aFoundOldWeak = aSubStr.find(oldWeakNameID());
+    size_t aFoundNewWeak = aFoundOldWeak != std::wstring::npos ?
+                           aSubStr.find(weakNameID()) :
+                           aFoundOldWeak;
+    if (aFoundOldWeak == 0 || aFoundNewWeak == 0) { // weak name identifier
+      std::wstring aWeakIndex = aSubStr.substr(aFoundOldWeak + oldWeakNameID().size());
+      myWeakIndex = atoi(Locale::Convert::toString(aWeakIndex).c_str());
+      myRecomputeWeakIndex = aFoundOldWeak == 0;
       continue;
     }
     TDF_Label aSubContext, aValue;
     if (!theNameGenerator->restoreContext(aSubStr, aSubContext, aValue))
       return TDF_Label(); // can not restore
-    if(aSubContext.IsNull() || aValue.IsNull())
+    if (aSubContext.IsNull() || (aValue.IsNull() && theShapeType <= TopAbs_SHELL))
       return TDF_Label(); // can not restore
     if (myFinal.IsNull()) {
       myFinal = aValue;
       aContext = aSubContext;
-    } else
-      myBases.Append(aValue);
+    } else {
+      // This could be a solid in a compsolid, which was not modified by the previous operation,
+      // however, the selected subshape is stored on its sub-label by mistake. Thus, wait until
+      // the end of processing to check whether the subshape is found in another solid.
+      TDF_Label aParent = aSubContext.Father().Father();
+      Handle(TNaming_NamedShape) aNS;
+      if (aParent.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+        TopoDS_Shape aShape = aNS->Get();
+        if (aShape.ShapeType() == TopAbs_COMPSOLID) {
+          if (aWrongSubsCompsolids.IsBound(aShape)) {
+            if (!aValue.IsNull())
+              aWrongSubsCompsolids.Bind(aShape, true);
+          } else
+            aWrongSubsCompsolids.Bind(aShape, !aValue.IsNull());
+        }
+      } else if (aValue.IsNull())
+        return TDF_Label();
+
+      if (!aValue.IsNull())
+        myBases.Append(aValue);
+    }
   }
+
+  // check all compsolids are processed and names are resolved
+  for (MapOfCompsolids::Iterator anIt(aWrongSubsCompsolids); anIt.More(); anIt.Next())
+    if (!anIt.Value())
+      return TDF_Label();
+
   return aContext;
 }
 
@@ -282,8 +319,9 @@ bool Selector_Modify::solve(const TopoDS_Shape& theContext)
           aCommon.Append(aNewShape);
       }
     }
-    Selector_NExplode aNexp(aCommon);
+    Selector_NExplode aNexp(aCommon, myRecomputeWeakIndex);
     aResult = aNexp.shape(myWeakIndex);
+    myRecomputeWeakIndex = false;
   } else { // standard case
     TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases
     findModificationResult(aFinalsCommon);
@@ -291,8 +329,9 @@ bool Selector_Modify::solve(const TopoDS_Shape& theContext)
       aResult = aFinalsCommon.First();
       findNewVersion(theContext, aResult);
     } else if (aFinalsCommon.Extent() > 1 && myWeakIndex > 0) {
-      Selector_NExplode aNExp(aFinalsCommon);
+      Selector_NExplode aNExp(aFinalsCommon, myRecomputeWeakIndex);
       aResult = aNExp.shape(myWeakIndex);
+      myRecomputeWeakIndex = false;
       findNewVersion(theContext, aResult);
     } else if (aFinalsCommon.Extent() > 1 && geometricalNaming()) {// if same geometry - compound
       TopoDS_ListOfShape::Iterator aCommonIter(aFinalsCommon);
@@ -331,17 +370,17 @@ std::wstring Selector_Modify::name(Selector_NameGenerator* theNameGenerator)
   if (!myFinal.FindAttribute(TDataStd_Name::GetID(), aName))
     return L"";
   aResult += theNameGenerator->contextName(myFinal) + L"/";
-  aResult += (wchar_t*)aName->Get().ToExtString();
+  aResult += Locale::Convert::toWString(aName->Get().ToExtString());
   for(TDF_LabelList::iterator aBase = myBases.begin(); aBase != myBases.end(); aBase++) {
     if (!aBase->FindAttribute(TDataStd_Name::GetID(), aName))
       return L"";
     aResult += L"&";
     aResult += theNameGenerator->contextName(*aBase) + L"/";
-    aResult += (wchar_t*)aName->Get().ToExtString();
+    aResult += Locale::Convert::toWString(aName->Get().ToExtString());
   }
   if (myWeakIndex != -1) {
     std::wostringstream aWeakStr;
-    aWeakStr<<"&"<<weakNameID()<<myWeakIndex;
+    aWeakStr<<L"&"<<weakNameID()<<myWeakIndex;
     aResult += aWeakStr.str();
   }
   return aResult;