Salome HOME
Dump with geometrical selection
authorazv <azv@opencascade.com>
Wed, 22 Aug 2018 12:46:28 +0000 (15:46 +0300)
committerazv <azv@opencascade.com>
Thu, 30 Aug 2018 08:39:24 +0000 (11:39 +0300)
Fix the problem with selection of similar sub-shapes shared by solids in compsolid

src/Model/Model_AttributeSelection.cpp
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp
src/ModelGeomAlgo/ModelGeomAlgo_Shape.h
src/ModelHighAPI/ModelHighAPI_Dumper.cpp

index 70e3643013db59909594a328c3ef0982a11a4425..2337fb0b58d2bed9e4d3027814fb3e809048f7eb 100644 (file)
@@ -1073,6 +1073,10 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType,
   if (theType.empty() || !thePoint)
     return;
 
+  // list of parent features
+  FeaturePtr anOwner = ModelAPI_Feature::feature(owner());
+  std::set<FeaturePtr> aParents = ModelAPI_Tools::getParents(anOwner);
+
   int aSelectionIndex = 0;
   GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::shapeTypeByStr(theType);
   if (aType == GeomAPI_Shape::SHAPE) {
@@ -1095,9 +1099,8 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType,
       aSelectionIndex -= 1;
     }
   }
-  ResultPtr aFoundResult;
-  GeomShapePtr aFoundSubShape;
-  int aFoundCenterType;
+
+  std::list<ModelGeomAlgo_Shape::SubshapeOfResult> anAppropriate;
 
   // collect features from PartSet and the current part
   SessionPtr aSession = ModelAPI_Session::get();
@@ -1110,6 +1113,9 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType,
   // to find appropriate sub-shape
   for (std::list<FeaturePtr>::const_reverse_iterator anIt = aFeatures.rbegin();
        anIt != aFeatures.rend(); ++anIt) {
+    // selection cannot be linked to the parent features
+    if (aParents.find(*anIt) != aParents.end())
+      continue;
     // check the feature is a part of composite feature (like sketch elements),
     // then do not process it, it will be processed in scope of composite feature
     bool isSubOfComposite = false;
@@ -1125,17 +1131,17 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType,
       continue;
 
     // process results of the current feature to find appropriate sub-shape
-    aFoundCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER;
-    if (ModelGeomAlgo_Shape::findSubshapeByPoint(*anIt, thePoint, aType,
-                                                 aFoundResult, aFoundSubShape, aFoundCenterType)) {
-      if (aSelectionIndex > 0)
-        --aSelectionIndex; // skip this shape, because one of the previous is selected
-      else {
-        if (aFoundCenterType == (int)ModelAPI_AttributeSelection::NOT_CENTER)
-          setValue(aFoundResult, aFoundSubShape);
+    if (ModelGeomAlgo_Shape::findSubshapeByPoint(*anIt, thePoint, aType, anAppropriate)) {
+      std::list<ModelGeomAlgo_Shape::SubshapeOfResult>::iterator anApIt = anAppropriate.begin();
+      for (; aSelectionIndex > 0 && anApIt != anAppropriate.end(); --aSelectionIndex)
+        ++anApIt; // skip this shape, because one of the previous is selected
+
+      if (anApIt != anAppropriate.end()) {
+        if (anApIt->myCenterType == (int)ModelAPI_AttributeSelection::NOT_CENTER)
+          setValue(anApIt->myResult, anApIt->mySubshape);
         else
-          setValueCenter(aFoundResult, aFoundSubShape->edge(),
-                         (ModelAPI_AttributeSelection::CenterType)aFoundCenterType);
+          setValueCenter(anApIt->myResult, anApIt->mySubshape->edge(),
+                         (ModelAPI_AttributeSelection::CenterType)anApIt->myCenterType);
         return;
       }
     }
index a1f4ef0640583075e4dd4eee980a3049f3309821..0b58e55968c5d69d71cc1a0fce20c0fa16016fdc 100755 (executable)
@@ -717,4 +717,44 @@ std::pair<std::string, bool> getDefaultName(const std::shared_ptr<ModelAPI_Resul
   return std::pair<std::string, bool>(aDefaultName.str(), false);
 }
 
+std::set<FeaturePtr> getParents(const FeaturePtr& theFeature)
+{
+  std::set<FeaturePtr> aParents;
+  for (FeaturePtr aCurFeat = theFeature; aCurFeat; ) {
+    CompositeFeaturePtr aFoundComposite;
+    const std::set<AttributePtr>& aRefs = aCurFeat->data()->refsToMe();
+    for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin();
+      anIt != aRefs.end(); ++anIt) {
+      FeaturePtr aF = ModelAPI_Feature::feature((*anIt)->owner());
+      aFoundComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aF);
+      if (aFoundComposite && aFoundComposite->isSub(aCurFeat))
+        break;
+      else
+        aFoundComposite = CompositeFeaturePtr();
+    }
+
+    if (aFoundComposite) {
+      aParents.insert(aFoundComposite);
+      aCurFeat = aFoundComposite;
+    }
+    else {
+      // add the part containing high-level feature
+      SessionPtr aSession = ModelAPI_Session::get();
+      DocumentPtr aPartSetDoc = aSession->moduleDocument();
+      std::list<FeaturePtr> aPartSetFeatures = aPartSetDoc->allFeatures();
+      for (std::list<FeaturePtr>::const_iterator anIt = aPartSetFeatures.begin();
+        anIt != aPartSetFeatures.end(); ++anIt) {
+        aFoundComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*anIt);
+        if (aFoundComposite && aFoundComposite->isSub(aCurFeat)) {
+          aParents.insert(aFoundComposite);
+          break;
+        }
+      }
+
+      aCurFeat = FeaturePtr();
+    }
+  }
+  return aParents;
+}
+
 } // namespace ModelAPI_Tools
