Salome HOME
Issue #2811: Update content of Object node on creation moment
[modules/shaper.git] / src / Selector / Selector_FilterByNeighbors.cpp
index 43221ba64d776f06c1538cca23930a1e2d765570..2d5488e159d392b6c77b9d617b777eee7a46119a 100644 (file)
@@ -125,7 +125,7 @@ static const TopoDS_Shape findNeighbor(const TopoDS_Shape theContext,
   if (aMatches.Extent() == 1)
     return aMatches.First(); // already found good candidate
   TopoDS_Compound aResultCompound; // in case of geometrical name and many candidates
-                                   // iterate all matches to find by other (higher level) neighbors the best candidate
+  // iterate all matches to find by other (higher level) neighbors the best candidate
   TopoDS_Shape aGoodCandidate;
   TopTools_MapOfShape aGoodCandidates; // already added good candidates to the map
   for(TopoDS_ListOfShape::Iterator aCandidate(aMatches); aCandidate.More(); aCandidate.Next()) {
@@ -189,12 +189,13 @@ bool Selector_FilterByNeighbors::select(const TopoDS_Shape theContext, const Top
     }
     // iterate by the order in theContext to keep same naming names
     TopExp_Explorer anOrder(theContext, theValue.ShapeType());
+    TopTools_MapOfShape alreadyProcessed;
     for (; anOrder.More(); anOrder.Next()) {
-      if (aNewNB.Contains(anOrder.Current())) {
+      if (alreadyProcessed.Add(anOrder.Current()) && aNewNB.Contains(anOrder.Current())) {
         TopoDS_Shape aNewNBShape = anOrder.Current();
         // check which can be named correctly, without "by neighbors" type
         Selector_Algo* aSubAlgo = Selector_Algo::select(theContext, aNewNBShape,
-          newSubLabel(), baseDocument(), geometricalNaming(), false, false);
+          newSubLabel(), baseDocument(), geometricalNaming(), false, useIntersections());
         if (aSubAlgo) {
           // add to list of good NBs
           aNBs.push_back(std::pair<TopoDS_Shape, int>(aNewNBShape, aLevel));
@@ -207,7 +208,7 @@ bool Selector_FilterByNeighbors::select(const TopoDS_Shape theContext, const Top
       std::list<std::pair<TopoDS_Shape, int> >::iterator aNBIter = aNBs.begin();
       for(; aNBIter != aNBs.end(); aNBIter++) {
         Selector_Algo* aSubAlgo = Selector_Algo::select(theContext, aNBIter->first,
-          newSubLabel(), baseDocument(), geometricalNaming(), false, false);
+          newSubLabel(), baseDocument(), geometricalNaming(), false, useIntersections());
         if (append(aSubAlgo)) {
           myNBLevel.push_back(aNBIter->second);
         } else {
@@ -229,7 +230,7 @@ void Selector_FilterByNeighbors::store()
     TDataStd_IntegerArray::Set(label(), kLEVELS_ARRAY, 0, int(myNBLevel.size()) - 1);
   std::list<int>::iterator aLevel = myNBLevel.begin();
   for(int anIndex = 0; aLevel != myNBLevel.end(); aLevel++, anIndex++) {
-    anArray->SetValue(anIndex, *aLevel);
+    anArray->SetValue(anIndex, Abs(*aLevel));
   }
   // store all sub-selectors
   std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
@@ -254,12 +255,21 @@ bool Selector_FilterByNeighbors::restore()
   // restore sub-selectors
   bool aSubResult = true;
   for(TDF_ChildIterator aSub(label(), false); aSub.More(); aSub.Next()) {
-    Selector_Algo* aSubSel = restoreByLab(aSub.Value());
+    Selector_Algo* aSubSel = restoreByLab(aSub.Value(), baseDocument());
     if (!append(aSubSel, false)) {
-      break; // some empty label left in the end
+      if (!aSub.Value().HasAttribute())
+        break; // some empty label left in the end
+      // some selector fails, try to use rest selectors, myNBLevel becomes negative: unused
+      if (myNBLevel.size() > list().size()) {
+        std::list<int>::iterator aListIter = myNBLevel.begin();
+        for(int a = 0; a < list().size(); a++)
+          aListIter++;
+        *aListIter = -*aListIter;
+        list().push_back(NULL);
+      }
     }
   }
-  return true;
+  return myNBLevel.size() == list().size() && !myNBLevel.empty();
 }
 
 TDF_Label Selector_FilterByNeighbors::restoreByName(std::string theName,
@@ -275,7 +285,7 @@ TDF_Label Selector_FilterByNeighbors::restoreByName(std::string theName,
       TDF_Label aSubContext;
       Selector_Algo* aSubSel =
         Selector_Algo::restoreByName(
-          label(), baseDocument(), aSubStr, myShapeType, theNameGenerator, aSubContext);
+          newSubLabel(), baseDocument(), aSubStr, myShapeType, theNameGenerator, aSubContext);
       if (!append(aSubSel))
         return TDF_Label();
 
@@ -323,15 +333,18 @@ bool Selector_FilterByNeighbors::solve(const TopoDS_Shape& theContext)
   std::list<int>::iterator aLevel = myNBLevel.begin();
   std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
   for(; aSubSel != list().cend(); aSubSel++, aLevel++) {
-    if (!(*aSubSel)->solve(theContext)) {
-      return false;
+    if (*aLevel < 0)
+      continue; // skip because sub-selector is not good
+    if ((*aSubSel)->solve(theContext)) {
+      aNBs.push_back(std::pair<TopoDS_Shape, int>((*aSubSel)->value(), *aLevel));
     }
-    aNBs.push_back(std::pair<TopoDS_Shape, int>((*aSubSel)->value(), *aLevel));
   }
-  aResult = findNeighbor(theContext, aNBs, geometricalNaming());
-  if (!aResult.IsNull()) {
-    Selector_Algo::store(aResult);
-    return true;
+  if (!aNBs.empty()) {
+    aResult = findNeighbor(theContext, aNBs, geometricalNaming());
+    if (!aResult.IsNull()) {
+      Selector_Algo::store(aResult);
+      return true;
+    }
   }
   return false;
 }
@@ -343,6 +356,8 @@ std::string Selector_FilterByNeighbors::name(Selector_NameGenerator* theNameGene
   std::list<int>::iterator aLevel = myNBLevel.begin();
   std::list<Selector_Algo*>::const_iterator aSubSel = list().cbegin();
   for(; aSubSel != list().cend(); aSubSel++, aLevel++) {
+    if (!*aSubSel)
+      continue;
     aResult += "(" + (*aSubSel)->name(theNameGenerator) + ")";
     if (*aLevel > 1) {
       std::ostringstream aLevelStr;