Salome HOME
Dump with geometrical selection
[modules/shaper.git] / src / Model / Model_SelectionNaming.cpp
index 50b64918e1b2b6b5d29e47ae16001c536744d6a2..1b1c51e9ec70901a076e22a19d15503fb263dae5 100644 (file)
@@ -76,7 +76,14 @@ static Handle(TNaming_NamedShape) shapeToNS(const TDF_Label theLabAccess,
     TDF_Label aLabel = aNSIter.Label();
     Handle(TNaming_NamedShape) aNS;
     if (aLabel.FindAttribute(TNaming_NamedShape::GetID(), aNS)) {
-      if (aNS->Evolution() != TNaming_SELECTED) {
+      if (aNS->Evolution() != TNaming_SELECTED && aNS->Evolution() != TNaming_DELETE) {
+        // check this is new shape in this named shape
+        bool aIsNew = false;
+        for(TNaming_Iterator aNSIter(aNS); aNSIter.More(); aNSIter.Next())
+          if (!aNSIter.NewShape().IsNull() && aNSIter.NewShape().IsSame(theShape))
+            aIsNew = true;
+        if (!aIsNew)
+          continue;
         // check this is the context-shape
         while(aLabel.Depth() > aContextLabDepth)
           aLabel = aLabel.Father();
@@ -134,10 +141,10 @@ std::string Model_SelectionNaming::getShapeName(
             !aNS->Label().IsDescendant(aContextData->label())) {
           isNeedContextName = false;
           TDF_Label aNSDataLab = aNS->Label();
-          while(aNSDataLab.Depth() != 7 && aNSDataLab.Depth() > 5)
+          if (aNSDataLab.Depth() % 2 == 0)
             aNSDataLab = aNSDataLab.Father();
           ObjectPtr aNewContext = theDoc->objects()->object(aNSDataLab);
-          if (!aNewContext.get() && aNSDataLab.Depth() == 7) {
+          while(!aNewContext.get() && aNSDataLab.Depth() > 5) {
             aNSDataLab = aNSDataLab.Father().Father();
             aNewContext = theDoc->objects()->object(aNSDataLab);
           }
@@ -249,6 +256,78 @@ const TopoDS_Shape findCommonShape(
   return aSharedShape;
 }
 
+// searches theType shape that contains theConnectionType sub-shapes in each shape from the List,
+// so, implements the neighbours searching
+/*
+const TopoDS_Shape findCommonShapeByNB(const TopAbs_ShapeEnum theType,
+  const TopAbs_ShapeEnum theConnectionType, const TopTools_ListOfShape& theList)
+{
+TopTools_MapOfShape aCheckedShapes; // already checked shapes of type theType
+  TopoDS_Shape aResult; // theType result shape
+  for(TopTools_ListIteratorOfListOfShape anIt(theList); anIt.More(); anIt.Next()) { // iterate all
+    for(TopExp_Explorer anExp(anIt.ChangeValue(), theType); anExp.More(); anExp.Next()) {
+      if (aCheckedShapes.Contains(anExp.Current()))
+        continue; // already checked
+      aCheckedShapes.Add(anExp.Current());
+      TopTools_MapOfShape aConnectors; // all connectors of the checked theType shape
+      for(TopExp_Explorer aCExp(anExp.Current(), theConnectionType); aCExp.More(); aCExp.Next()) {
+        aConnectors.Add(aCExp.Current());
+      }
+      // check that all shapes from the List contain the connector sub-shapes
+      bool aFound = true;
+      for(TopTools_ListIteratorOfListOfShape anIt2(theList); anIt2.More() && aFound; anIt2.Next()) {
+        if (anIt2.Value().IsSame(anIt.Value()))
+          continue;
+        aFound = false;
+        for(TopExp_Explorer anE(anIt2.ChangeValue(), theConnectionType); anE.More(); anE.Next()) {
+          if (aConnectors.Contains(anE.Current())) {
+            aFound = true;
+            break;
+          }
+        }
+      }
+      if (aFound) {
+        if (!aResult.IsNull()) // more than one result
+          return TopoDS_Shape();
+        aResult = anExp.Current();
+      }
+    }
+  }
+  return aResult;
+}*/
+
+std::string Model_SelectionNaming::vertexNameByEdges(TopoDS_Shape theContext, TopoDS_Shape theSub,
+  std::shared_ptr<Model_Document> theDoc, ResultPtr& theContextRes, const bool theAnotherDoc)
+{
+  std::string aResult;
+  TopTools_IndexedDataMapOfShapeListOfShape aMap;
+  TopExp::MapShapesAndAncestors(theContext, TopAbs_VERTEX, TopAbs_EDGE, aMap);
+  const TopTools_ListOfShape& aList22  = aMap.FindFromKey(theSub);
+  if(aList22.Extent() >= 2)  { // regular solution
+    TopTools_MapOfShape aFMap;
+    TopTools_ListOfShape aListE;
+    TopTools_ListIteratorOfListOfShape itl2(aList22);
+    for (int i = 1;itl2.More();itl2.Next(),i++) {
+      if(aFMap.Add(itl2.Value()))
+        aListE.Append(itl2.Value());
+    }
+    TopTools_ListIteratorOfListOfShape itl(aListE);
+    for (int i = 1;itl.More();itl.Next(),i++) {
+      const TopoDS_Shape& anEdge = itl.Value();
+      std::string anEdgeName = getShapeName(theDoc, anEdge, theContextRes, theAnotherDoc, false);
+      if (anEdgeName.empty()) { // edge is not in DS
+        aResult.clear();
+        return aResult;
+      }
+      if(i == 1)
+        aResult = anEdgeName;
+      else
+        aResult += "&" + anEdgeName;
+    }
+  }
+  return aResult;
+}
+
 std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
   std::shared_ptr<GeomAPI_Shape> theSubSh, const std::string& theDefaultName,
   const bool theAnotherDoc)
@@ -318,7 +397,7 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
           }
         } else
           break;
-        TopTools_ListOfShape aListOfNbs;
+        TopTools_MapOfShape aNbs;
         if(!isTrivialCase) { // find Neighbors
           TNaming_Localizer aLocalizer;
           TopTools_MapOfShape aMap3;
@@ -332,25 +411,25 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
             TopTools_ListIteratorOfListOfShape it2(aList);
             for(;it2.More();it2.Next()) {
               if(aSMap.Contains(it2.Value())) continue; // skip this Face
-              aListOfNbs.Append(it2.Value());
+              aNbs.Add(it2.Value());
             }
           }
         }  // else a trivial case
 
         // build name of the sub-shape Edge
-        for(int i=1; i <= aSMap.Extent(); i++) {
-          const TopoDS_Shape& aFace = aSMap.FindKey(i);
+        // iterate faces of the context to get stable order, not map-order
+        TopTools_MapOfShape aStoredFaces; // to avoid duplicates
+        for(TopExp_Explorer aContExp(aContext, TopAbs_FACE); aContExp.More(); aContExp.Next()) {
+          const TopoDS_Shape& aFace = aContExp.Current();
+          if (aStoredFaces.Contains(aFace) || !(aSMap.Contains(aFace) || aNbs.Contains(aFace)))
+            continue;
+          aStoredFaces.Add(aFace);
           std::string aFaceName = getShapeName(aDoc, aFace, theContext, theAnotherDoc, false);
-          if(i == 1)
+          if(aName.empty())
             aName = aFaceName;
           else
             aName += "&" + aFaceName;
         }
-        TopTools_ListIteratorOfListOfShape itl(aListOfNbs);
-        for (;itl.More();itl.Next()) {
-          std::string aFaceName = getShapeName(aDoc, itl.Value(), theContext, theAnotherDoc, false);
-          aName += "&" + aFaceName;
-        }
       }
       break;
 
@@ -389,40 +468,24 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
           TopoDS_Shape aVertex = findCommonShape(TopAbs_VERTEX, aList);
           isByFaces = !aVertex.IsNull() && aVertex.ShapeType() == TopAbs_VERTEX;
         }
-        if(!isByFaces) { // open topology case or Compound case => via edges
-          TopTools_IndexedDataMapOfShapeListOfShape aMap;
-          TopExp::MapShapesAndAncestors(aContext, TopAbs_VERTEX, TopAbs_EDGE, aMap);
-          const TopTools_ListOfShape& aList22  = aMap.FindFromKey(aSubShape);
-          if(aList22.Extent() >= 2)  { // regular solution
 
-            // bug! duplication; fix is below
-            aFMap.Clear();
-            TopTools_ListOfShape aListE;
-            TopTools_ListIteratorOfListOfShape itl2(aList22);
-            for (int i = 1;itl2.More();itl2.Next(),i++) {
-              if(aFMap.Add(itl2.Value()))
-                aListE.Append(itl2.Value());
-            }
-            n = aListE.Extent();
-            TopTools_ListIteratorOfListOfShape itl(aListE);
-            for (int i = 1;itl.More();itl.Next(),i++) {
-              const TopoDS_Shape& anEdge = itl.Value();
-              std::string anEdgeName = getShapeName(aDoc, anEdge, theContext, theAnotherDoc, false);
-              if (anEdgeName.empty()) { // edge is not in DS, trying by faces anyway
-                isByFaces = true;
-                aName.clear();
-                break;
+        if(!isByFaces) { // open topology case or Compound case => via edges
+          aName = vertexNameByEdges(aContext, aSubShape, aDoc, theContext, theAnotherDoc);
+          isByFaces = aName.empty();
+          if (isByFaces) { // try to find a vertex in sketch faces
+            ResultConstructionPtr aConstr =
+              std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(theContext);
+            if (aConstr.get() && aConstr->facesNum()) {
+              for(int aFace = aConstr->facesNum() - 1; isByFaces && aFace >= 0; aFace--) {
+                std::shared_ptr<GeomAPI_Face> aGFace = aConstr->face(aFace);
+                aName = vertexNameByEdges(aGFace->impl<TopoDS_Face>(), aSubShape,
+                  aDoc, theContext, theAnotherDoc);
+                isByFaces = aName.empty();
               }
-              if(i == 1)
-                aName = anEdgeName;
-              else
-                aName += "&" + anEdgeName;
             }
-          }//reg
-          else { // dangle vertex: if(aList22.Extent() == 1)
-            //it should be already in DF
           }
         }
+
         if (isByFaces) {
           TopTools_ListIteratorOfListOfShape itl(aList);
           for (int i = 1;itl.More();itl.Next(),i++) {
@@ -438,7 +501,6 @@ std::string Model_SelectionNaming::namingName(ResultPtr& theContext,
       break;
     }
   }
-
   return aName;
 }
 
@@ -878,16 +940,28 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
             aFaceContext = aDoc->findByName(aContName, *it, anUniqueContext);
           }
         }
-        const TopoDS_Shape aFace = findFaceByName(*it, aDoc, aFaceContext, anUniqueContext);
+        TopoDS_Shape aFace = findFaceByName(*it, aDoc, aFaceContext, anUniqueContext);
+        if (aFace.IsNull() && aFaceContext.get() &&
+            aFaceContext->groupName() == ModelAPI_ResultConstruction::group() ) {
+          // search the construction sub-elements for the intersection if they are in the tree
+          size_t aSlash = it->find("/");
+          if (aSlash != std::string::npos) {
+            std::string aSubShapeName = it->substr(aSlash + 1);
+            aFace = findFaceByName(aSubShapeName, aDoc, aFaceContext, true);
+          }
+        }
         if(!aFace.IsNull())
           aList.Append(aFace);
       }
       aSelection = findCommonShape(aType, aList);
+      //if (aSelection.IsNull() && aType == TopAbs_EDGE) { // try to find selection by neighbours
+      //  aSelection = findCommonShapeByNB(aType, TopAbs_VERTEX, aList);
+      //}
     }
   }
   // in case of construction, there is no registered names for all sub-elements,
   // even for the main element; so, trying to find them by name (without "&" intersections)
