]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp
Salome HOME
Issue #2971: Naming issue in a group when loading a dump file
[modules/shaper.git] / src / ModelGeomAlgo / ModelGeomAlgo_Shape.cpp
1 // Copyright (C) 2014-2019  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 email : webmaster.salome@opencascade.com
18 //
19
20 #include <GeomAPI_Shape.h>
21
22 #include "ModelGeomAlgo_Shape.h"
23
24 #include <ModelAPI_AttributeSelection.h>
25 #include <ModelAPI_CompositeFeature.h>
26 #include <ModelAPI_Feature.h>
27 #include <ModelAPI_Result.h>
28 #include <ModelAPI_ResultBody.h>
29 #include <ModelAPI_ResultConstruction.h>
30
31 #include <GeomAPI_Circ.h>
32 #include <GeomAPI_Ellipse.h>
33 #include <GeomAPI_PlanarEdges.h>
34 #include <GeomAPI_Pnt.h>
35
36
37 #ifdef WIN32
38 #pragma warning(disable : 4996) // for sprintf
39 #endif
40
41 namespace ModelGeomAlgo_Shape
42 {
43   void shapesOfType(const FeaturePtr& theFeature,
44                     const GeomAPI_Shape::ShapeType& theType,
45                     std::set<ResultPtr>& theShapeResults)
46   {
47     theShapeResults.clear();
48     std::list<ResultPtr> aResults = theFeature->results();
49     std::list<ResultPtr>::const_iterator aRIter = aResults.cbegin();
50     for (; aRIter != aResults.cend(); aRIter++) {
51       ResultPtr aResult = *aRIter;
52       GeomShapePtr aShape = aResult->shape();
53       if (aShape.get() && aShape->shapeType() == theType)
54         theShapeResults.insert(aResult);
55     }
56   }
57
58   // Check the point is within shape's bounding box
59   static bool isPointWithinBB(const GeomPointPtr& thePoint,
60                               const GeomShapePtr& theShape,
61                               const double theTolerance)
62   {
63     double aXMin, aXMax, aYMin, aYMax, aZMin, aZMax;
64     return theShape->computeSize(aXMin, aYMin, aZMin, aXMax, aYMax, aZMax) &&
65            thePoint->x() >= aXMin - theTolerance && thePoint->x() <= aXMax + theTolerance &&
66            thePoint->y() >= aYMin - theTolerance && thePoint->y() <= aYMax + theTolerance &&
67            thePoint->z() >= aZMin - theTolerance && thePoint->z() <= aZMax + theTolerance;
68   }
69
70   // Select sub-shape of the given type, which contains the given point
71   static std::list<GeomShapePtr> findSubShape(const GeomShapePtr& theShape,
72                                               const GeomAPI_Shape::ShapeType& theType,
73                                               const GeomPointPtr& thePoint,
74                                               const double theTolerance)
75   {
76     std::list<GeomShapePtr> aFoundSubs;
77     std::list<GeomShapePtr> aSubs = theShape->subShapes(theType);
78     for (std::list<GeomShapePtr>::const_iterator aSubIt = aSubs.begin();
79          aSubIt != aSubs.end(); ++aSubIt) {
80       double aTol = (*aSubIt)->tolerance();
81       if (theTolerance > aTol)
82         aTol = theTolerance;
83       GeomPointPtr aMiddlePoint = (*aSubIt)->middlePoint();
84       if (aMiddlePoint && aMiddlePoint->distance(thePoint) < aTol)
85         aFoundSubs.push_back(*aSubIt);
86     }
87     return aFoundSubs;
88   }
89
90   // Find circular/elliptical edge, which center/focus coincide with the given point
91   static GeomShapePtr findEdgeByCenter(const GeomShapePtr& theBaseShape,
92                                        const GeomPointPtr& theCenter,
93                                        const double theTolerance,
94                                        int& theCenterType)
95   {
96     theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER;
97     std::list<GeomShapePtr> anEdges = theBaseShape->subShapes(GeomAPI_Shape::EDGE);
98     for (std::list<GeomShapePtr>::const_iterator anIt = anEdges.begin();
99          anIt != anEdges.end(); ++anIt) {
100       GeomEdgePtr anEdge = (*anIt)->edge();
101       if (!anEdge)
102         continue;
103
104       if (anEdge->isCircle()) {
105         GeomCirclePtr aCircle = anEdge->circle();
106         if (aCircle->center()->distance(theCenter) < theTolerance) {
107           theCenterType = (int)ModelAPI_AttributeSelection::CIRCLE_CENTER;
108           return *anIt;
109         }
110       }
111       else if (anEdge->isEllipse()) {
112         GeomEllipsePtr anEllipse = anEdge->ellipse();
113         if (anEllipse->firstFocus()->distance(theCenter) < theTolerance)
114           theCenterType = (int)ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS;
115         else if (anEllipse->secondFocus()->distance(theCenter) < theTolerance)
116           theCenterType = (int)ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS;
117
118         if (theCenterType != (int)ModelAPI_AttributeSelection::NOT_CENTER)
119           return *anIt;
120       }
121     }
122
123     // not found
124     return GeomShapePtr();
125   }
126
127   static void appendSubshapeOfResult(std::list<SubshapeOfResult>& theList,
128       const ResultPtr& theResult,
129       const GeomShapePtr& theSubshape,
130       int theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER)
131   {
132     SubshapeOfResult aSR;
133     aSR.myResult = theResult;
134     aSR.mySubshape = theSubshape;
135     aSR.myCenterType = theCenterType;
136     // compound subshapes from other compounds should be processed as whole results
137     if (aSR.mySubshape && aSR.mySubshape->shapeType() == GeomAPI_Shape::COMPOUND &&
138         !theResult->shape()->isEqual(theSubshape)) {
139       ResultBodyPtr aResult = std::dynamic_pointer_cast<ModelAPI_ResultBody>(theResult);
140       for (int i = 0; aResult && i < aResult->numberOfSubs(); ++i) {
141         ResultBodyPtr aSub = aResult->subResult(i);
142         if (aSub->shape()->isEqual(theSubshape)) {
143           aSR.myResult = aSub;
144           aSR.mySubshape = GeomShapePtr();
145           break;
146         }
147       }
148     }
149     theList.push_back(aSR);
150   }
151
152   static void appendSubshapeOfResult(std::list<SubshapeOfResult>& theList,
153       const ResultPtr& theResult,
154       const std::list<GeomShapePtr>& theSubshape)
155   {
156     for (std::list<GeomShapePtr>::const_iterator anIt = theSubshape.begin();
157          anIt != theSubshape.end(); ++anIt)
158       appendSubshapeOfResult(theList, theResult, *anIt);
159   }
160
161   static bool findSubshapeInCompsolid(const ResultBodyPtr& theCompsolid,
162                                       const std::shared_ptr<GeomAPI_Pnt>& thePoint,
163                                       const GeomAPI_Shape::ShapeType& theShapeType,
164                                       const double theTolerance,
165                                       std::list<SubshapeOfResult>& theSelected)
166   {
167     bool isSubshapeFound = false;
168     int aNbSolids = theCompsolid->numberOfSubs();
169     for (int i = 0; i < aNbSolids; ++i) {
170       ResultPtr aSubResult = theCompsolid->subResult(i);
171
172       // process subs of compsolid
173       ResultBodyPtr aSubCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aSubResult);
174       if (theShapeType != GeomAPI_Shape::COMPSOLID &&
175           aSubCompSolid && aSubCompSolid->numberOfSubs() > 0) {
176         isSubshapeFound = findSubshapeInCompsolid(aSubCompSolid,
177             thePoint, theShapeType, theTolerance, theSelected);
178       }
179       else {
180         GeomShapePtr aSubSolid = aSubResult->shape();
181         if (aSubSolid && isPointWithinBB(thePoint, aSubSolid, theTolerance)) {
182           std::list<GeomShapePtr> aSubshapes =
183               findSubShape(aSubSolid, theShapeType, thePoint, theTolerance);
184           if (!aSubshapes.empty()) {
185             appendSubshapeOfResult(theSelected, aSubResult, aSubshapes);
186             isSubshapeFound = true;
187           }
188         }
189       }
190     }
191     return isSubshapeFound;
192   }
193
194   bool findSubshapeByPoint(const std::shared_ptr<ModelAPI_Feature>& theFeature,
195                            const std::shared_ptr<GeomAPI_Pnt>& thePoint,
196                            const GeomAPI_Shape::ShapeType& theShapeType,
197                            std::list<SubshapeOfResult>& theSelected)
198   {
199     static const double TOLERANCE = 1.e-6;
200
201     theSelected.clear();
202
203     const std::list<ResultPtr>& aResults = theFeature->results();
204     for (std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
205          aResIt != aResults.end(); ++aResIt) {
206       bool isSubshapeFound = false;
207       GeomShapePtr aCurShape = (*aResIt)->shape();
208       // first of all, check the point is within bounding box of the result
209       if (!aCurShape || !isPointWithinBB(thePoint, aCurShape, TOLERANCE))
210         continue;
211       // now, process all sub-shapes of the given type and check their inner points,
212       // but skip the case the selected type is COMPOUND and the shape is a list of sketch edges
213       // (it will be processed later)
214       std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
215           std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aCurShape);
216       if (theShapeType != GeomAPI_Shape::COMPOUND || !aSketchEdges) {
217         ResultBodyPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aResIt);
218         if (aCompSolid) {
219           isSubshapeFound = findSubshapeInCompsolid(aCompSolid,
220               thePoint, theShapeType, TOLERANCE, theSelected);
221         }
222
223         if (!isSubshapeFound) {
224           std::list<GeomShapePtr> aSubshapes =
225               findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
226           if (!aSubshapes.empty()) {
227             appendSubshapeOfResult(theSelected, *aResIt, aSubshapes);
228             isSubshapeFound = true;
229           }
230         }
231       }
232       if (isSubshapeFound)
233         continue;
234
235       // special case for ResultConstruction if the FACE is selected
236       ResultConstructionPtr aResConstr =
237           std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIt);
238       if (aResConstr && theShapeType >= GeomAPI_Shape::FACE) {
239         int aNbFaces = aResConstr->facesNum();
240         for (int aFaceInd = 0; aFaceInd < aNbFaces; ++aFaceInd) {
241           GeomFacePtr aCurFace = aResConstr->face(aFaceInd);
242           // check the point is within bounding box of the face
243           if (!isPointWithinBB(thePoint, aCurFace, TOLERANCE))
244             continue;
245           std::list<GeomShapePtr> aSubshapes =
246               findSubShape(aCurFace, theShapeType, thePoint, TOLERANCE);
247           if (!aSubshapes.empty()) {
248             appendSubshapeOfResult(theSelected, *aResIt, aSubshapes);
249             isSubshapeFound = true;
250           }
251         }
252       }
253       if (isSubshapeFound)
254         continue;
255
256       // next special case: the full sketch is selected
257       // the selection type is a COMPOUND
258       if (aSketchEdges && theShapeType == GeomAPI_Shape::COMPOUND &&
259           aSketchEdges->middlePoint()->distance(thePoint) < TOLERANCE) {
260         // select whole result
261         appendSubshapeOfResult(theSelected, *aResIt, GeomShapePtr());
262         continue;
263       }
264
265       // another special case: the center of circle or the focus of ellipse is selected;
266       // return the corresponding edge and a status of the center
267       if (theShapeType == GeomAPI_Shape::VERTEX) {
268         int aCenterType;
269         GeomShapePtr aSubshape = findEdgeByCenter(aCurShape, thePoint, TOLERANCE, aCenterType);
270         if (aSubshape) {
271           appendSubshapeOfResult(theSelected, *aResIt, aSubshape, aCenterType);
272           continue;
273         }
274       }
275     }
276
277     // one more special case: the selected entity is a separated sketch point
278     // or an auxiliary sketch edge; they are not included into the sketch result;
279     // thus, it is necessary to pass through the sketch sub-features and find selected.
280     if (theSelected.empty() && !aResults.empty() &&
281        (theShapeType == GeomAPI_Shape::VERTEX || theShapeType == GeomAPI_Shape::EDGE)) {
282       CompositeFeaturePtr aCF = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
283       std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
284           std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aResults.front()->shape());
285
286       if (aSketchEdges && aCF) {
287         int aNbSubs = aCF->numberOfSubs();
288         for (int aSubInd = 0; aSubInd < aNbSubs; ++aSubInd) {
289           FeaturePtr aSub = aCF->subFeature(aSubInd);
290           const std::list<ResultPtr>& aSubResults = aSub->results();
291           for (std::list<ResultPtr>::const_iterator aSRIt = aSubResults.begin();
292                aSRIt != aSubResults.end(); ++aSRIt) {
293             GeomShapePtr aCurShape = (*aSRIt)->shape();
294             std::list<GeomShapePtr> aSubshapes =
295                 findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
296             if (!aSubshapes.empty()) {
297               appendSubshapeOfResult(theSelected, aResults.front(), aSubshapes);
298               break;
299             }
300           }
301         }
302       }
303     }
304
305     return !theSelected.empty();
306   }
307 } // namespace ModelGeomAlgo_Shape