Salome HOME
Pure weak naming implementation in Selector
authormpv <mpv@opencascade.com>
Tue, 23 Oct 2018 08:10:49 +0000 (11:10 +0300)
committermpv <mpv@opencascade.com>
Mon, 19 Nov 2018 08:45:52 +0000 (11:45 +0300)
src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp
src/Model/Model_Objects.cpp
src/Selector/Selector_NExplode.cpp
src/Selector/Selector_NExplode.h
src/Selector/Selector_Selector.cpp
src/Selector/Selector_Selector.h

index b9399a815a44a295cce514a29d82676897af4344..5df959f46cf8d91e17607432bee00214179a13bf 100644 (file)
@@ -317,123 +317,6 @@ void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theRes
       aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
     theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::EDGE);
   }
-  // issue #2197: make naming of edges generated from vertices
-  if (aShapeTypeToExplode == GeomAPI_Shape::EDGE) {
-    GeomAPI_DataMapOfShapeShape aFacesFromFromEdges;
-    GeomAPI_ShapeExplorer anEdgeExp(theBaseShape, GeomAPI_Shape::EDGE);
-    for(; anEdgeExp.more(); anEdgeExp.next()) {
-      ListOfShape aGenerated;
-      theMakeShape->generated(anEdgeExp.current(), aGenerated);
-      ListOfShape::iterator aGenIter = aGenerated.begin();
-      for(; aGenIter != aGenerated.end(); aGenIter++) {
-        GeomShapePtr aGen = *aGenIter;
-        if (aGen.get() && !aGen->isNull()) {
-          if ((*aGenIter)->shapeType() == GeomAPI_Shape::FACE) { // normal case
-            aFacesFromFromEdges.bind(aGen, anEdgeExp.current());
-          }
-        }
-      }
-    }
-
-    // closed revolution of 1-3 faces can not distinguish lateral and base edges
-    if (aFacesFromFromEdges.size() <= 3) {
-      bool isClosed = false; // lateral edges are closed (in full revolution)
-      GeomAPI_DataMapOfShapeShape anEdgesFromVertices;
-      GeomAPI_ShapeExplorer aVertExp(theBaseShape, GeomAPI_Shape::VERTEX);
-      for(; aVertExp.more(); aVertExp.next()) {
-        ListOfShape aGenerated;
-        theMakeShape->generated(aVertExp.current(), aGenerated);
-        ListOfShape::iterator aGenIter = aGenerated.begin();
-        for(; aGenIter != aGenerated.end(); aGenIter++) {
-          std::shared_ptr<GeomAPI_Shape> aGenerated = *aGenIter;
-          if (anEdgesFromVertices.isBound(aGenerated)) // already here
-            continue;
-          std::ostringstream aStream;
-          aStream << "Lateral_" << aLateralIndex++;
-          theResultBody->generated(aGenerated, aStream.str());
-
-          anEdgesFromVertices.bind(aGenerated, aVertExp.current());
-          std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aGenerated));
-          isClosed = isClosed || anEdge->isClosed();
-        }
-      }
-      if (isClosed) {
-        GeomAPI_ShapeExplorer anEdgesExp(theMakeShape->shape(), GeomAPI_Shape::EDGE);
-        for(; anEdgesExp.more(); anEdgesExp.next()) {
-          if (!anEdgesFromVertices.isBound(anEdgesExp.current())) {
-            // found a base edge
-            std::ostringstream aStream;
-            aStream << "Base_Edge_" << aBaseEdgeIndex++;
-            theResultBody->generated(anEdgesExp.current(), aStream.str());
-            // only one orientation is needed
-            anEdgesFromVertices.bind(anEdgesExp.current(), anEdgesExp.current());
-          }
-        }
-      } else if (aFacesFromFromEdges.size() == 1) { // 2233: sphere created by the revolution:
-        // vertices at degenerated edges will have the same name
-        GeomAPI_DataMapOfShapeShape aVertices;
-        GeomAPI_ShapeExplorer aVertExp(theMakeShape->shape(), GeomAPI_Shape::VERTEX);
-        for(int anIndex = 1; aVertExp.more(); aVertExp.next()) {
-          if (!aVertices.isBound(aVertExp.current())) {
-            // found a base edge
-            std::ostringstream aStream;
-            aStream << "Vertex_" << aVertexIndex++;
-            theResultBody->generated(aVertExp.current(), aStream.str());
-            // only one orientation is needed
-            aVertices.bind(aVertExp.current(), aVertExp.current());
-          }
-        }
-      }
-    } else { // issue #2197, test case 4 : edges that produce fully-revolved face,
-      // but contain only 2 edges (on apex of revolution)
-      GeomAPI_ShapeExplorer anEdgeExp(theBaseShape, GeomAPI_Shape::EDGE);
-      for(; anEdgeExp.more(); anEdgeExp.next()) {
-        ListOfShape aGenerated;
-        theMakeShape->generated(anEdgeExp.current(), aGenerated);
-        ListOfShape::iterator aGenIter = aGenerated.begin();
-        for(; aGenIter != aGenerated.end(); aGenIter++) {
-          GeomShapePtr aGen = (*aGenIter);
-          if (aGen.get() && !aGen->isNull()) {
-            GeomAPI_ShapeExplorer aFaceEdgeExp(aGen, GeomAPI_Shape::EDGE);
-            int aNumEdges = 0;
-            int aNumClosed = 0;
-            GeomShapePtr aNotClosedEdge;
-            GeomEdgePtr aDegenerateEdge;
-            GeomAPI_DataMapOfShapeShape alreadyIterated;
-            for(; aFaceEdgeExp.more(); aFaceEdgeExp.next()) {
-              std::shared_ptr<GeomAPI_Edge> anEdge(new GeomAPI_Edge(aFaceEdgeExp.current()));
-              if (anEdge->isDegenerated()) {
-                aDegenerateEdge = anEdge;
-                continue;
-              }
-              if (alreadyIterated.isBound(anEdge))
-                continue;
-              alreadyIterated.bind(anEdge, anEdge);
-              aNumEdges++;
-              if (anEdge->isClosed()) {
-                aNumClosed++;
-              } else {
-                aNotClosedEdge = anEdge;
-              }
-            }
-            if (aNumEdges == 2 && aNumClosed == 1) {
-              std::ostringstream aStream;
-              aStream << "Base_Edge_" << aBaseEdgeIndex++;
-              theResultBody->generated(aNotClosedEdge, aStream.str());
-              if (aDegenerateEdge.get()) { // export vertex of the degenerated edge (apex) #2520
-                GeomAPI_ShapeExplorer anEdgeExp(aDegenerateEdge, GeomAPI_Shape::VERTEX);
-                if (anEdgeExp.more()) {
-                  std::ostringstream aStream;
-                  aStream << "Base_Vertex_" << aBaseVertexIndex++;
-                  theResultBody->generated(anEdgeExp.current(), aStream.str());
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-  }
 
   std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep =
     std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
index 9d89e5c64c37a4d9499513f7b80eb0f52840d0b6..e6116ebbe764594b5f317d0eb4a5438c523b144b 100644 (file)
@@ -309,7 +309,7 @@ void Model_Objects::removeFeature(FeaturePtr theFeature)
     for(; aRefIter != aRefs.end(); aRefIter++) {
       std::shared_ptr<ModelAPI_CompositeFeature> aComposite =
         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
-      if (aComposite.get() && aComposite->isSub(theFeature)) {
+      if (aComposite.get() && aComposite->data()->isValid() && aComposite->isSub(theFeature)) {
         aComposite->removeFeature(theFeature);
       }
     }
index 018f6b4388d4531f53057e9dad9bb87cf505d861..98b3dd42e517373f9e52a1778686ea104d917ddc 100644 (file)
@@ -152,6 +152,26 @@ Selector_NExplode::Selector_NExplode(const TopoDS_ListOfShape& theShapes)
   }
 }
 
+Selector_NExplode::Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType)
+{
+  std::vector<TopoDS_Shape> aShapesVec;
+  TopTools_MapOfShape anAdded; // to avoid same shapes duplication
+  for(TopExp_Explorer anExp(theShape, theType); anExp.More(); anExp.Next()) {
+    if (anAdded.Add(anExp.Current()))
+     aShapesVec.push_back(anExp.Current());
+  }
+
+  CompareShapes::DataMapOfShapeDouble aCash;
+  CompareShapes shComp(&aCash);
+  std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp);
+
+  std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin();
+  for (; anIter != aShapesVec.end(); ++anIter) {
+    mySorted.Append(*anIter);
+  }
+}
+
+
 int Selector_NExplode::index(const TopoDS_Shape& theSubShape)
 {
   TopoDS_ListOfShape::Iterator anIter(mySorted);
index 4e020c1a9fc9e1f4e06decae426309771d9d8f48..dc4d0064bd6d0f3b514f7ef01b284ffd54518ea4 100644 (file)
 class Selector_NExplode
 {
  public:
-   /// \brief Initializes the sorted list of shapes by the context shape and type of sub-shapes.
+   /// \brief Initializes the sorted list of shapes by the shapes list.
    SELECTOR_EXPORT Selector_NExplode(const TopoDS_ListOfShape& theShapes);
+   /// \brief Initializes the sorted list of shapes by the context shape and type of sub-shapes.
+   SELECTOR_EXPORT Selector_NExplode(const TopoDS_Shape& theShape, const TopAbs_ShapeEnum theType);
 
    /// Returns an index (started from one) of sub-shape in the sorted list. Returns 0 if not found.
    SELECTOR_EXPORT int index(const TopoDS_Shape& theSubShape);
index 54c8aca55a28d04a582d2d0837c04b20ff12fab6..4627c6b69410f288079675d825bb81bcc430b28a 100644 (file)
@@ -283,6 +283,8 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape
 
     // try to find the shape of the higher level type in the context shape
     bool aFacesTried = false; // for identification of vertices, faces are tried, then edges
+    TopoDS_ListOfShape aLastCommon; // to store the commons not good, but may be used for weak
+    TopTools_MapOfShape aLastIntersectors;
     while(aSelectionType != TopAbs_FACE || !aFacesTried) {
       if (aSelectionType == TopAbs_FACE) {
         if (theValue.ShapeType() != TopAbs_VERTEX)
@@ -308,7 +310,7 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape
       commonShapes(anIntList, theValue.ShapeType(), aCommon);
       if (aCommon.Extent() == 1 && aCommon.First().IsSame(theValue)) {
         // name the intersectors
-        std::list<Selector_Selector> aSubSelList;
+        mySubSelList.clear();
         TopTools_MapOfShape::Iterator anInt(anIntersectors);
         for (; anInt.More(); anInt.Next()) {
           if (!selectBySubSelector(theContext, anInt.Value())) {
@@ -318,7 +320,10 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape
         if (!anInt.More()) { // all intersectors were correctly named
           myType = SELTYPE_INTERSECT;
           return true;
-        }
+          }
+      } else if (aCommon.Extent() > 1 && aLastCommon.IsEmpty())  {
+        aLastCommon = aCommon;
+        aLastIntersectors = anIntersectors;
       }
     }
 
@@ -356,6 +361,36 @@ bool Selector_Selector::select(const TopoDS_Shape theContext, const TopoDS_Shape
         return true;
       }
     }
+
+    // weak naming to distinguish commons coming from intersection
+    if (aLastCommon.Extent() > 1) {
+      Selector_NExplode aNexp(aLastCommon);
+      myWeakIndex = aNexp.index(theValue);
+      if (myWeakIndex != -1) {
+        // name the intersectors
+        mySubSelList.clear();
+        TopTools_MapOfShape::Iterator anInt(aLastIntersectors);
+        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;
+        }
+      }
+    }
+
+    // pure weak naming
+    myType = SELTYPE_WEAK_NAMING;
+    Selector_NExplode aNexp(theContext, theValue.ShapeType());
+    myWeakIndex = aNexp.index(theValue);
+    if (myWeakIndex != -1) {
+      myShapeType = theValue.ShapeType();
+      return true;
+    }
+
     return false;
   }
   // searching for the base shapes of the value
@@ -496,6 +531,9 @@ void Selector_Selector::store()
     for(; aSubSel != mySubSelList.end(); aSubSel++) {
       aSubSel->store();
     }
+    if (myWeakIndex != -1) {
+      TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
+    }
     break;
   }
   case SELTYPE_PRIMITIVE: {
@@ -531,6 +569,12 @@ void Selector_Selector::store()
     for(; aSubSel != mySubSelList.end(); aSubSel++) {
       aSubSel->store();
     }
+    break;
+  }
+  case SELTYPE_WEAK_NAMING: {
+    TDataStd_Integer::Set(myLab, kWEAK_INDEX, myWeakIndex);
+    TDataStd_Integer::Set(myLab, kSHAPE_TYPE, (int)myShapeType);
+    break;
   }
   default: { // unknown case
     break;
@@ -559,6 +603,10 @@ bool Selector_Selector::restore()
       if (!mySubSelList.back().restore())
         aSubResult = false;
     }
+    Handle(TDataStd_Integer) aWeakInt;
+    if (myLab.FindAttribute(kWEAK_INDEX, aWeakInt)) {
+      myWeakIndex = aWeakInt->Get();
+    }
     return aSubResult;
   }
   case SELTYPE_PRIMITIVE: {
@@ -607,6 +655,17 @@ bool Selector_Selector::restore()
     }
     return true;
   }
+  case SELTYPE_WEAK_NAMING: {
+    Handle(TDataStd_Integer) aWeakInt;
+    if (!myLab.FindAttribute(kWEAK_INDEX, aWeakInt))
+      return false;
+    myWeakIndex = aWeakInt->Get();
+    Handle(TDataStd_Integer) aShapeTypeAttr;
+    if (!myLab.FindAttribute(kSHAPE_TYPE, aShapeTypeAttr))
+      return false;
+    myShapeType = TopAbs_ShapeEnum(aShapeTypeAttr->Get());
+    return myWeakIndex != -1;
+  }
   default: { // unknown case
   }
   }