-  if (aN < 2) {
+  if (aSelection.IsNull() && aN < 2) {
     size_t aConstrNamePos = aSubShapeName.find("/");
     bool isFullName = aConstrNamePos == std::string::npos;
     std::string anEmpty, aContrName = aContName;
@@ -1042,6 +1116,21 @@ bool Model_SelectionNaming::selectSubShape(const std::string& theType,
         }
       }
     }
+  } else if (aSelection.IsNull() && aN >= 2 && aType == TopAbs_VERTEX) {
+    // support of shape name as intersection separated by "&"
+    static std::string anEdgeType = "edge"; // for now it works only with su-edges
+    std::list<std::string>::iterator aSubNames = aListofNames.begin();
+    TopTools_ListOfShape aSubsList;
+    for(; aSubNames != aListofNames.end(); aSubNames++) {
+      std::string aSubName = *aSubNames;
+      std::shared_ptr<GeomAPI_Shape> aSubShapeFound;
+      std::shared_ptr<ModelAPI_Result> aContextFound;
+      if (selectSubShape(anEdgeType, aSubName, theDoc, aSubShapeFound, aContextFound)) {
+        if (aSubShapeFound.get())
+          aSubsList.Append(aSubShapeFound->impl<TopoDS_Shape>());
+      }
+    }
+    aSelection = findCommonShape(TopAbs_VERTEX, aSubsList);
   }
   if (!aSelection.IsNull()) {
     // Select it (must be after N=0 checking,