Salome HOME
Issue #2612 : Re-calculate model after modification of parameters
[modules/shaper.git] / src / Model / Model_AttributeSelection.cpp
index 31bc8a0cf190506bd87e8920bf56c4fcb9958d2a..2337fb0b58d2bed9e4d3027814fb3e809048f7eb 100644 (file)
@@ -36,9 +36,9 @@
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
+#include <ModelGeomAlgo_Shape.h>
 #include <Events_InfoMessage.h>
 #include <GeomAPI_Edge.h>
-#include <GeomAPI_PlanarEdges.h>
 #include <GeomAPI_Pnt.h>
 #include <GeomAPI_Vertex.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
@@ -1067,44 +1067,40 @@ void Model_AttributeSelection::selectSubShape(
   reset();
 }
 
-
-// Check the point is within shape's bounding box
-static bool isPointWithinBB(const GeomPointPtr& thePoint, const GeomShapePtr& theShape)
-{
-  double aXMin, aXMax, aYMin, aYMax, aZMin, aZMax;
-  theShape->computeSize(aXMin, aYMin, aZMin, aXMax, aYMax, aZMax);
-  return thePoint->x() >= aXMin - Precision::Confusion() &&
-         thePoint->x() <= aXMax + Precision::Confusion() &&
-         thePoint->y() >= aYMin - Precision::Confusion() &&
-         thePoint->y() <= aYMax + Precision::Confusion() &&
-         thePoint->z() >= aZMin - Precision::Confusion() &&
-         thePoint->z() <= aZMax + Precision::Confusion();
-}
-
-// 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)
-{
-  std::list<GeomShapePtr> aSubs = theShape->subShapes(theType);
-  for (std::list<GeomShapePtr>::const_iterator aSubIt = aSubs.begin();
-    aSubIt != aSubs.end(); ++aSubIt) {
-    if ((*aSubIt)->middlePoint()->distance(thePoint) < Precision::Confusion())
-      return *aSubIt;
-  }
-
-  // not found
-  return GeomShapePtr();
-}
-
 void Model_AttributeSelection::selectSubShape(const std::string& theType,
                                               const GeomPointPtr& thePoint)
 {
   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);
-  GeomShapePtr aFoundSubShape;
+  if (aType == GeomAPI_Shape::SHAPE) {
+    // possibly, the string consists of the type and the index,
+    // thus, try to separate them
+    size_t aUndersporePos = theType.find_first_of('_');
+    if (aUndersporePos != std::string::npos)
+      aType = GeomAPI_Shape::shapeTypeByStr(theType.substr(0, aUndersporePos));
+
+    if (aType != GeomAPI_Shape::SHAPE) {
+      for (std::string::const_iterator aChar = theType.begin() + aUndersporePos + 1;
+           aChar != theType.end(); ++aChar) {
+        if (std::isdigit(*aChar))
+          aSelectionIndex = aSelectionIndex * 10 + (*aChar - '0');
+        else {
+          aSelectionIndex = 1;
+          break;
+        }
+      }
+      aSelectionIndex -= 1;
+    }
+  }
+
+  std::list<ModelGeomAlgo_Shape::SubshapeOfResult> anAppropriate;
 
   // collect features from PartSet and the current part
   SessionPtr aSession = ModelAPI_Session::get();
@@ -1117,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;
@@ -1131,50 +1130,18 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType,
     if (isSubOfComposite)
       continue;
 
-    // process results of the current feature
-    const std::list<ResultPtr>& aResults = (*anIt)->results();
-    for (std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
-         aResIt != aResults.end(); ++aResIt) {
-      GeomShapePtr aCurShape = (*aResIt)->shape();
-      // first of all, check the point is within bounding box of the result
-      if (!aCurShape || !isPointWithinBB(thePoint, aCurShape))
-        continue;
-      // now, process all sub-shapes of the given type and check their inner points,
-      // but skip the case the selected type is COMPOUND and the shape is a list of sketch edges
-      // (it will be processed later)
-      std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
-          std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aCurShape);
-      if (aType != GeomAPI_Shape::COMPOUND || !aSketchEdges)
-        aFoundSubShape = findSubShape(aCurShape, aType, thePoint);
-      if (aFoundSubShape) {
-        setValue(*aResIt, aFoundSubShape);
-        return;
-      }
-
-      // special case for ResultConstruction if the FACE is selected
-      ResultConstructionPtr aResConstr =
-          std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIt);
-      if (aResConstr && aType >= GeomAPI_Shape::FACE) {
-        int aNbFaces = aResConstr->facesNum();
-        for (int aFaceInd = 0; aFaceInd < aNbFaces; ++aFaceInd) {
-          GeomFacePtr aCurFace = aResConstr->face(aFaceInd);
-          // check the point is within bounding box of the face
-          if (!isPointWithinBB(thePoint, aCurFace))
-            continue;
-          aFoundSubShape = findSubShape(aCurFace, aType, thePoint);
-          if (aFoundSubShape) {
-            setValue(*aResIt, aFoundSubShape);
-            return;
-          }
-        }
-      }
-
-      // next special case: the full sketch is selected
-      // the selection type is a COMPOUND
-      if (aSketchEdges &&
-          aSketchEdges->middlePoint()->distance(thePoint) < Precision::Confusion()) {
-        // select whole result
-        setValue(*aResIt, GeomShapePtr());
+    // process results of the current feature to find appropriate sub-shape
+    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(anApIt->myResult, anApIt->mySubshape->edge(),
+                         (ModelAPI_AttributeSelection::CenterType)anApIt->myCenterType);
         return;
       }
     }