Fix the problem with selection of similar sub-shapes shared by solids in compsolid
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) {
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();
// 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;
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;
}
}
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
*/
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
}
// 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
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))
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 =
// 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;
}
}
}
// 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());
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;
}
}
}
- return (bool)theResult;
+ return !theSelected.empty();
}
} // 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
}
static int possibleSelectionsByPoint(const GeomPointPtr& thePoint,
- const GeomAPI_Shape::ShapeType& theType,
+ const ResultPtr& theResult,
+ const GeomShapePtr& theShape,
const FeaturePtr& theStartFeature,
const FeaturePtr& theEndFeature)
{
// 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) {
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;
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;
}
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;