Salome HOME
Issue #2964: Coloring of a step field on a part
[modules/shaper.git] / src / Selector / Selector_Algo.cpp
index 50e652a6366c2ba3895d3f7ff35b7688c0e4c1e7..0c860c517d43115babf1ce00bb471376ed49740b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2019  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
 //
 // You should have received a copy of the GNU Lesser General Public
 // License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include <Selector_Algo.h>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS.hxx>
+#include <TopTools_MapOfShape.hxx>
 #include <Geom_Surface.hxx>
 #include <BRep_Tool.hxx>
 #include <TNaming_Builder.hxx>
 #include <TNaming_Tool.hxx>
 #include <TNaming_SameShapeIterator.hxx>
 #include <TNaming_Iterator.hxx>
+#include <TNaming_NewShapeIterator.hxx>
 #include <TDataStd_ReferenceArray.hxx>
 #include <TDataStd_ExtStringList.hxx>
 #include <TDataStd_Integer.hxx>
+#include <TDataStd_UAttribute.hxx>
+#include <TopoDS_Iterator.hxx>
+#include <TopExp_Explorer.hxx>
+#include <BRep_Builder.hxx>
+
 
 /// type of the selection, integer keeps the Selector_Type value
 static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6");
@@ -60,6 +66,24 @@ Selector_Algo::Selector_Algo()
   myAlwaysGeometricalNaming = false;
 }
 
+static TDF_Label findGoodLabelWithShape(const TDF_Label theAccess, const TopoDS_Shape& theShape) {
+  TDF_Label aResult;
+  if (TNaming_Tool::HasLabel(theAccess, theShape)) { // selection and delete evolution are not used
+    for(TNaming_SameShapeIterator aShapes(theShape, theAccess); aShapes.More(); aShapes.Next())
+    {
+      Handle(TNaming_NamedShape) aNS;
+      if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+        if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
+            aNS->Evolution() == TNaming_PRIMITIVE) {
+          aResult = aNS->Label();
+          break;
+        }
+      }
+    }
+  }
+  return aResult;
+}
+
 #define SET_ALGO_FLAGS(algo) \
   algo->myLab = theAccess; \
   algo->myBaseDocumentLab = theBaseDocument; \
