-// 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
//
// 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 "ModelGeomAlgo_Shape.h"
+#include <ModelAPI_AttributeSelection.h>
#include <ModelAPI_CompositeFeature.h>
#include <ModelAPI_Feature.h>
#include <ModelAPI_Result.h>
-#include <ModelAPI_ResultCompSolid.h>
+#include <ModelAPI_ResultBody.h>
#include <ModelAPI_ResultConstruction.h>
+#include <GeomAPI_Circ.h>
+#include <GeomAPI_Ellipse.h>
#include <GeomAPI_PlanarEdges.h>
#include <GeomAPI_Pnt.h>
}
// 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);
+ }
+ return aFoundSubs;
+ }
+
+ // Find circular/elliptic 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<GeomShapePtr> anEdges = theBaseShape->subShapes(GeomAPI_Shape::EDGE);
+ for (std::list<GeomShapePtr>::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<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;
+ // 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<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);
+ }
+
+ 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)
+ 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 std::shared_ptr<GeomAPI_Pnt>& thePoint,
const GeomAPI_Shape::ShapeType& theShapeType,
- std::shared_ptr<ModelAPI_Result>& theResult,
- std::shared_ptr<GeomAPI_Shape>& theSubshape)
+ std::list<SubshapeOfResult>& theSelected)
{
- static const double TOLERANCE = 1.e-7;
+ static const double TOLERANCE = 1.e-6;
+
+ theSelected.clear();
- theResult = ResultPtr();
- theSubshape = GeomShapePtr();
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))
std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aCurShape);
if (theShapeType != GeomAPI_Shape::COMPOUND || !aSketchEdges) {
- ResultCompSolidPtr aCompSolid =
- std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIt);
+ ResultBodyPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aResIt);
if (aCompSolid) {
- // process solids
- int aNbSolids = aCompSolid->numberOfSubs();
- for (int i = 0; i < aNbSolids && !theSubshape; ++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;
- }
- }
- if (theSubshape)
- break;
+ isSubshapeFound = findSubshapeInCompsolid(aCompSolid,
+ thePoint, theShapeType, TOLERANCE, theSelected);
}
- 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 &&
+ 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: 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()) {
+ // 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<ModelAPI_CompositeFeature>(theFeature);
std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aResults.front()->shape());
if (aSketchEdges && aCF) {
- bool isContinue = true;
int aNbSubs = aCF->numberOfSubs();
- for (int aSubInd = 0; aSubInd < aNbSubs && isContinue; ++aSubInd) {
+ for (int aSubInd = 0; aSubInd < aNbSubs; ++aSubInd) {
FeaturePtr aSub = aCF->subFeature(aSubInd);
const std::list<ResultPtr>& aSubResults = aSub->results();
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();
- isContinue = false;
+ std::list<GeomShapePtr> aSubshapes =
+ findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
+ if (!aSubshapes.empty()) {
+ appendSubshapeOfResult(theSelected, aResults.front(), aSubshapes);
break;
}
}
}
}
- return (bool)theResult;
+ return !theSelected.empty();
}
} // namespace ModelGeomAlgo_Shape