#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>
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();
// 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;
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;
}
}