#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>
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;
+ 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;
+ }
+ }
+ ResultPtr aFoundResult;
GeomShapePtr aFoundSubShape;
- std::list<FeaturePtr> aFeatures = owner()->document()->allFeatures();
+ // 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) {
- 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 (!isPointWithinBB(thePoint, aCurShape))
- continue;
- // now, process all sub-shapes of the given type and check their inner points
- aFoundSubShape = findSubShape(aCurShape, aType, thePoint);
- if (aFoundSubShape) {
- setValue(*aResIt, aFoundSubShape);
+ // 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,
+ aFoundResult, aFoundSubShape)) {
+ if (aSelectionIndex > 0)
+ --aSelectionIndex; // skip this shape, because one of the previous is selected
+ else {
+ setValue(aFoundResult, 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;
- }
- }
- }
}
}