X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModelGeomAlgo%2FModelGeomAlgo_Shape.cpp;h=207e4f3aa807ce4c1b861cd4f76df85927b0a26c;hb=b7ec3c27f028060b3c42b7da6fa3dfe962fe26e4;hp=ca7809b3906a09014590f8416afec48dec5d93d5;hpb=d21a0974f79da3df31bc2ccfd5becafb76e815d8;p=modules%2Fshaper.git diff --git a/src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp b/src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp index ca7809b39..207e4f3aa 100644 --- a/src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp +++ b/src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// Copyright (C) 2014-2019 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -12,20 +12,24 @@ // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or -// email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // #include #include "ModelGeomAlgo_Shape.h" +#include +#include #include #include +#include #include +#include +#include #include #include @@ -57,41 +61,146 @@ namespace ModelGeomAlgo_Shape const double theTolerance) { double aXMin, aXMax, aYMin, aYMax, aZMin, aZMax; - theShape->computeSize(aXMin, aYMin, aZMin, aXMax, aYMax, aZMax); - return thePoint->x() >= aXMin - theTolerance && thePoint->x() <= aXMax + theTolerance && + return theShape->computeSize(aXMin, aYMin, aZMin, aXMax, aYMax, aZMax) && + thePoint->x() >= aXMin - theTolerance && thePoint->x() <= aXMax + theTolerance && thePoint->y() >= aYMin - theTolerance && thePoint->y() <= aYMax + theTolerance && thePoint->z() >= aZMin - theTolerance && thePoint->z() <= aZMax + theTolerance; } // 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) { - if ((*aSubIt)->middlePoint()->distance(thePoint) < theTolerance) - return *aSubIt; + aSubIt != aSubs.end(); ++aSubIt) { + GeomPointPtr aMiddlePoint = (*aSubIt)->middlePoint(); + if (aMiddlePoint && aMiddlePoint->distance(thePoint) < theTolerance) + aFoundSubs.push_back(*aSubIt); + } + return aFoundSubs; + } + + // Find circular/elliptical edge, which center/focus coincide with the given point + static GeomShapePtr findEdgeByCenter(const GeomShapePtr& theBaseShape, + const GeomPointPtr& theCenter, + const double theTolerance, + int& theCenterType) + { + theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER; + std::list anEdges = theBaseShape->subShapes(GeomAPI_Shape::EDGE); + for (std::list::const_iterator anIt = anEdges.begin(); + anIt != anEdges.end(); ++anIt) { + GeomEdgePtr anEdge = (*anIt)->edge(); + if (!anEdge) + continue; + + if (anEdge->isCircle()) { + GeomCirclePtr aCircle = anEdge->circle(); + if (aCircle->center()->distance(theCenter) < theTolerance) { + theCenterType = (int)ModelAPI_AttributeSelection::CIRCLE_CENTER; + return *anIt; + } + } + else if (anEdge->isEllipse()) { + GeomEllipsePtr anEllipse = anEdge->ellipse(); + if (anEllipse->firstFocus()->distance(theCenter) < theTolerance) + theCenterType = (int)ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS; + else if (anEllipse->secondFocus()->distance(theCenter) < theTolerance) + theCenterType = (int)ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS; + + if (theCenterType != (int)ModelAPI_AttributeSelection::NOT_CENTER) + return *anIt; + } } // not found 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; + // compound subshapes from other compounds should be processed as whole results + if (aSR.mySubshape && aSR.mySubshape->shapeType() == GeomAPI_Shape::COMPOUND && + !theResult->shape()->isEqual(theSubshape)) { + ResultBodyPtr aResult = std::dynamic_pointer_cast(theResult); + for (int i = 0; aResult && i < aResult->numberOfSubs(); ++i) { + ResultBodyPtr aSub = aResult->subResult(i); + if (aSub->shape()->isEqual(theSubshape)) { + aSR.myResult = aSub; + aSR.mySubshape = GeomShapePtr(); + break; + } + } + } + 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) + appendSubshapeOfResult(theList, theResult, *anIt); + } + + static bool findSubshapeInCompsolid(const ResultBodyPtr& theCompsolid, + const std::shared_ptr& thePoint, + const GeomAPI_Shape::ShapeType& theShapeType, + const double theTolerance, + std::list& theSelected) + { + bool isSubshapeFound = false; + int aNbSolids = theCompsolid->numberOfSubs(); + for (int i = 0; i < aNbSolids; ++i) { + ResultPtr aSubResult = theCompsolid->subResult(i); + + // process subs of compsolid + ResultBodyPtr aSubCompSolid = std::dynamic_pointer_cast(aSubResult); + if (theShapeType != GeomAPI_Shape::COMPSOLID && + aSubCompSolid && aSubCompSolid->numberOfSubs() > 0) { + isSubshapeFound = findSubshapeInCompsolid(aSubCompSolid, + thePoint, theShapeType, theTolerance, theSelected); + } + else { + GeomShapePtr aSubSolid = aSubResult->shape(); + if (aSubSolid && isPointWithinBB(thePoint, aSubSolid, theTolerance)) { + std::list aSubshapes = + findSubShape(aSubSolid, theShapeType, thePoint, theTolerance); + if (!aSubshapes.empty()) { + appendSubshapeOfResult(theSelected, aSubResult, aSubshapes); + isSubshapeFound = true; + } + } + } + } + return isSubshapeFound; + } + 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) + std::list& theSelected) { - static const double TOLERANCE = 1.e-7; + static const double TOLERANCE = 1.e-6; + + theSelected.clear(); - theResult = ResultPtr(); 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)) @@ -101,12 +210,24 @@ namespace ModelGeomAlgo_Shape // (it will be processed later) std::shared_ptr aSketchEdges = std::dynamic_pointer_cast(aCurShape); - if (theShapeType != GeomAPI_Shape::COMPOUND || !aSketchEdges) - theSubshape = findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE); - if (theSubshape) { - theResult = *aResIt; - break; + if (theShapeType != GeomAPI_Shape::COMPOUND || !aSketchEdges) { + ResultBodyPtr aCompSolid = std::dynamic_pointer_cast(*aResIt); + if (aCompSolid) { + isSubshapeFound = findSubshapeInCompsolid(aCompSolid, + thePoint, theShapeType, TOLERANCE, theSelected); + } + + 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 = @@ -118,27 +239,66 @@ 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 && + if (aSketchEdges && theShapeType == GeomAPI_Shape::COMPOUND && 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) { + int aCenterType; + GeomShapePtr aSubshape = findEdgeByCenter(aCurShape, thePoint, TOLERANCE, aCenterType); + if (aSubshape) { + appendSubshapeOfResult(theSelected, *aResIt, aSubshape, aCenterType); + continue; + } + } + } + + // one more special case: the selected entity is a separated sketch point + // or an auxiliary sketch edge; they are not included into the sketch result; + // thus, it is necessary to pass through the sketch sub-features and find selected. + if (theSelected.empty() && !aResults.empty() && + (theShapeType == GeomAPI_Shape::VERTEX || theShapeType == GeomAPI_Shape::EDGE)) { + CompositeFeaturePtr aCF = std::dynamic_pointer_cast(theFeature); + std::shared_ptr aSketchEdges = + std::dynamic_pointer_cast(aResults.front()->shape()); + + if (aSketchEdges && aCF) { + int aNbSubs = aCF->numberOfSubs(); + for (int aSubInd = 0; aSubInd < aNbSubs; ++aSubInd) { + FeaturePtr aSub = aCF->subFeature(aSubInd); + const std::list& aSubResults = aSub->results(); + for (std::list::const_iterator aSRIt = aSubResults.begin(); + aSRIt != aSubResults.end(); ++aSRIt) { + GeomShapePtr aCurShape = (*aSRIt)->shape(); + std::list aSubshapes = + findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE); + if (!aSubshapes.empty()) { + appendSubshapeOfResult(theSelected, aResults.front(), aSubshapes); + break; + } + } + } } } - return (bool)theResult; + return !theSelected.empty(); } } // namespace ModelGeomAlgo_Shape