index e302d19a0634191fed1345f06ec8688ba64431ac..0b21a3c2eace9a55a4c442259fd127a57fee550e 100755 (executable)
@@ -200,6 +200,11 @@ MODELAPI_EXPORT void getConcealedResults(const std::shared_ptr<ModelAPI_Feature>
  */
 MODELAPI_EXPORT std::pair<std::string, bool> getDefaultName(
   const std::shared_ptr<ModelAPI_Result>& theResult, const bool theInherited = true);
+
+/*! Collect all parents for the given feature, including the Part
+ */
+MODELAPI_EXPORT std::set<std::shared_ptr<ModelAPI_Feature> >
+    getParents(const std::shared_ptr<ModelAPI_Feature>& theFeature);
 }
 
 #endif
index 05929ba1c882a6bdee15a686a3b613ef6b409b13..b15754742b69c41ee388eb90ed7e34b262fe4b0b 100644 (file)
@@ -69,21 +69,20 @@ namespace ModelGeomAlgo_Shape
   }
 
   // Select sub-shape of the given type, which contains the given point
-  static GeomShapePtr findSubShape(const GeomShapePtr& theShape,
-                                   const GeomAPI_Shape::ShapeType& theType,
-                                   const GeomPointPtr& thePoint,
-                                   const double theTolerance)
+  static std::list<GeomShapePtr> findSubShape(const GeomShapePtr& theShape,
+                                              const GeomAPI_Shape::ShapeType& theType,
+                                              const GeomPointPtr& thePoint,
+                                              const double theTolerance)
   {
+    std::list<GeomShapePtr> aFoundSubs;
     std::list<GeomShapePtr> aSubs = theShape->subShapes(theType);
     for (std::list<GeomShapePtr>::const_iterator aSubIt = aSubs.begin();
          aSubIt != aSubs.end(); ++aSubIt) {
       GeomPointPtr aMiddlePoint = (*aSubIt)->middlePoint();
       if (aMiddlePoint && aMiddlePoint->distance(thePoint) < theTolerance)
-        return *aSubIt;
+        aFoundSubs.push_back(*aSubIt);
     }
-
-    // not found
-    return GeomShapePtr();
+    return aFoundSubs;
   }
 
   // Find circular/elliptical edge, which center/focus coincide with the given point
@@ -123,22 +122,45 @@ namespace ModelGeomAlgo_Shape
     return GeomShapePtr();
   }
 