@@ -704,9 +763,16 @@ bool Selector_Selector::solve(const TopoDS_Shape& theContext)
     }
     TopoDS_ListOfShape aCommon; // common sub shapes in each sub-selector (a result)
     commonShapes(aSubSelectorShapes, myShapeType, aCommon);
-    if (aCommon.Extent() != 1)
-      return false;
-    aResult = aCommon.First();
+    if (aCommon.Extent() != 1) {
+      if (myWeakIndex != -1) {
+        Selector_NExplode aNexp(aCommon);
+        aResult = aNexp.shape(myWeakIndex);
+      } else {
+        return false;
+      }
+    } else {
+      aResult = aCommon.First();
+    }
     break;
   }
   case SELTYPE_PRIMITIVE: {
@@ -751,6 +817,11 @@ bool Selector_Selector::solve(const TopoDS_Shape& theContext)
       aNBs.push_back(std::pair<TopoDS_Shape, int>(aSubSel->value(), *aLevel));
     }
     aResult = findNeighbor(theContext, aNBs);
+    break;
+  }
+  case SELTYPE_WEAK_NAMING: {
+    Selector_NExplode aNexp(theContext, myShapeType);
+    aResult = aNexp.shape(myWeakIndex);
   }
   default: { // unknown case
   }
@@ -779,13 +850,18 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
   case SELTYPE_CONTAINER:
   case SELTYPE_INTERSECT: {
     std::string aResult;
-    // add names of sub-components one by one in "[]"
+    // add names of sub-components one by one in "[]" +optionally [weak_name_1]
     std::list<Selector_Selector>::iterator aSubSel = mySubSelList.begin();
     for(; aSubSel != mySubSelList.end(); aSubSel++) {
       aResult += '[';
       aResult += aSubSel->name(theNameGenerator);
       aResult += ']';
     }
+    if (myWeakIndex != -1) {
+      std::ostringstream aWeakStr;
+      aWeakStr<<"["<<kWEAK_NAME_IDENTIFIER<<myWeakIndex<<"]";
+      aResult += aWeakStr.str();
+    }
     return aResult;
   }
   case SELTYPE_PRIMITIVE: {
@@ -806,6 +882,7 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
     for(TDF_LabelList::iterator aBase = myBases.begin(); aBase != myBases.end(); aBase++) {
       if (!aBase->FindAttribute(TDataStd_Name::GetID(), aName))
         return "";
+      aResult += "&";
       aResult += theNameGenerator->contextName(*aBase) + "/" +
         std::string(TCollection_AsciiString(aName->Get()).ToCString());
     }
@@ -828,6 +905,13 @@ std::string Selector_Selector::name(Selector_NameGenerator* theNameGenerator) {
     }
     return aResult;
   }
