]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Simple implementation of all kinds of names except FILTER
authormpv <mpv@opencascade.com>
Tue, 9 Oct 2018 08:51:59 +0000 (11:51 +0300)
committermpv <mpv@opencascade.com>
Fri, 26 Oct 2018 17:06:01 +0000 (20:06 +0300)
src/Model/CMakeLists.txt
src/Model/Model_AttributeSelection.cpp
src/Selector/Selector_Selector.cpp
src/Selector/Selector_Selector.h

index 33ec73c00da0d180a8b3d58b10c09f869ab09ae8..27a8c6eb5aedaab44eb0d5804ba9b4668f846d2b 100644 (file)
@@ -99,6 +99,7 @@ SET(PROJECT_LIBRARIES
     ModelAPI
     Events
     Config
+    Selector
     GeomData
     GeomAPI
     GeomAlgoAPI
@@ -109,6 +110,7 @@ SET(PROJECT_INCLUDES
   ../ModelAPI
   ../Events
   ../Config
+  ../Selector
   ../GeomData
   ../GeomDataAPI
   ../GeomAlgoAPI
index 7b1259db39ecaa7c013a37deb329fdf113d7fa38..c5f95948997aa44fdd36335fe361c2a588246b56 100644 (file)
@@ -43,6 +43,7 @@
 #include <GeomAPI_Vertex.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
 #include <GeomAlgoAPI_NExplode.h>
+#include <Selector_Selector.h>
 
 #include <TNaming_Selector.hxx>
 #include <TNaming_NamedShape.hxx>
@@ -686,21 +687,30 @@ bool Model_AttributeSelection::update()
       GeomShapePtr aValue = aNExplode.shape(aWeakId->Get());
       return setInvalidIfFalse(aSelLab, aValue.get() != NULL);
     }
-    // body: just a named shape, use selection mechanism from OCCT
-    TNaming_Selector aSelector(aSelLab);
+    // body: just a named shape, use topological selection mechanism
+    bool aResult = false;
     TopoDS_Shape anOldShape;
-    if (!aSelector.NamedShape().IsNull()) {
-      anOldShape = aSelector.NamedShape()->Get();
+    Handle(TNaming_NamedShape) aNS;
+    if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
+      anOldShape = aNS->Get();
+
+    Selector_Selector aSelector(aSelLab);
+    if (!aSelector.restore()) { // it is stored in old OCCT format, use TNaming_Selector
+      TNaming_Selector aSelector(aSelLab);
+      if (!aSelector.NamedShape().IsNull()) {
+        anOldShape = aSelector.NamedShape()->Get();
+      }
+      aResult = aSelector.Solve(scope()) == Standard_True;
+    } else {
+      aResult = aSelector.solve();
     }
-    bool aResult = aSelector.Solve(scope()) == Standard_True;
-    // must be before sending of updated attribute (1556)
     aResult = setInvalidIfFalse(aSelLab, aResult);
+
     TopoDS_Shape aNewShape;
-    if (!aSelector.NamedShape().IsNull()) {
-      aNewShape = aSelector.NamedShape()->Get();
-    }
-    if (anOldShape.IsNull() || aNewShape.IsNull() ||
-        !anOldShape.IsEqual(aSelector.NamedShape()->Get())) {
+    if (aSelLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
+      aNewShape = aNS->Get();
+
+    if (anOldShape.IsNull() || aNewShape.IsNull() || !anOldShape.IsEqual(aNewShape)) {
       // shape type shoud not not changed: if shape becomes compound of such shapes, then split
       if (myParent && !anOldShape.IsNull() && !aNewShape.IsNull() &&
           anOldShape.ShapeType() != aNewShape.ShapeType() &&
@@ -738,7 +748,6 @@ void Model_AttributeSelection::selectBody(
   const ResultPtr& theContext, const std::shared_ptr<GeomAPI_Shape>& theSubShape)
 {
   // perform the selection
-  TNaming_Selector aSel(selectionLabel());
   TopoDS_Shape aContext;
 
   ResultBodyPtr aBody = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theContext);//myRef.value()
@@ -828,8 +837,12 @@ void Model_AttributeSelection::selectBody(
         aFeatureOwner->removeResults(0, false, false);
     }
     bool aSelectorOk = true;
+    //TNaming_Selector aSel(aSelLab);
+    Selector_Selector aSel(aSelLab);
     try {
-      aSel.Select(aNewSub, aNewContext);
+      //aSel.Select(aNewSub, aNewContext);
+      aSelectorOk = aSel.select(aNewContext, aNewSub);
+      aSel.store();
     } catch(...) {
       aSelectorOk = false;
     }
index 45880cab08e24decdc3397901b311dcc94450ea5..61de2fd446ed6cd66e8e3a2d459602ec4866e7e7 100644 (file)
 
 #include <Selector_Selector.h>
 
+#include <TDF_ChildIDIterator.hxx>
 #include <TopoDS_Iterator.hxx>
+#include <TopoDS_Builder.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TNaming_Tool.hxx>
 #include <TNaming_NewShapeIterator.hxx>
+#include <TNaming_OldShapeIterator.hxx>
+#include <TNaming_SameShapeIterator.hxx>
 #include <TNaming_Iterator.hxx>
+#include <TNaming_Builder.hxx>
 #include <TopTools_MapOfShape.hxx>
 
 #include <TDataStd_Integer.hxx>
 
 /// type of the selection, integerm keeps the Selector_Type value
 static const Standard_GUID kSEL_TYPE("db174d59-c2e3-4a90-955e-55544df090d6");
+/// type of the shape, stored in case it is intersection or container
+static const Standard_GUID kSHAPE_TYPE("864b3267-cb9d-4107-bf58-c3ce1775b171");
 //  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");
+static const Standard_GUID kBASE_ARRAY("7c515b1a-9549-493d-9946-a4933a22f45f");
 
 Selector_Selector::Selector_Selector(TDF_Label theLab) : myLab(theLab)
 {
@@ -55,12 +62,12 @@ static void findBases(Handle(TNaming_NamedShape) theFinal, const TopoDS_Shape& t
     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();
+      TNaming_OldShapeIterator anOldIter(anOldShape, theFinal->Label());
+      for(; anOldIter.More(); anOldIter.Next()) {
+        TNaming_Evolution anEvolution = anOldIter.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();
+          const TDF_Label aResult = anOldIter.NamedShape()->Label();
           TDF_LabelList::Iterator aResIter(theResult);
           for(; aResIter.More(); aResIter.Next()) {
             if (aResIter.Value().IsEqual(aResult))
@@ -70,14 +77,14 @@ static void findBases(Handle(TNaming_NamedShape) theFinal, const TopoDS_Shape& t
             theResult.Append(aResult);
         } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
           // continue recursively
-          findBases(aNSIter.NamedShape(), anOldShape, theResult);
+          findBases(anOldIter.NamedShape(), anOldShape, theResult);
         }
       }
     }
   }
 }
 
-bool Selector_Selector::Select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
 {
   if (theValue.IsNull() || theContext.IsNull())
     return false;
@@ -85,17 +92,16 @@ bool Selector_Selector::Select(const TopoDS_Shape theContext, const TopoDS_Shape
   // higher level shapes (like a box vertex by faces that form this vertex)
   if (!TNaming_Tool::HasLabel(myLab, theValue)) {
     TopAbs_ShapeEnum aSelectionType = theValue.ShapeType();
+    myShapeType = aSelectionType;
     if (aSelectionType == TopAbs_COMPOUND || aSelectionType == TopAbs_COMPSOLID ||
-        aSelectionType == TopAbs_SOLID) { // iterate all sub-shapes and select them on sublabels
-      std::list<Selector_Selector> aSubSelList;
+        aSelectionType == TopAbs_SHELL || aSelectionType == TopAbs_WIRE)
+    { // iterate all sub-shapes and select them on sublabels
       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())) {
+        if (!selectBySubSelector(theContext, aSubIter.Value())) {
           return false; // if some selector is failed, everything is failed
         }
       }
       myType = SELTYPE_CONTAINER;
-      myShapeType = aSelectionType;
       return true;
     }
 
@@ -115,21 +121,45 @@ bool Selector_Selector::Select(const TopoDS_Shape theContext, const TopoDS_Shape
       }
       //TODO: check if intersectors produce several subs, try to remove one of the intersector
 
-      // name the intersectors
+      //TODO: check that solution is only one
 
+      // name the intersectors
+      std::list<Selector_Selector> aSubSelList;
+      TopTools_MapOfShape::Iterator anInt(anIntersectors);
+      for (; anInt.More(); anInt.Next()) {
+        if (!selectBySubSelector(theContext, anInt.Value())) {
+          break; // if some selector is failed, stop and search another solution
+        }
+      }
+      if (!anInt.More()) { // all intersectors were correctly named
+        myType = SELTYPE_INTERSECT;
+        return true;
+      }
     }
+
+    // TODO: searching by neighbours
+    return false;
   }
   // 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())
+  for(TNaming_SameShapeIterator aShapes(theValue, myLab); aShapes.More(); aShapes.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 (aShapes.Label().FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+      TNaming_Evolution anEvolution = aNS->Evolution();
+      if (anEvolution == TNaming_PRIMITIVE) { // the value shape is declared as PRIMITIVE
+        aPrimitiveNS = aNS;
+        break;
+      } else if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
+        // check this is a new shape
+        TNaming_Iterator aNSIter(aNS);
+        for(; aNSIter.More(); aNSIter.Next())
+          if (aNSIter.NewShape().IsSame(theValue))
+            break;
+        if (aNSIter.More()) // new was found
+          aModifList.Append(aNS);
+      }
     }
   }
 
@@ -172,30 +202,35 @@ bool Selector_Selector::Select(const TopoDS_Shape theContext, const TopoDS_Shape
   return false;
 }
 
-void Selector_Selector::Store()
+void Selector_Selector::store()
 {
+  myLab.ForgetAllAttributes(true); // remove old naming data
   TDataStd_Integer::Set(myLab, kSEL_TYPE, (int)myType);
   switch(myType) {
-  case SELTYPE_CONTAINER: {
-    /// TODO
-    break;
-  }
+  case SELTYPE_CONTAINER:
   case SELTYPE_INTERSECT: {
-    /// TODO
+    TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
+    // store also all sub-selectors
+    std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
+    for(; aSubSel != mySubSelList.end(); aSubSel++) {
+      aSubSel->store();
+    }
     break;
   }
   case SELTYPE_PRIMITIVE: {
-    Handle(TDataStd_ReferenceArray) anArray = TDataStd_ReferenceArray::Set(myLab, 0, 0);
-    anArray->SetValue(0, myBases.First());
+    Handle(TDataStd_ReferenceArray) anArray =
+      TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, 0);
+    anArray->SetValue(0, myFinal);
     break;
   }
   case SELTYPE_MODIFICATION: {
     Handle(TDataStd_ReferenceArray) anArray =
-      TDataStd_ReferenceArray::Set(myLab, 0, myBases.Extent() - 1);
+      TDataStd_ReferenceArray::Set(myLab, kBASE_ARRAY, 0, myBases.Extent());
     TDF_LabelList::Iterator aBIter(myBases);
     for(int anIndex = 0; aBIter.More(); aBIter.Next(), anIndex++) {
       anArray->SetValue(anIndex, aBIter.Value());
     }
+    anArray->SetValue(myBases.Extent(), myFinal); // final is in the end of array
     break;
   }
   default: { // unknown case
@@ -203,3 +238,200 @@ void Selector_Selector::Store()
   }
   }
 }
+
+bool Selector_Selector::restore()
+{
+  Handle(TDataStd_Integer) aTypeAttr;
+  if (!myLab.FindAttribute(kSEL_TYPE, aTypeAttr))
+    return false;
+  myType = Selector_Type(aTypeAttr->Get());
+  switch(myType) {
+  case SELTYPE_CONTAINER:
+  case SELTYPE_INTERSECT: {
+    Handle(TDataStd_Integer) aShapeTypeAttr;
+    if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
+      return false;
+    myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
+    // restore sub-selectors
+    bool aSubResult = true;
+    mySubSelList.clear();
+    for(TDF_ChildIDIterator aSub(myLab, kSEL_TYPE, false); aSub.More(); aSub.Next()) {
+      mySubSelList.push_back(Selector_Selector(aSub.Value()->Label()));
+      if (!mySubSelList.back().restore())
+        aSubResult = false;
+    }
+    return aSubResult;
+  }
+  case SELTYPE_PRIMITIVE: {
+    Handle(TDataStd_ReferenceArray) anArray;
+    if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
+      myFinal = anArray->Value(0);
+      return true;
+    }
+    return false;
+  }
+  case SELTYPE_MODIFICATION: {
+    Handle(TDataStd_ReferenceArray) anArray;
+    if (myLab.FindAttribute(kBASE_ARRAY, anArray)) {
+      int anUpper = anArray->Upper();
+      for(int anIndex = 0; anIndex < anUpper; anIndex++) {
+        myBases.Append(anArray->Value(anIndex));
+      }
+      myFinal = anArray->Value(anUpper);
+      return true;
+    }
+    return false;
+  }
+  default: { // unknown case
+  }
+  }
+  return false;
+}
+
+/// Returns in theResults all shapes with history started in theBase and ended in theFinal
+static void findFinals(const TopoDS_Shape& theBase, const TDF_Label& theFinal,
+  TopTools_MapOfShape& theResults)
+{
+  for(TNaming_NewShapeIterator aBaseIter(theBase, theFinal); aBaseIter.More(); aBaseIter.Next()) {
+    TNaming_Evolution anEvolution = aBaseIter.NamedShape()->Evolution();
+    if (anEvolution == TNaming_GENERATED || anEvolution == TNaming_MODIFY) {
+      if (aBaseIter.NamedShape()->Label().IsEqual(theFinal)) {
+        theResults.Add(aBaseIter.Shape());
+      } else {
+        findFinals(aBaseIter.Shape(), theFinal, theResults);
+      }
+    }
+  }
+
+}
+
+bool Selector_Selector::solve()
+{
+  TopoDS_Shape aResult; // null if invalid
+  switch(myType) {
+  case SELTYPE_CONTAINER: {
+    TopoDS_Builder aBuilder;
+    switch(myShapeType) {
+    case TopAbs_COMPOUND: {
+      TopoDS_Compound aComp;
+      aBuilder.MakeCompound(aComp);
+      aResult = aComp;
+      break;
+      }
+    case TopAbs_COMPSOLID: {
+      TopoDS_CompSolid aComp;
+      aBuilder.MakeCompSolid(aComp);
+      aResult = aComp;
+      break;
+    }
+    case TopAbs_SHELL: {
+      TopoDS_Shell aShell;
+      aBuilder.MakeShell(aShell);
+      aResult = aShell;
+      break;
+    }
+    case TopAbs_WIRE: {
+      TopoDS_Wire aWire;
+      aBuilder.MakeWire(aWire);
+      aResult = aWire;
+      break;
+    }
+    }
+    std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
+    for(; aSubSel != mySubSelList.end(); aSubSel++) {
+      if (!aSubSel->solve()) {
+        return false;
+      }
+      aBuilder.Add(aResult, aSubSel->value());
+    }
+    break;
+  }
+  case SELTYPE_INTERSECT: {
+    TopoDS_ListOfShape aCommon; // common sub shapes in each sub-selector (a result)
+    std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
+    for(; aSubSel != mySubSelList.end(); aSubSel++) {
+      if (!aSubSel->solve()) {
+        return false;
+      }
+      TopoDS_Shape anArg = aSubSel->value();
+      TopTools_MapOfShape aCurrentMap;
+      for(TopExp_Explorer anExp(anArg, myShapeType); anExp.More(); anExp.Next()) {
+        if (aCurrentMap.Add(anExp.Current()) && aSubSel == mySubSelList.begin())
+          aCommon.Append(anExp.Current());
+      }
+      if (aSubSel != mySubSelList.begin()) { // remove from common shapes not in aCurrentMap
+        for(TopoDS_ListOfShape::Iterator aComIter(aCommon); aComIter.More(); ) {
+          if (aCurrentMap.Contains(aComIter.Value()))
+            aComIter.Next();
+          else
+            aCommon.Remove(aComIter);
+        }
+      }
+    }
+    if (aCommon.Extent() != 1)
+      return false;
+    aResult = aCommon.First();
+    break;
+  }
+  case SELTYPE_PRIMITIVE: {
+    Handle(TNaming_NamedShape) aNS;
+    if (myFinal.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
+      aResult = aNS->Get();
+    }
+  }
+  case SELTYPE_MODIFICATION: {
+    TopoDS_ListOfShape aFinalsCommon; // final shapes presented in all results from bases
+    TDF_LabelList::Iterator aBase(myBases);
+    for(; aBase.More(); aBase.Value()) {
+      TopTools_MapOfShape aFinals;
+      for(TNaming_Iterator aBaseShape(aBase.Value()); aBaseShape.More(); aBaseShape.Next())
+        findFinals(aBaseShape.NewShape(), myFinal, aFinals);
+      if (!aFinals.IsEmpty()) {
+        if (aFinalsCommon.IsEmpty()) { // just copy all to common
+          for(TopTools_MapOfShape::Iterator aFinal(aFinals); aFinal.More(); aFinal.Next()) {
+            aFinalsCommon.Append(aFinal.Key());
+          }
+        } else { // keep only shapes presented in both lists
+          TopoDS_ListOfShape::Iterator aCommon(aFinalsCommon);
+          for(; aCommon.More(); aCommon.Next()) {
+            if (aFinals.Contains(aCommon.Value())) {
+              aCommon.Next();
+            } else { // common is not found, remove it
+              aFinalsCommon.Remove(aCommon);
+            }
+          }
+        }
+      }
+    }
+    if (aFinalsCommon.Extent() == 1) // only in this case result is valid: found only one shape
+      aResult = aFinalsCommon.First();
+  }
+  default: { // unknown case
+  }
+  }
+
+  TNaming_Builder aBuilder(myLab);
+  if (!aResult.IsNull()) {
+    aBuilder.Select(aResult, aResult);
+    return true;
+  }
+  return false; // builder just erases the named shape in case of error
+}
+
+TopoDS_Shape Selector_Selector::value()
+{
+  Handle(TNaming_NamedShape) aNS;
+  if (myLab.FindAttribute(TNaming_NamedShape::GetID(), aNS))
+    return aNS->Get();
+  return TopoDS_Shape(); // empty, error shape
+}
+
+bool Selector_Selector::selectBySubSelector(const TopoDS_Shape theContext, const TopoDS_Shape theValue)
+{
+  mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
+  if (!mySubSelList.back().select(theContext, theValue)) {
+    mySubSelList.clear(); // if one of the selector is failed, all become invalid
+    return false;
+  }
+  return true;
+}
index dc4866018342d31e3aa11335e6608673b0ed1447..7a9cdeda518c0b47c2aab295610fe0b4b4898f38 100644 (file)
@@ -27,6 +27,8 @@
 #include <TDF_LabelList.hxx>
 #include <TopoDS_Shape.hxx>
 
+#include <list>
+
 /**\class Selector_Selector
  * \ingroup DataModel
  * \brief Main object for selection of the sub-shapes in the parametrically updated
@@ -46,6 +48,7 @@ class Selector_Selector
 
   Selector_Type myType; ///< Type of this selector.
   TopAbs_ShapeEnum myShapeType; ///< type of this shape: container or result of intersection
+  std::list<Selector_Selector> mySubSelList; // list of sub-selectors if needed
   TDF_Label myFinal; ///< final label of the primitive or generation, where the value is
   TDF_LabelList myBases; ///< initial labels that contain shapes that produce the modification
 
@@ -53,19 +56,32 @@ class Selector_Selector
 
  public:
   /// Initializes selector on the label
-  Selector_Selector(TDF_Label theLab);
+   SELECTOR_EXPORT Selector_Selector(TDF_Label theLab);
   /// Returns label of this selector
-  TDF_Label label();
+   SELECTOR_EXPORT TDF_Label label();
 
   /// Initializes the selector structure on the label.
   /// Stores the name data to restore after modification.
-  bool Select(const TopoDS_Shape theContext, const TopoDS_Shape theValue);
+   SELECTOR_EXPORT bool select(const TopoDS_Shape theContext, const TopoDS_Shape theValue);
 
   /// Stores the name to the label and sub-labels tree
-  void Store();
+   SELECTOR_EXPORT void store();
 
   /// Restores the selected shape by the topological naming kept in the data structure
-  //TopoDS_Shape Restore();
+  /// Returns true if it can restore structure correctly
+   SELECTOR_EXPORT bool restore();
+
+  /// Updates the current shape by the stored topological name
+   SELECTOR_EXPORT bool solve();
+
+  /// Returns the current sub-shape value (null if can not resolve)
+   SELECTOR_EXPORT TopoDS_Shape value();
+
+private:
+
+  /// Create and keep in the list the sub-sulector that select the given value.
+  /// Returns true if selection is correct.
+  bool selectBySubSelector(const TopoDS_Shape theContext, const TopoDS_Shape theValue);
 };
 
 #endif