-// Copyright (C) 2014-2017 CEA/DEN, EDF R&D
+// Copyright (C) 2014-2023 CEA, EDF
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
//
// 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<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
#include <GeomAPI_Shape.h>
#include <GeomAPI_PlanarEdges.h>
#include <GeomAPI_Pnt.h>
+#include <GeomAlgoAPI_ShapeTools.h>
+
#ifdef WIN32
#pragma warning(disable : 4996) // for sprintf
for (std::list<GeomShapePtr>::const_iterator aSubIt = aSubs.begin();
aSubIt != aSubs.end(); ++aSubIt) {
GeomPointPtr aMiddlePoint = (*aSubIt)->middlePoint();
- if (aMiddlePoint && aMiddlePoint->distance(thePoint) < theTolerance)
+ if (!aMiddlePoint)
+ continue;
+
+ double aDistance = aMiddlePoint->distance(thePoint);
+ bool isFound = aDistance < theTolerance;
+ // issue #19019: special workaround for faces, because if the face contains B-spline contour,
+ // the middle point is calculated with respect to its poles, but not a curve itself.
+ // Thus, in some operations (like BOP) the curve may have different number of poles
+ // from time to time, as a result, the face parametric boundaries are floating
+ // as well as the middle point.
+ // The workaround is to find a distance from the picking point to the face, if the distance
+ // between the picking point and the middle point on the face is small to some extend.
+ static const double THE_THRESHOLD = 100.;
+ if (!isFound && aDistance < THE_THRESHOLD * theTolerance && (*aSubIt)->isFace()) {
+ GeomVertexPtr aVertex(new GeomAPI_Vertex(thePoint));
+ aDistance = GeomAlgoAPI_ShapeTools::minimalDistance(aVertex, *aSubIt);
+ isFound = aDistance < theTolerance;
+ }
+ if (isFound)
aFoundSubs.push_back(*aSubIt);
}
return aFoundSubs;
}
- // Find circular/elliptical edge, which center/focus coincide with the given point
+ // Find circular/elliptic edge, which center/focus coincide with the given point
static GeomShapePtr findEdgeByCenter(const GeomShapePtr& theBaseShape,
const GeomPointPtr& theCenter,
const double theTolerance,
if (!anEdge)
continue;
- if (anEdge->isCircle()) {
+ if (anEdge->isCircle() || anEdge->isArc()) {
GeomCirclePtr aCircle = anEdge->circle();
if (aCircle->center()->distance(theCenter) < theTolerance) {
theCenterType = (int)ModelAPI_AttributeSelection::CIRCLE_CENTER;
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::COMPSOLID) {
+ if (theResult->shape()->isEqual(theSubshape))
+ aSR.mySubshape = GeomShapePtr();
+ else {
+ ResultBodyPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(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);
}
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);
+ anIt != theSubshape.end(); ++anIt)
+ appendSubshapeOfResult(theList, theResult, *anIt);
+ }
+
+ static bool findSubshapeInCompsolid(const ResultBodyPtr& theCompsolid,
+ const std::shared_ptr<GeomAPI_Pnt>& thePoint,
+ const GeomAPI_Shape::ShapeType& theShapeType,
+ const double theTolerance,
+ std::list<SubshapeOfResult>& 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<ModelAPI_ResultBody>(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<GeomShapePtr> aSubshapes =
+ findSubShape(aSubSolid, theShapeType, thePoint, theTolerance);
+ if (!aSubshapes.empty()) {
+ appendSubshapeOfResult(theSelected, aSubResult, aSubshapes);
+ isSubshapeFound = true;
+ }
+ }
+ }
}
+ return isSubshapeFound;
}
bool findSubshapeByPoint(const std::shared_ptr<ModelAPI_Feature>& theFeature,
const GeomAPI_Shape::ShapeType& theShapeType,
std::list<SubshapeOfResult>& theSelected)
{
- static const double TOLERANCE = 1.e-6;
+ static const double TOLERANCE = 1.5e-6;
theSelected.clear();
if (theShapeType != GeomAPI_Shape::COMPOUND || !aSketchEdges) {
ResultBodyPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aResIt);
if (aCompSolid) {
- // process solids
- int aNbSolids = aCompSolid->numberOfSubs();
- for (int i = 0; i < aNbSolids; ++i) {
- ResultPtr aSubResult = aCompSolid->subResult(i);
- GeomShapePtr aSubSolid = aSubResult->shape();
- if (aSubSolid && isPointWithinBB(thePoint, aSubSolid, TOLERANCE)) {
- std::list<GeomShapePtr> aSubshapes =
- findSubShape(aSubSolid, theShapeType, thePoint, TOLERANCE);
- if (!aSubshapes.empty()) {
- appendSubshapeOfResult(theSelected, aSubResult, aSubshapes);
- isSubshapeFound = true;
- }
- }
- }
+ isSubshapeFound = findSubshapeInCompsolid(aCompSolid,
+ thePoint, theShapeType, TOLERANCE, theSelected);
}
if (!isSubshapeFound) {
}
}
+ bool processSketch = theSelected.empty() || (theSelected.size() == 1 &&
+ theSelected.front().myCenterType != (int)ModelAPI_AttributeSelection::NOT_CENTER);
// 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() &&
+ if (processSketch && !aResults.empty() &&
(theShapeType == GeomAPI_Shape::VERTEX || theShapeType == GeomAPI_Shape::EDGE)) {
CompositeFeaturePtr aCF = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =