]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp
Salome HOME
Fix issues related to selection of sub-shapes in a Part
[modules/shaper.git] / src / ModelGeomAlgo / ModelGeomAlgo_Shape.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <GeomAPI_Shape.h>
22
23 #include "ModelGeomAlgo_Shape.h"
24
25 #include <ModelAPI_AttributeSelection.h>
26 #include <ModelAPI_CompositeFeature.h>
27 #include <ModelAPI_Feature.h>
28 #include <ModelAPI_Result.h>
29 #include <ModelAPI_ResultBody.h>
30 #include <ModelAPI_ResultConstruction.h>
31
32 #include <GeomAPI_Circ.h>
33 #include <GeomAPI_Ellipse.h>
34 #include <GeomAPI_PlanarEdges.h>
35 #include <GeomAPI_Pnt.h>
36
37
38 #ifdef WIN32
39 #pragma warning(disable : 4996) // for sprintf
40 #endif
41
42 namespace ModelGeomAlgo_Shape
43 {
44   void shapesOfType(const FeaturePtr& theFeature,
45                     const GeomAPI_Shape::ShapeType& theType,
46                     std::set<ResultPtr>& theShapeResults)
47   {
48     theShapeResults.clear();
49     std::list<ResultPtr> aResults = theFeature->results();
50     std::list<ResultPtr>::const_iterator aRIter = aResults.cbegin();
51     for (; aRIter != aResults.cend(); aRIter++) {
52       ResultPtr aResult = *aRIter;
53       GeomShapePtr aShape = aResult->shape();
54       if (aShape.get() && aShape->shapeType() == theType)
55         theShapeResults.insert(aResult);
56     }
57   }
58
59   // Check the point is within shape's bounding box
60   static bool isPointWithinBB(const GeomPointPtr& thePoint,
61                               const GeomShapePtr& theShape,
62                               const double theTolerance)
63   {
64     double aXMin, aXMax, aYMin, aYMax, aZMin, aZMax;
65     return theShape->computeSize(aXMin, aYMin, aZMin, aXMax, aYMax, aZMax) &&
66            thePoint->x() >= aXMin - theTolerance && thePoint->x() <= aXMax + theTolerance &&
67            thePoint->y() >= aYMin - theTolerance && thePoint->y() <= aYMax + theTolerance &&
68            thePoint->z() >= aZMin - theTolerance && thePoint->z() <= aZMax + theTolerance;
69   }
70
71   // Select sub-shape of the given type, which contains the given point
72   static std::list<GeomShapePtr> findSubShape(const GeomShapePtr& theShape,
73                                               const GeomAPI_Shape::ShapeType& theType,
74                                               const GeomPointPtr& thePoint,
75                                               const double theTolerance)
76   {
77     std::list<GeomShapePtr> aFoundSubs;
78     std::list<GeomShapePtr> aSubs = theShape->subShapes(theType);
79     for (std::list<GeomShapePtr>::const_iterator aSubIt = aSubs.begin();
80          aSubIt != aSubs.end(); ++aSubIt) {
81       GeomPointPtr aMiddlePoint = (*aSubIt)->middlePoint();
82       if (aMiddlePoint && aMiddlePoint->distance(thePoint) < theTolerance)
83         aFoundSubs.push_back(*aSubIt);
84     }
85     return aFoundSubs;
86   }
87
88   // Find circular/elliptical edge, which center/focus coincide with the given point
89   static GeomShapePtr findEdgeByCenter(const GeomShapePtr& theBaseShape,
90                                        const GeomPointPtr& theCenter,
91                                        const double theTolerance,
92                                        int& theCenterType)
93   {
94     theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER;
95     std::list<GeomShapePtr> anEdges = theBaseShape->subShapes(GeomAPI_Shape::EDGE);
96     for (std::list<GeomShapePtr>::const_iterator anIt = anEdges.begin();
97          anIt != anEdges.end(); ++anIt) {
98       GeomEdgePtr anEdge = (*anIt)->edge();
99       if (!anEdge)
100         continue;
101
102       if (anEdge->isCircle()) {
103         GeomCirclePtr aCircle = anEdge->circle();
104         if (aCircle->center()->distance(theCenter) < theTolerance) {
105           theCenterType = (int)ModelAPI_AttributeSelection::CIRCLE_CENTER;
106           return *anIt;
107         }
108       }
109       else if (anEdge->isEllipse()) {
110         GeomEllipsePtr anEllipse = anEdge->ellipse();
111         if (anEllipse->firstFocus()->distance(theCenter) < theTolerance)
112           theCenterType = (int)ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS;
113         else if (anEllipse->secondFocus()->distance(theCenter) < theTolerance)
114           theCenterType = (int)ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS;
115
116         if (theCenterType != (int)ModelAPI_AttributeSelection::NOT_CENTER)
117           return *anIt;
118       }
119     }
120
121     // not found
122     return GeomShapePtr();
123   }
124
125   static void appendSubshapeOfResult(std::list<SubshapeOfResult>& theList,
126       const ResultPtr& theResult,
127       const GeomShapePtr& theSubshape,
128       int theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER)
129   {
130     SubshapeOfResult aSR;
131     aSR.myResult = theResult;
132     aSR.mySubshape = theSubshape;
133     aSR.myCenterType = theCenterType;
134     theList.push_back(aSR);
135   }
136
137   static void appendSubshapeOfResult(std::list<SubshapeOfResult>& theList,
138       const ResultPtr& theResult,
139       const std::list<GeomShapePtr>& theSubshape)
140   {
141     for (std::list<GeomShapePtr>::const_iterator anIt = theSubshape.begin();
142          anIt != theSubshape.end(); ++anIt) {
143       SubshapeOfResult aSR;
144       aSR.myResult = theResult;
145       aSR.mySubshape = *anIt;
146       aSR.myCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER;
147       theList.push_back(aSR);
148     }
149   }
150
151   bool findSubshapeByPoint(const std::shared_ptr<ModelAPI_Feature>& theFeature,
152                            const std::shared_ptr<GeomAPI_Pnt>& thePoint,
153                            const GeomAPI_Shape::ShapeType& theShapeType,
154                            std::list<SubshapeOfResult>& theSelected)
155   {
156     static const double TOLERANCE = 1.e-6;
157
158     theSelected.clear();
159
160     const std::list<ResultPtr>& aResults = theFeature->results();
161     for (std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
162          aResIt != aResults.end(); ++aResIt) {
163       bool isSubshapeFound = false;
164       GeomShapePtr aCurShape = (*aResIt)->shape();
165       // first of all, check the point is within bounding box of the result
166       if (!aCurShape || !isPointWithinBB(thePoint, aCurShape, TOLERANCE))
167         continue;
168       // now, process all sub-shapes of the given type and check their inner points,
169       // but skip the case the selected type is COMPOUND and the shape is a list of sketch edges
170       // (it will be processed later)
171       std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
172           std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aCurShape);
173       if (theShapeType != GeomAPI_Shape::COMPOUND || !aSketchEdges) {
174         ResultBodyPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aResIt);
175         if (aCompSolid) {
176           // process solids
177           int aNbSolids = aCompSolid->numberOfSubs();
178           for (int i = 0; i < aNbSolids; ++i) {
179             ResultPtr aSubResult = aCompSolid->subResult(i);
180             GeomShapePtr aSubSolid = aSubResult->shape();
181             if (aSubSolid && isPointWithinBB(thePoint, aSubSolid, TOLERANCE)) {
182               std::list<GeomShapePtr> aSubshapes =
183                   findSubShape(aSubSolid, theShapeType, thePoint, TOLERANCE);
184               if (!aSubshapes.empty()) {
185                 appendSubshapeOfResult(theSelected, aSubResult, aSubshapes);
186                 isSubshapeFound = true;
187               }
188             }
189           }
190         }
191
192         if (!isSubshapeFound) {
193           std::list<GeomShapePtr> aSubshapes =
194               findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
195           if (!aSubshapes.empty()) {
196             appendSubshapeOfResult(theSelected, *aResIt, aSubshapes);
197             isSubshapeFound = true;
198           }
199         }
200       }
201       if (isSubshapeFound)
202         continue;
203
204       // special case for ResultConstruction if the FACE is selected
205       ResultConstructionPtr aResConstr =
206           std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIt);
207       if (aResConstr && theShapeType >= GeomAPI_Shape::FACE) {
208         int aNbFaces = aResConstr->facesNum();
209         for (int aFaceInd = 0; aFaceInd < aNbFaces; ++aFaceInd) {
210           GeomFacePtr aCurFace = aResConstr->face(aFaceInd);
211           // check the point is within bounding box of the face
212           if (!isPointWithinBB(thePoint, aCurFace, TOLERANCE))
213             continue;
214           std::list<GeomShapePtr> aSubshapes =
215               findSubShape(aCurFace, theShapeType, thePoint, TOLERANCE);
216           if (!aSubshapes.empty()) {
217             appendSubshapeOfResult(theSelected, *aResIt, aSubshapes);
218             isSubshapeFound = true;
219           }
220         }
221       }
222       if (isSubshapeFound)
223         continue;
224
225       // next special case: the full sketch is selected
226       // the selection type is a COMPOUND
227       if (aSketchEdges && theShapeType == GeomAPI_Shape::COMPOUND &&
228           aSketchEdges->middlePoint()->distance(thePoint) < TOLERANCE) {
229         // select whole result
230         appendSubshapeOfResult(theSelected, *aResIt, GeomShapePtr());
231         continue;
232       }
233
234       // another special case: the center of circle or the focus of ellipse is selected;
235       // return the corresponding edge and a status of the center
236       if (theShapeType == GeomAPI_Shape::VERTEX) {
237         int aCenterType;
238         GeomShapePtr aSubshape = findEdgeByCenter(aCurShape, thePoint, TOLERANCE, aCenterType);
239         if (aSubshape) {
240           appendSubshapeOfResult(theSelected, *aResIt, aSubshape, aCenterType);
241           continue;
242         }
243       }
244     }
245
246     // one more special case: the selected entity is a separated sketch point
247     // or an auxiliary sketch edge; they are not included into the sketch result;
248     // thus, it is necessary to pass through the sketch sub-features and find selected.
249     if (theSelected.empty() && !aResults.empty() &&
250        (theShapeType == GeomAPI_Shape::VERTEX || theShapeType == GeomAPI_Shape::EDGE)) {
251       CompositeFeaturePtr aCF = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
252       std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
253           std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aResults.front()->shape());
254
255       if (aSketchEdges && aCF) {
256         int aNbSubs = aCF->numberOfSubs();
257         for (int aSubInd = 0; aSubInd < aNbSubs; ++aSubInd) {
258           FeaturePtr aSub = aCF->subFeature(aSubInd);
259           const std::list<ResultPtr>& aSubResults = aSub->results();
260           for (std::list<ResultPtr>::const_iterator aSRIt = aSubResults.begin();
261                aSRIt != aSubResults.end(); ++aSRIt) {
262             GeomShapePtr aCurShape = (*aSRIt)->shape();
263             std::list<GeomShapePtr> aSubshapes =
264                 findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
265             if (!aSubshapes.empty()) {
266               appendSubshapeOfResult(theSelected, aResults.front(), aSubshapes);
267               break;
268             }
269           }
270         }
271       }
272     }
273
274     return !theSelected.empty();
275   }
276 } // namespace ModelGeomAlgo_Shape