+  case SELTYPE_WEAK_NAMING: {
+    // weak_naming_1
+    std::ostringstream aWeakStr;
+    aWeakStr<<kWEAK_NAME_IDENTIFIER<<myWeakIndex;
+    std::string aResult = aWeakStr.str();
+    return aResult;
+  }
   default: { // unknown case
   }
   };
@@ -861,6 +945,11 @@ TDF_Label Selector_Selector::restoreByName(
       size_t anEndPos = theName.find(']', aStart + 1);
       if (anEndPos != std::string::npos) {
         std::string aSubStr = theName.substr(aStart + 1, anEndPos - aStart - 1);
+        if (aSubStr.find(kWEAK_NAME_IDENTIFIER) == 0) { // weak name identifier
+          std::string aWeakIndex = aSubStr.substr(kWEAK_NAME_IDENTIFIER.size());
+          myWeakIndex = atoi(aWeakIndex.c_str());
+          continue;
+        }
         mySubSelList.push_back(Selector_Selector(myLab.FindChild(int(mySubSelList.size()) + 1)));
         TDF_Label aSubContext =
           mySubSelList.back().restoreByName(aSubStr, theShapeType, theNameGenerator);
@@ -922,6 +1011,12 @@ TDF_Label Selector_Selector::restoreByName(
       if (!myFinal.IsNull())
         return aContext;
     }
+  } if (theName.find(kWEAK_NAME_IDENTIFIER) == 0) { // weak naming identifier
+    myType = SELTYPE_WEAK_NAMING;
+    std::string aWeakIndex = theName.substr(kWEAK_NAME_IDENTIFIER.size());
+    myWeakIndex = atoi(aWeakIndex.c_str());
+    myShapeType = theShapeType;
+    return myLab;
   } else { // modification
     myType = SELTYPE_MODIFICATION;
     TDF_Label aContext;
index a91816c36367d43babe1251237102d9e50d45e11..06b05d2daebefdf91ccf55be88020d0dc2c3ebba 100644 (file)
@@ -45,6 +45,7 @@ class Selector_Selector
     SELTYPE_PRIMITIVE, ///< sub-shape found as a primitive on some label
     SELTYPE_MODIFICATION, ///< modification of base shapes to the final label
     SELTYPE_FILTER_BY_NEIGHBOR,  ///< identification by neighbor shapes in context
+    SELTYPE_WEAK_NAMING, ///< pure weak naming by weak index in context
   };
 
   Selector_Type myType; ///< Type of this selector.