Salome HOME
Issue #2878: In Extrusion, can't select all in Vertex feature
[modules/shaper.git] / src / Selector / Selector_Selector.cpp
index 45880cab08e24decdc3397901b311dcc94450ea5..f10a0d082d6e28e87e2887e1d0fb13915c6a86e4 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_Selector.h>
 
-#include <TopoDS_Iterator.hxx>
-#include <TopExp_Explorer.hxx>
-#include <TNaming_Tool.hxx>
-#include <TNaming_NewShapeIterator.hxx>
-#include <TNaming_Iterator.hxx>
-#include <TopTools_MapOfShape.hxx>
+#include <Selector_NameGenerator.h>
+#include <Selector_Algo.h>
 
-#include <TDataStd_Integer.hxx>
-#include <TDataStd_ReferenceArray.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Builder.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TNaming_NamedShape.hxx>
 
-#include <list>
+Selector_Selector::Selector_Selector(TDF_Label theLab, TDF_Label theBaseDocLab) :
+  myLab(theLab), myBaseDocumentLab(theBaseDocLab), myAlgo(NULL)
+{}
 
-/// type of the selection, integerm keeps the Selector_Type value
-static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6");
-//  reference attribute that contains the reference to labels where the "from" or "base" shapes
-// of selection are located
-static const Standard_GUID kBASE_LIST("7c515b1a-9549-493d-9946-a4933a22f45f");
+Selector_Selector::~Selector_Selector()
+{
+  if (myAlgo)
+    delete myAlgo;
+}
 
-Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab)
+bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue,
+  const bool theGeometricalNaming)
 {
+  if (theValue.IsNull() || theContext.IsNull())
+    return false;
+
+  myAlgo = Selector_Algo::select(theContext, theValue, myLab, myBaseDocumentLab,
+    theGeometricalNaming, true, true);
+
+  return myAlgo != NULL;
 }
 
-TDF_Label Selector_Selector::label()
+bool Selector_Selector::store(const TopoDS_Shape theContext)
 {
-  return myLab;
+  myAlgo->store();
+  return myAlgo->solve(theContext); // to update the selection shape on the label
 }
 
-// adds to theResult all labels that contain initial shapes for theValue located in theFinal
-static void findBases(Handle(TNaming_NamedShape) theFinal, const TopoDS_Shape& theValue,
-  TDF_LabelList& theResult)
+bool Selector_Selector::restore(const TopoDS_Shape theContext)
 {
-  for(TNaming_Iterator aThisIter(theFinal); aThisIter.More(); aThisIter.Next()) {
-    if (aThisIter.NewShape().IsSame(theValue)) {
-      const TopoDS_Shape& anOldShape = aThisIter.OldShape();
-      // searching for all old shapes in this sequence of modification
-      TNaming_NewShapeIterator aNSIter(anOldShape, theFinal->Label());
-      for(; aNSIter.More(); aNSIter.Next()) {
-        TNaming_Evolution anEvolution = aNSIter.NamedShape()->Evolution();
-        if (anEvolution == TNaming_PRIMITIVE) { // found a good candidate, a base shape
-          // check that this is not in the results already
-          const TDF_Label aResult = aNSIter.NamedShape()->Label();
-          TDF_LabelList::Iterator aResIter(theResult);
-          for(; aResIter.More(); aResIter.Next()) {
-            if (aResIter.Value().IsEqual(aResult))
-              break;
-          }
-          if (!aResIter.More()) // not found, so add this new
-            theResult.Append(aResult);
-        } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
-          // continue recursively
-          findBases(aNSIter.NamedShape(), anOldShape, theResult);
-        }
-      }
-    }
+  myAlgo = Selector_Algo::restoreByLab(myLab, myBaseDocumentLab);
+  if (myAlgo) {
+    return myAlgo->solve(theContext); // to update the selection shape on the label
   }
+  return false;
 }
 
