From cde8d0d7004a3ad4a36c6582e2bb5e27870806ad Mon Sep 17 00:00:00 2001 From: azv Date: Wed, 22 Aug 2018 15:46:28 +0300 Subject: [PATCH] Dump with geometrical selection Fix the problem with selection of similar sub-shapes shared by solids in compsolid --- src/Model/Model_AttributeSelection.cpp | 32 +++--- src/ModelAPI/ModelAPI_Tools.cpp | 40 ++++++++ src/ModelAPI/ModelAPI_Tools.h | 5 + src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp | 115 ++++++++++++++-------- src/ModelGeomAlgo/ModelGeomAlgo_Shape.h | 16 +-- src/ModelHighAPI/ModelHighAPI_Dumper.cpp | 72 +++++--------- 6 files changed, 172 insertions(+), 108 deletions(-) diff --git a/src/Model/Model_AttributeSelection.cpp b/src/Model/Model_AttributeSelection.cpp index 70e364301..2337fb0b5 100644 --- a/src/Model/Model_AttributeSelection.cpp +++ b/src/Model/Model_AttributeSelection.cpp @@ -1073,6 +1073,10 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType, if (theType.empty() || !thePoint) return; + // list of parent features + FeaturePtr anOwner = ModelAPI_Feature::feature(owner()); + std::set aParents = ModelAPI_Tools::getParents(anOwner); + int aSelectionIndex = 0; GeomAPI_Shape::ShapeType aType = GeomAPI_Shape::shapeTypeByStr(theType); if (aType == GeomAPI_Shape::SHAPE) { @@ -1095,9 +1099,8 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType, aSelectionIndex -= 1; } } - ResultPtr aFoundResult; - GeomShapePtr aFoundSubShape; - int aFoundCenterType; + + std::list anAppropriate; // collect features from PartSet and the current part SessionPtr aSession = ModelAPI_Session::get(); @@ -1110,6 +1113,9 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType, // to find appropriate sub-shape for (std::list::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; @@ -1125,17 +1131,17 @@ void Model_AttributeSelection::selectSubShape(const std::string& theType, 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::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; } } diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp index a1f4ef064..0b58e5596 100755 --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -717,4 +717,44 @@ std::pair getDefaultName(const std::shared_ptr(aDefaultName.str(), false); } +std::set getParents(const FeaturePtr& theFeature) +{ + std::set aParents; + for (FeaturePtr aCurFeat = theFeature; aCurFeat; ) { + CompositeFeaturePtr aFoundComposite; + const std::set& aRefs = aCurFeat->data()->refsToMe(); + for (std::set::const_iterator anIt = aRefs.begin(); + anIt != aRefs.end(); ++anIt) { + FeaturePtr aF = ModelAPI_Feature::feature((*anIt)->owner()); + aFoundComposite = std::dynamic_pointer_cast(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 aPartSetFeatures = aPartSetDoc->allFeatures(); + for (std::list::const_iterator anIt = aPartSetFeatures.begin(); + anIt != aPartSetFeatures.end(); ++anIt) { + aFoundComposite = std::dynamic_pointer_cast(*anIt); + if (aFoundComposite && aFoundComposite->isSub(aCurFeat)) { + aParents.insert(aFoundComposite); + break; + } + } + + aCurFeat = FeaturePtr(); + } + } + return aParents; +} + } // namespace ModelAPI_Tools diff --git a/src/ModelAPI/ModelAPI_Tools.h b/src/ModelAPI/ModelAPI_Tools.h index e302d19a0..0b21a3c2e 100755 --- a/src/ModelAPI/ModelAPI_Tools.h +++ b/src/ModelAPI/ModelAPI_Tools.h @@ -200,6 +200,11 @@ MODELAPI_EXPORT void getConcealedResults(const std::shared_ptr */ MODELAPI_EXPORT std::pair getDefaultName( const std::shared_ptr& theResult, const bool theInherited = true); + +/*! Collect all parents for the given feature, including the Part + */ +MODELAPI_EXPORT std::set > + getParents(const std::shared_ptr& theFeature); } #endif diff --git a/src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp b/src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp index 05929ba1c..b15754742 100644 --- a/src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp +++ b/src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp @@ -69,21 +69,20 @@ namespace ModelGeomAlgo_Shape } // 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 findSubShape(const GeomShapePtr& theShape, + const GeomAPI_Shape::ShapeType& theType, + const GeomPointPtr& thePoint, + const double theTolerance) { + std::list aFoundSubs; std::list aSubs = theShape->subShapes(theType); for (std::list::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 @@ -123,22 +122,45 @@ namespace ModelGeomAlgo_Shape return GeomShapePtr(); } + static void appendSubshapeOfResult(std::list& 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& theList, + const ResultPtr& theResult, + const std::list& theSubshape) + { + for (std::list::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& theFeature, const std::shared_ptr& thePoint, const GeomAPI_Shape::ShapeType& theShapeType, - std::shared_ptr& theResult, - std::shared_ptr& theSubshape, - int& theCenterType) + std::list& theSelected) { static const double TOLERANCE = 1.e-7; - theResult = ResultPtr(); - theSubshape = GeomShapePtr(); - theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER; + theSelected.clear(); const std::list& aResults = theFeature->results(); for (std::list::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)) @@ -154,26 +176,31 @@ namespace ModelGeomAlgo_Shape 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 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 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 = @@ -185,33 +212,34 @@ namespace ModelGeomAlgo_Shape // 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 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; } } } @@ -219,7 +247,7 @@ namespace ModelGeomAlgo_Shape // 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(theFeature); std::shared_ptr aSketchEdges = std::dynamic_pointer_cast(aResults.front()->shape()); @@ -233,9 +261,10 @@ namespace ModelGeomAlgo_Shape for (std::list::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 aSubshapes = + findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE); + if (!aSubshapes.empty()) { + appendSubshapeOfResult(theSelected, aResults.front(), aSubshapes); isContinue = false; break; } @@ -244,6 +273,6 @@ namespace ModelGeomAlgo_Shape } } - return (bool)theResult; + return !theSelected.empty(); } } // namespace ModelGeomAlgo_Shape diff --git a/src/ModelGeomAlgo/ModelGeomAlgo_Shape.h b/src/ModelGeomAlgo/ModelGeomAlgo_Shape.h index fbba1bb25..2354e8049 100644 --- a/src/ModelGeomAlgo/ModelGeomAlgo_Shape.h +++ b/src/ModelGeomAlgo/ModelGeomAlgo_Shape.h @@ -40,22 +40,26 @@ namespace ModelGeomAlgo_Shape { const GeomAPI_Shape::ShapeType& theType, std::set >& theShapeResults); + struct SubshapeOfResult + { + std::shared_ptr myResult; + std::shared_ptr 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& theFeature, const std::shared_ptr& thePoint, const GeomAPI_Shape::ShapeType& theShapeType, - std::shared_ptr& theResult, - std::shared_ptr& theSubshape, - int& theCenterType); + std::list& theSelected); } #endif diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp index d5c22c97f..6c8132447 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp @@ -939,7 +939,8 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( } static int possibleSelectionsByPoint(const GeomPointPtr& thePoint, - const GeomAPI_Shape::ShapeType& theType, + const ResultPtr& theResult, + const GeomShapePtr& theShape, const FeaturePtr& theStartFeature, const FeaturePtr& theEndFeature) { @@ -965,41 +966,7 @@ static int possibleSelectionsByPoint(const GeomPointPtr& thePoint, // 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 aEndFeatureParents; - for (FeaturePtr aCurFeat = theEndFeature; aCurFeat;) { - CompositeFeaturePtr aFoundComposite; - const std::set& aRefs = aCurFeat->data()->refsToMe(); - for (std::set::const_iterator anIt = aRefs.begin(); - anIt != aRefs.end(); ++anIt) { - FeaturePtr aF = ModelAPI_Feature::feature((*anIt)->owner()); - aFoundComposite = std::dynamic_pointer_cast(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 aPartSetFeatures = aPartSetDoc->allFeatures(); - for (std::list::const_iterator anIt = aPartSetFeatures.begin(); - anIt != aPartSetFeatures.end(); ++anIt) { - aFoundComposite = std::dynamic_pointer_cast(*anIt); - if (aFoundComposite && aFoundComposite->isSub(aCurFeat)) { - aEndFeatureParents.insert(aFoundComposite); - break; - } - } - - aCurFeat = FeaturePtr(); - } - } + std::set aEndFeatureParents = ModelAPI_Tools::getParents(theEndFeature); int aNbPossibleSelections = 0; for (; aFIt != aFeatures.end() && *aFIt != theEndFeature; ++aFIt) { @@ -1008,8 +975,11 @@ static int possibleSelectionsByPoint(const GeomPointPtr& thePoint, isSkipFeature = true; CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast(*aFIt); if (aCompFeat) { - aLastCompositeFeature = aCompFeat; - if (aEndFeatureParents.find(aLastCompositeFeature) != aEndFeatureParents.end()) { + ResultPartPtr aPartRes = + std::dynamic_pointer_cast(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; @@ -1018,12 +988,22 @@ static int possibleSelectionsByPoint(const GeomPointPtr& thePoint, if (isSkipFeature) continue; - ResultPtr aResult; - GeomShapePtr aSubshape; - int theCenterType; - if (ModelGeomAlgo_Shape::findSubshapeByPoint(*aFIt, thePoint, theType, - aResult, aSubshape, theCenterType)) - ++aNbPossibleSelections; + std::list anApproproate; + if (ModelGeomAlgo_Shape::findSubshapeByPoint(*aFIt, thePoint, theShape->shapeType(), + anApproproate)) { + std::list::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; } @@ -1072,8 +1052,8 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( 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; -- 2.30.2