Salome HOME
Issue #2612 : Re-calculate model after modification of parameters
[modules/shaper.git] / src / Model / Model_AttributeSelection.cpp
index b81952bd58d0d1b6188dc675235c27b9a59c054f..2337fb0b58d2bed9e4d3027814fb3e809048f7eb 100644 (file)
 #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_Pnt.h>
 #include <GeomAPI_Vertex.h>
 #include <GeomAlgoAPI_CompoundBuilder.h>
 
@@ -492,10 +494,10 @@ FeaturePtr Model_AttributeSelection::contextFeature() {
   return std::dynamic_pointer_cast<ModelAPI_Feature>(myRef.value());
 }
 ObjectPtr Model_AttributeSelection::contextObject() {
-  ResultPtr aRes = context();
+  FeaturePtr aRes = contextFeature();
   if (aRes.get())
     return aRes;
-  return contextFeature();
+  return context();
 }
 
 
@@ -1065,6 +1067,91 @@ void Model_AttributeSelection::selectSubShape(
   reset();
 }
 
+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);
+  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();
+  std::list<FeaturePtr> aFeatures = aSession->moduleDocument()->allFeatures();
+  if (aSession->moduleDocument() != owner()->document()) {
+    std::list<FeaturePtr> aPartFeatures = owner()->document()->allFeatures();
+    aFeatures.insert(aFeatures.end(), aPartFeatures.begin(), aPartFeatures.end());
+  }
+  // Process results of all features from the last to the first
+  // 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;
+    const std::set<AttributePtr>& aRefs = (*anIt)->data()->refsToMe();
+    for (std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
+         aRefIt != aRefs.end() && !isSubOfComposite; ++aRefIt) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature((*aRefIt)->owner());
+      CompositeFeaturePtr aCompFeature =
+          std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature);
+      isSubOfComposite = aCompFeature && aCompFeature->isSub(*anIt);
+    }
+    if (isSubOfComposite)
+      continue;
+
+    // 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;
+      }
+    }
+  }
+
+  TDF_Label aSelLab = selectionLabel();
+  setInvalidIfFalse(aSelLab, false);
+  reset();
+}
+
 int Model_AttributeSelection::Id()
 {
   int anID = 0;