-bool Selector_Selector::Select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+TopoDS_Shape Selector_Selector::value()
 {
-  if (theValue.IsNull() || theContext.IsNull())
-    return false;
-  // 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)
-  if (!TNaming_Tool::HasLabel(myLab, theValue)) {
-    TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
-    if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
-        aSelectionType == TopAbs_SOLID) { // iterate all sub-shapes and select them on sublabels
-      std::list<Selector_Selector> aSubSelList;
-      for(TopoDS_Iterator aSubIter(theValue); aSubIter.More(); aSubIter.Next()) {
-        aSubSelList.push_back(Selector_Selector(myLab.FindChild(aSubSelList.size() + 1)));
-        if (!aSubSelList.back().Select(theContext, aSubIter.Value())) {
-          return false; // if some selector is failed, everything is failed
-        }
-      }
-      myType = SELTYPE_CONTAINER;
-      myShapeType = aSelectionType;
-      return true;
-    }
-
-    // try to find the shape of the higher level type in the context shape
-    while(aSelectionType != TopAbs_FACE) {
-      if (aSelectionType == TopAbs_VERTEX) aSelectionType = TopAbs_EDGE;
-      else if (aSelectionType == TopAbs_EDGE) aSelectionType = TopAbs_FACE;
-      TopTools_MapOfShape anIntersectors; // shapes of aSelectionType that contain theValue
-      for(TopExp_Explorer aSelExp(theContext, aSelectionType); aSelExp.More(); aSelExp.Next()) {
-        TopExp_Explorer aSubExp(aSelExp.Current(), theValue.ShapeType());
-        for(; aSubExp.More(); aSubExp.Next()) {
-          if (aSubExp.Current().IsSame(theValue)) {
-            anIntersectors.Add(aSelExp.Current());
-            break;
-          }
-        }
-      }
-      //TODO: check if intersectors produce several subs, try to remove one of the intersector
-
-      // name the intersectors
-
-    }
-  }
-  // searching for the base shapes of the value
-  Handle(TNaming_NamedShape) aPrimitiveNS;
-  NCollection_List<Handle(TNaming_NamedShape)> aModifList;
-  for(TNaming_NewShapeIterator aNewShapes(theValue, myLab); aNewShapes.More(); aNewShapes.Next())
-  {
-    TNaming_Evolution anEvolution = aNewShapes.NamedShape()->Evolution();
-    if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as primitive => PRIMITIVE
-      aPrimitiveNS = aNewShapes.NamedShape();
-      break;
-    } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
-      aModifList.Append(aNewShapes.NamedShape());
-    }
-  }
+  Handle(TNaming_NamedShape) aNS;
+  if (myLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
+    return aNS->Get();
+  return TopoDS_Shape(); // empty, error shape
+}
 
-  if (!aPrimitiveNS.IsNull()) {
-    myType = SELTYPE_PRIMITIVE;
-    myFinal = aPrimitiveNS->Label();
-    return true;
-  }
+std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
+  return myAlgo->name(theNameGenerator);
+}
 
-  if (aModifList.Extent() > 1) { // searching for the best modification result: by context
-    Handle(TNaming_NamedShape) aCandidate;
-    NCollection_List<Handle(TNaming_NamedShape)>::Iterator aModIter(aModifList);
-    for(; !aModifList.IsEmpty() && aModIter.More(); 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()) {
-          if (theContext.IsSame(anIter.NewShape())) { // found the best modification
-            aModifList.Clear();
-            break;
-          }
-        }
-      }
-    }
-    // take the best candidate, or the last in the iteration
-    aModifList.Clear();
-    aModifList.Append(aCandidate);
+TDF_Label Selector_Selector::restoreByName(
+  std::string theName, const TopAbs_ShapeEnum theShapeType,
+  Selector_NameGenerator* theNameGenerator, const bool theGeometricalNaming)
+{
+  TDF_Label aResult;
+  myAlgo = Selector_Algo::restoreByName(myLab, myBaseDocumentLab, theName, theShapeType,
+    theGeometricalNaming, theNameGenerator, aResult);
+  if (myAlgo) {
+    return aResult;
   }
+  return TDF_Label();
+}
 
-  if (!aModifList.IsEmpty()) {
-    // searching for all the base shapes of this modification
-    findBases(aModifList.First(), theValue, myBases);
-    myFinal = aModifList.First()->Label();
-    myType = SELTYPE_MODIFICATION;
-    return !myBases.IsEmpty();
+void Selector_Selector::combineGeometrical(const TopoDS_Shape theContext)
+{
+  TopoDS_Shape aValue = value();
+  if (aValue.IsNull() || aValue.ShapeType() == TopAbs_COMPOUND)
+    return;
+
+  Selector_Algo* aNewAlgo = Selector_Algo::relesectWithAllGeometry(myAlgo, theContext);
+  if (aNewAlgo) {
+    aNewAlgo->store();
+    aNewAlgo->solve(theContext);
+    delete myAlgo;
+    myAlgo = aNewAlgo;
   }
-
-  // not found a good result
-  return false;
 }
 
-void Selector_Selector::Store()
+bool Selector_Selector::solve(const TopoDS_Shape theContext)
 {
-  TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType);
-  switch(myType) {
-  case SELTYPE_CONTAINER: {
-    /// TODO
-    break;
-  }
-  case SELTYPE_INTERSECT: {
-    /// TODO
-    break;
-  }
-  case SELTYPE_PRIMITIVE: {
-    Handle(TDataStd_ReferenceArray) anArray = TDataStd_ReferenceArray::Set(myLab, 0, 0);
-    anArray->SetValue(0, myBases.First());
-    break;
-  }
-  case SELTYPE_MODIFICATION: {
-    Handle(TDataStd_ReferenceArray) anArray =
-      TDataStd_ReferenceArray::Set(myLab, 0, myBases.Extent() - 1);
-    TDF_LabelList::Iterator aBIter(myBases);
-    for(int anIndex = 0; aBIter.More(); aBIter.Next(), anIndex++) {
-      anArray->SetValue(anIndex, aBIter.Value());
-    }
-    break;
-  }
-  default: { // unknown case
-    break;
-  }
-  }
+  return myAlgo->solve(theContext);
 }