+  static void appendSubshapeOfResult(std::list<SubshapeOfResult>& theList,
+      const ResultPtr& theResult,
+      const GeomShapePtr& theSubshape,
+      int theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER)
+  {
+    SubshapeOfResult aSR;
+    aSR.myResult = theResult;
+    aSR.mySubshape = theSubshape;
+    aSR.myCenterType = theCenterType;
+    theList.push_back(aSR);
+  }
+
+  static void appendSubshapeOfResult(std::list<SubshapeOfResult>& theList,
+      const ResultPtr& theResult,
+      const std::list<GeomShapePtr>& theSubshape)
+  {
+    for (std::list<GeomShapePtr>::const_iterator anIt = theSubshape.begin();
+         anIt != theSubshape.end(); ++anIt) {
+      SubshapeOfResult aSR;
+      aSR.myResult = theResult;
+      aSR.mySubshape = *anIt;
+      aSR.myCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER;
+      theList.push_back(aSR);
+    }
+  }
+
   bool findSubshapeByPoint(const std::shared_ptr<ModelAPI_Feature>& theFeature,
                            const std::shared_ptr<GeomAPI_Pnt>& thePoint,
                            const GeomAPI_Shape::ShapeType& theShapeType,
-                           std::shared_ptr<ModelAPI_Result>& theResult,
-                           std::shared_ptr<GeomAPI_Shape>& theSubshape,
-                           int& theCenterType)
+                           std::list<SubshapeOfResult>& theSelected)
   {
     static const double TOLERANCE = 1.e-7;
 
-    theResult = ResultPtr();
-    theSubshape = GeomShapePtr();
-    theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER;
+    theSelected.clear();
 
     const std::list<ResultPtr>& aResults = theFeature->results();
     for (std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
          aResIt != aResults.end(); ++aResIt) {
+      bool isSubshapeFound = false;
       GeomShapePtr aCurShape = (*aResIt)->shape();
       // first of all, check the point is within bounding box of the result
       if (!aCurShape || !isPointWithinBB(thePoint, aCurShape, TOLERANCE))
@@ -154,26 +176,31 @@ namespace ModelGeomAlgo_Shape
         if (aCompSolid) {
           // process solids
           int aNbSolids = aCompSolid->numberOfSubs();
-          for (int i = 0; i < aNbSolids && !theSubshape; ++i) {
+          for (int i = 0; i < aNbSolids; ++i) {
             ResultPtr aSubResult = aCompSolid->subResult(i);
             GeomShapePtr aSubSolid = aSubResult->shape();
             if (aSubSolid && isPointWithinBB(thePoint, aSubSolid, TOLERANCE)) {
-              theSubshape = findSubShape(aSubSolid, theShapeType, thePoint, TOLERANCE);
-              if (theSubshape)
-                theResult = aSubResult;
+              std::list<GeomShapePtr> aSubshapes =
+                  findSubShape(aSubSolid, theShapeType, thePoint, TOLERANCE);
+              if (!aSubshapes.empty()) {
+                appendSubshapeOfResult(theSelected, aSubResult, aSubshapes);
+                isSubshapeFound = true;
+              }
             }
           }
-          if (theSubshape)
-            break;
         }
 
-        if (!theSubshape)
-          theSubshape = findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
-        if (theSubshape) {
-          theResult = *aResIt;
-          break;
+        if (!isSubshapeFound) {
+          std::list<GeomShapePtr> aSubshapes =
+              findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
+          if (!aSubshapes.empty()) {
+            appendSubshapeOfResult(theSelected, *aResIt, aSubshapes);
+            isSubshapeFound = true;
+          }
         }
       }
+      if (isSubshapeFound)
+        continue;
 
       // special case for ResultConstruction if the FACE is selected
       ResultConstructionPtr aResConstr =
@@ -185,33 +212,34 @@ namespace ModelGeomAlgo_Shape
           // check the point is within bounding box of the face
           if (!isPointWithinBB(thePoint, aCurFace, TOLERANCE))
             continue;
-          theSubshape = findSubShape(aCurFace, theShapeType, thePoint, TOLERANCE);
-          if (theSubshape) {
-            theResult = *aResIt;
-            break;
+          std::list<GeomShapePtr> aSubshapes =
+              findSubShape(aCurFace, theShapeType, thePoint, TOLERANCE);
+          if (!aSubshapes.empty()) {
+            appendSubshapeOfResult(theSelected, *aResIt, aSubshapes);
+            isSubshapeFound = true;
           }
         }
       }
-      if (theResult)
-        break;
+      if (isSubshapeFound)
+        continue;
 
       // next special case: the full sketch is selected
       // the selection type is a COMPOUND
       if (aSketchEdges &&
           aSketchEdges->middlePoint()->distance(thePoint) < TOLERANCE) {
         // select whole result
-        theResult = *aResIt;
-        theSubshape = GeomShapePtr();
-        break;
+        appendSubshapeOfResult(theSelected, *aResIt, GeomShapePtr());
+        continue;
       }
 
       // another special case: the center of circle or the focus of ellipse is selected;
       // return the corresponding edge and a status of the center
       if (theShapeType == GeomAPI_Shape::VERTEX) {
-        theSubshape = findEdgeByCenter(aCurShape, thePoint, TOLERANCE, theCenterType);
-        if (theSubshape) {
-          theResult = *aResIt;
-          break;
+        int aCenterType;
+        GeomShapePtr aSubshape = findEdgeByCenter(aCurShape, thePoint, TOLERANCE, aCenterType);
+        if (aSubshape) {
+          appendSubshapeOfResult(theSelected, *aResIt, aSubshape, aCenterType);
+          continue;
         }
       }
     }
@@ -219,7 +247,7 @@ namespace ModelGeomAlgo_Shape
     // one more special case: a vertex selected is a sketch point;
     // it is not included into sketch result; thus, it is necessary
     // to pass through the sketch sub-features and verify all points
-    if (!theResult && theShapeType == GeomAPI_Shape::VERTEX && !aResults.empty()) {
+    if (theSelected.empty() && theShapeType == GeomAPI_Shape::VERTEX && !aResults.empty()) {
       CompositeFeaturePtr aCF = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
       std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
           std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aResults.front()->shape());
@@ -233,9 +261,10 @@ namespace ModelGeomAlgo_Shape
           for (std::list<ResultPtr>::const_iterator aSRIt = aSubResults.begin();
                aSRIt != aSubResults.end(); ++aSRIt) {
             GeomShapePtr aCurShape = (*aSRIt)->shape();
-            theSubshape = findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
-            if (theSubshape) {
-              theResult = aResults.front();
+            std::list<GeomShapePtr> aSubshapes =
+                findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
+            if (!aSubshapes.empty()) {
+              appendSubshapeOfResult(theSelected, aResults.front(), aSubshapes);
               isContinue = false;
               break;
             }
@@ -244,6 +273,6 @@ namespace ModelGeomAlgo_Shape
       }
     }
 
-    return (bool)theResult;
+    return !theSelected.empty();
   }
 } // namespace ModelGeomAlgo_Shape
index fbba1bb25762625dbeca000d14fa7dd517e4d372..2354e8049b3bcf2e845b3e8793b4465f2465bf1f 100644 (file)
@@ -40,22 +40,26 @@ namespace ModelGeomAlgo_Shape {
                               const GeomAPI_Shape::ShapeType& theType,
                               std::set<std::shared_ptr<ModelAPI_Result> >& theShapeResults);
 
+  struct SubshapeOfResult
+  {
+    std::shared_ptr<ModelAPI_Result> myResult;
+    std::shared_ptr<GeomAPI_Shape> mySubshape;
+    int myCenterType;
+  };
+
   /// Searches a sub-shape in the results of the given features,
   /// which contains the given point.
   /// \param[in]  theFeature    feature, which results are being processed
   /// \param[in]  thePoint      selected point which identifies the shape
   /// \param[in]  theShapeType  type of the selected shape
-  /// \param[out] theResult     applicable result
-  /// \param[out] theSubshape   sub-shape of the found result
-  /// \param[out] theCenterType type of the point if it is a center of circle or a focus of ellipse
+  /// \param[out] theSelected   applicable result, sub-shape of the found result and
+  ///                           type of the point if it is a center of circle or a focus of ellipse
   /// \return \c true if the result and its applicable sub-shape are found
   MODELGEOMALGO_EXPORT bool findSubshapeByPoint(
                               const std::shared_ptr<ModelAPI_Feature>& theFeature,
                               const std::shared_ptr<GeomAPI_Pnt>& thePoint,
                               const GeomAPI_Shape::ShapeType& theShapeType,
-                              std::shared_ptr<ModelAPI_Result>& theResult,
-                              std::shared_ptr<GeomAPI_Shape>& theSubshape,
-                              int& theCenterType);
+                              std::list<SubshapeOfResult>& theSelected);
 }
 
 #endif