@@ -79,37 +103,9 @@ Selector_Algo* Selector_Algo::select(const TopoDS_Shape theContext, const TopoDS
 
   // check the value shape can be named as it is, or it is needed to construct it from the
   // higher level shapes (like a box vertex by faces that form this vertex)
-  bool aIsFound = TNaming_Tool::HasLabel(theAccess, theValue);
-  if (aIsFound) { // additional check for selection and delete evolution only: also could not use
-    aIsFound = false;
-    for(TNaming_SameShapeIterator aShapes(theValue, theAccess); aShapes.More(); aShapes.Next())
-    {
-      Handle(TNaming_NamedShape) aNS;
-      if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
-        if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
-          aNS->Evolution() == TNaming_PRIMITIVE) {
-          aIsFound = true;
-          break;
-        }
-      }
-    }
-  }
-  // searching in the base document
-  if (!aIsFound && !theBaseDocument.IsNull() && TNaming_Tool::HasLabel(theBaseDocument, theValue))
-  {
-    TNaming_SameShapeIterator aShapes(theValue, theBaseDocument);
-    for(; aShapes.More(); aShapes.Next())
-    {
-      Handle(TNaming_NamedShape) aNS;
-      if (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
-        if (aNS->Evolution() == TNaming_MODIFY || aNS->Evolution() == TNaming_GENERATED ||
-          aNS->Evolution() == TNaming_PRIMITIVE) {
-          aIsFound = true;
-          break;
-        }
-      }
-    }
-  }
+  bool aIsFound = !findGoodLabelWithShape(theAccess, theValue).IsNull();
+  if (!aIsFound && !theBaseDocument.IsNull()) // searching in the base document
+    aIsFound = !findGoodLabelWithShape(theBaseDocument, theValue).IsNull();
   if (!aIsFound) {
     TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
     if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
@@ -120,8 +116,9 @@ Selector_Algo* Selector_Algo::select(const TopoDS_Shape theContext, const TopoDS
       if (aContainer->select(theContext, theValue))
         return aContainer;
       delete aContainer;
-      return false;
+      return NULL;
     }
+
     Selector_Intersect* anIntersect = new Selector_Intersect;
     SET_ALGO_FLAGS(anIntersect);
     bool aGoodIntersector = anIntersect->select(theContext, theValue);
@@ -131,12 +128,16 @@ Selector_Algo* Selector_Algo::select(const TopoDS_Shape theContext, const TopoDS
     }
     if (!theUseNeighbors) {
       delete anIntersect;
-      return false;
+      return NULL;
     }
     // searching by neighbors
     Selector_FilterByNeighbors* aNBs = new Selector_FilterByNeighbors;
     SET_ALGO_FLAGS(aNBs);
-    if (aNBs->select(theContext, theValue)) {
+    // searching a context lab to store in NB algorithm
+    TDF_Label aContextLab = findGoodLabelWithShape(theAccess, theContext);
+    if (aContextLab.IsNull() && !theBaseDocument.IsNull()) // search also in the base document
+      aContextLab = findGoodLabelWithShape(theBaseDocument, theContext);
+    if (aNBs->select(aContextLab, theContext, theValue)) {
       delete anIntersect;
       return aNBs;
     }
@@ -200,12 +201,16 @@ Selector_Algo* Selector_Algo::select(const TopoDS_Shape theContext, const TopoDS
     }
     if (!theUseNeighbors) {
       delete aModify;
-      return false;
+      return NULL;
     }
     // searching by neighbors
     Selector_FilterByNeighbors* aNBs = new Selector_FilterByNeighbors;
     SET_ALGO_FLAGS(aNBs);
-    if (aNBs->select(theContext, theValue)) {
+    // searching a context lab to store in NB algorithm
+    TDF_Label aContextLab = findGoodLabelWithShape(theAccess, theContext);
+    if (aContextLab.IsNull() && !theBaseDocument.IsNull()) // search also in the base document
+      aContextLab = findGoodLabelWithShape(theBaseDocument, theContext);
+    if (aNBs->select(aContextLab, theContext, theValue)) {
       delete aModify;
       return aNBs;
     }
@@ -372,7 +377,7 @@ Selector_Algo* Selector_Algo::restoreByLab(TDF_Label theLab, TDF_Label theBaseDo
 }
 
 Selector_Algo* Selector_Algo::restoreByName(TDF_Label theLab, TDF_Label theBaseDocLab,
-  std::string theName, const TopAbs_ShapeEnum theShapeType,
+  std::string theName, const TopAbs_ShapeEnum theShapeType, const bool theGeomNaming,
   Selector_NameGenerator* theNameGenerator, TDF_Label& theContextLab)
 {
   Selector_Algo* aResult = NULL;
@@ -403,6 +408,7 @@ Selector_Algo* Selector_Algo::restoreByName(TDF_Label theLab, TDF_Label theBaseD
   if (aResult) {
     aResult->myLab = theLab;
     aResult->myBaseDocumentLab = theBaseDocLab;
+    aResult->myGeometricalNaming = theGeomNaming;
     theContextLab = aResult->restoreByName(theName, theShapeType, theNameGenerator);
     if (theContextLab.IsNull()) {
       delete aResult;
@@ -414,5 +420,76 @@ Selector_Algo* Selector_Algo::restoreByName(TDF_Label theLab, TDF_Label theBaseD
 
 void Selector_Algo::storeType(const Selector_Type theType)
 {
+  myLab.ForgetAllAttributes(true);
   TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)(theType));
+  if (myGeometricalNaming)
+    TDataStd_UAttribute::Set(myLab, kGEOMETRICAL_NAMING);
+}
+
+/// Returns true if theSub is in theContext shape
+static bool isInContext(const TopoDS_Shape& theContext, const TopoDS_Shape& theSub) {
+  for(TopExp_Explorer anExp(theContext, theSub.ShapeType()); anExp.More(); anExp.Next()) {
+    if (anExp.Current().IsSame(theSub))
+      return true;
+  }
+  return false;
+}
+
+bool Selector_Algo::findNewVersion(const TopoDS_Shape& theContext, TopoDS_Shape& theResult) const
+{
+  if (theResult.IsNull())
+    return false;
+  if (!TNaming_Tool::HasLabel(myLab, theResult)) {
+    if (theResult.ShapeType() == TopAbs_COMPOUND) { // do it for all elements of compound
+      BRep_Builder aBuilder;
+      TopoDS_Compound aResultingCompound;
+      aBuilder.MakeCompound(aResultingCompound);
+      bool aWasChanged = false;
+      for (TopoDS_Iterator anIter(theResult); anIter.More(); anIter.Next()) {
+        TopoDS_Shape aSub = anIter.Value();
+        if (findNewVersion(theContext, aSub))
+          aWasChanged = true;
+        aBuilder.Add(aResultingCompound, aSub);
+      }
+      if (aWasChanged)
+        theResult = aResultingCompound;
+      return aWasChanged;
+    }
+  } else {
+    // check theResult is in theContext
+    if (isInContext(theContext, theResult))
+      return false;
+    // searching the next modifications of the result shape in document
+    TopTools_MapOfShape aResultShapes;
+    for(TNaming_NewShapeIterator aBaseIter(theResult, myLab); aBaseIter.More(); aBaseIter.Next())
+    {
+      TNaming_Evolution anEvolution = aBaseIter.NamedShape()->Evolution();
+      if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
+        TopoDS_Shape aNextModification = aBaseIter.Shape();
+        if (aNextModification.IsNull())
+          continue;
+        if (isInContext(theContext, aNextModification))
+          // don't add vertices generated from edges
+          if (aNextModification.ShapeType() <= theResult.ShapeType())
+            aResultShapes.Add(aNextModification);
+        else if (findNewVersion(theContext, aNextModification))
+          if (aNextModification.ShapeType() <= theResult.ShapeType())
+            aResultShapes.Add(aNextModification);
+      }
+    }
+    if (aResultShapes.IsEmpty())
+      return false;
+    if (aResultShapes.Size() == 1) {
+      theResult = TopTools_MapIteratorOfMapOfShape(aResultShapes).Value();
+    } else { // make a compound of all results
+      BRep_Builder aBuilder;
+      TopoDS_Compound aResultingCompound;
+      aBuilder.MakeCompound(aResultingCompound);
+      for(TopTools_MapIteratorOfMapOfShape anIter(aResultShapes); anIter.More(); anIter.Next())
+        aBuilder.Add(aResultingCompound, anIter.Value());
+      theResult = aResultingCompound;
+    }
+    return true;
+  }
+  return false;
 }