index d5c22c97fec29d192132fca0684b9edfee1f1257..6c8132447472323082217f3e427a091b81518185 100644 (file)
@@ -939,7 +939,8 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
 }
 
 static int possibleSelectionsByPoint(const GeomPointPtr& thePoint,
-                                     const GeomAPI_Shape::ShapeType& theType,
+                                     const ResultPtr& theResult,
+                                     const GeomShapePtr& theShape,
                                      const FeaturePtr& theStartFeature,
                                      const FeaturePtr& theEndFeature)
 {
@@ -965,41 +966,7 @@ static int possibleSelectionsByPoint(const GeomPointPtr& thePoint,
   // collect the list of composite features, containing the last feature;
   // these features should be excluded from searching,
   // because the feature cannot select sub-shapes from its parent
-  std::set<CompositeFeaturePtr> aEndFeatureParents;
-  for (FeaturePtr aCurFeat = theEndFeature; aCurFeat;) {
-    CompositeFeaturePtr aFoundComposite;
-    const std::set<AttributePtr>& aRefs = aCurFeat->data()->refsToMe();
-    for (std::set<AttributePtr>::const_iterator anIt = aRefs.begin();
-         anIt != aRefs.end(); ++anIt) {
-      FeaturePtr aF = ModelAPI_Feature::feature((*anIt)->owner());
-      aFoundComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aF);
-      if (aFoundComposite && aFoundComposite->isSub(aCurFeat))
-        break;
-      else
-        aFoundComposite = CompositeFeaturePtr();
-    }
-
-    if (aFoundComposite) {
-      aEndFeatureParents.insert(aFoundComposite);
-      aCurFeat = aFoundComposite;
-    }
-    else {
-      // add the part containing high-level feature
-      SessionPtr aSession = ModelAPI_Session::get();
-      DocumentPtr aPartSetDoc = aSession->moduleDocument();
-      std::list<FeaturePtr> aPartSetFeatures = aPartSetDoc->allFeatures();
-      for (std::list<FeaturePtr>::const_iterator anIt = aPartSetFeatures.begin();
-           anIt != aPartSetFeatures.end(); ++anIt) {
-        aFoundComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*anIt);
-        if (aFoundComposite && aFoundComposite->isSub(aCurFeat)) {
-          aEndFeatureParents.insert(aFoundComposite);
-          break;
-        }
-      }
-
-      aCurFeat = FeaturePtr();
-    }
-  }
+  std::set<FeaturePtr> aEndFeatureParents = ModelAPI_Tools::getParents(theEndFeature);
 
   int aNbPossibleSelections = 0;
   for (; aFIt != aFeatures.end() && *aFIt != theEndFeature; ++aFIt) {
@@ -1008,8 +975,11 @@ static int possibleSelectionsByPoint(const GeomPointPtr& thePoint,
       isSkipFeature = true;
     CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFIt);
     if (aCompFeat) {
-      aLastCompositeFeature = aCompFeat;
-      if (aEndFeatureParents.find(aLastCompositeFeature) != aEndFeatureParents.end()) {
+      ResultPartPtr aPartRes =
+          std::dynamic_pointer_cast<ModelAPI_ResultPart>(aCompFeat->firstResult());
+      if (!aPartRes)
+        aLastCompositeFeature = aCompFeat;
+      if (aEndFeatureParents.find(aCompFeat) != aEndFeatureParents.end()) {
         // do not process the parent for the last feature,
         // because it cannot select objects from its parent
         isSkipFeature = true;
@@ -1018,12 +988,22 @@ static int possibleSelectionsByPoint(const GeomPointPtr& thePoint,
     if (isSkipFeature)
       continue;
 
-    ResultPtr aResult;
-    GeomShapePtr aSubshape;
-    int theCenterType;
-    if (ModelGeomAlgo_Shape::findSubshapeByPoint(*aFIt, thePoint, theType,
-                                                 aResult, aSubshape, theCenterType))
-      ++aNbPossibleSelections;
+    std::list<ModelGeomAlgo_Shape::SubshapeOfResult> anApproproate;
+    if (ModelGeomAlgo_Shape::findSubshapeByPoint(*aFIt, thePoint, theShape->shapeType(),
+                                                 anApproproate)) {
+      std::list<ModelGeomAlgo_Shape::SubshapeOfResult>::iterator anApIt = anApproproate.begin();
+      for (; anApIt != anApproproate.end(); ++anApIt) {
+        ++aNbPossibleSelections;
+
+        // stop if the target shape and result are found
+        GeomShapePtr aCurShape = anApIt->mySubshape;
+        if (!aCurShape)
+          aCurShape = anApIt->myResult->shape();
+
+        if (anApIt->myResult->isSame(theResult) && aCurShape->isSame(theShape))
+          break;
+      }
+    }
   }
   return aNbPossibleSelections;
 }
@@ -1072,8 +1052,8 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
     GeomPointPtr aMiddlePoint = aShape->middlePoint();
     // calculate number of features, which could be selected by the same point
     FeaturePtr anOwner = ModelAPI_Feature::feature(theAttrSelect->owner());
-    int aNbPossibleSelections =
-        possibleSelectionsByPoint(aMiddlePoint, aShape->shapeType(), aSelectedFeature, anOwner);
+    int aNbPossibleSelections = possibleSelectionsByPoint(aMiddlePoint,
+        theAttrSelect->context(), aShape, aSelectedFeature, anOwner);
 
     // produce the index if the number of applicable features is greater than 1
     std::string anIndex;