]> SALOME platform Git repositories - modules/shaper.git/blob - src/ModelGeomAlgo/ModelGeomAlgo_Shape.cpp
Salome HOME
Merge remote-tracking branch 'remotes/origin/master' into DumpWithGeom
[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   static bool findSubshapeInCompsolid(const ResultBodyPtr& theCompsolid,
152                                       const std::shared_ptr<GeomAPI_Pnt>& thePoint,
153                                       const GeomAPI_Shape::ShapeType& theShapeType,
154                                       const double theTolerance,
155                                       std::list<SubshapeOfResult>& theSelected)
156   {
157     bool isSubshapeFound = false;
158     int aNbSolids = theCompsolid->numberOfSubs();
159     for (int i = 0; i < aNbSolids; ++i) {
160       ResultPtr aSubResult = theCompsolid->subResult(i);
161
162       // process subs of compsolid
163       ResultBodyPtr aSubCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(aSubResult);
164       if (aSubCompSolid && aSubCompSolid->numberOfSubs() > 0) {
165         isSubshapeFound = findSubshapeInCompsolid(aSubCompSolid,
166             thePoint, theShapeType, theTolerance, theSelected);
167       }
168       else {
169         GeomShapePtr aSubSolid = aSubResult->shape();
170         if (aSubSolid && isPointWithinBB(thePoint, aSubSolid, theTolerance)) {
171           std::list<GeomShapePtr> aSubshapes =
172               findSubShape(aSubSolid, theShapeType, thePoint, theTolerance);
173           if (!aSubshapes.empty()) {
174             appendSubshapeOfResult(theSelected, aSubResult, aSubshapes);
175             isSubshapeFound = true;
176           }
177         }
178       }
179     }
180     return isSubshapeFound;
181   }
182
183   bool findSubshapeByPoint(const std::shared_ptr<ModelAPI_Feature>& theFeature,
184                            const std::shared_ptr<GeomAPI_Pnt>& thePoint,
185                            const GeomAPI_Shape::ShapeType& theShapeType,
186                            std::list<SubshapeOfResult>& theSelected)
187   {
188     static const double TOLERANCE = 1.e-6;
189
190     theSelected.clear();
191
192     const std::list<ResultPtr>& aResults = theFeature->results();
193     for (std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
194          aResIt != aResults.end(); ++aResIt) {
195       bool isSubshapeFound = false;
196       GeomShapePtr aCurShape = (*aResIt)->shape();
197       // first of all, check the point is within bounding box of the result
198       if (!aCurShape || !isPointWithinBB(thePoint, aCurShape, TOLERANCE))
199         continue;
200       // now, process all sub-shapes of the given type and check their inner points,
201       // but skip the case the selected type is COMPOUND and the shape is a list of sketch edges
202       // (it will be processed later)
203       std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
204           std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aCurShape);
205       if (theShapeType != GeomAPI_Shape::COMPOUND || !aSketchEdges) {
206         ResultBodyPtr aCompSolid = std::dynamic_pointer_cast<ModelAPI_ResultBody>(*aResIt);
207         if (aCompSolid) {
208           isSubshapeFound = findSubshapeInCompsolid(aCompSolid,
209               thePoint, theShapeType, TOLERANCE, theSelected);
210         }
211
212         if (!isSubshapeFound) {
213           std::list<GeomShapePtr> aSubshapes =
214               findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
215           if (!aSubshapes.empty()) {
216             appendSubshapeOfResult(theSelected, *aResIt, aSubshapes);
217             isSubshapeFound = true;
218           }
219         }
220       }
221       if (isSubshapeFound)
222         continue;
223
224       // special case for ResultConstruction if the FACE is selected
225       ResultConstructionPtr aResConstr =
226           std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIt);
227       if (aResConstr && theShapeType >= GeomAPI_Shape::FACE) {
228         int aNbFaces = aResConstr->facesNum();
229         for (int aFaceInd = 0; aFaceInd < aNbFaces; ++aFaceInd) {
230           GeomFacePtr aCurFace = aResConstr->face(aFaceInd);
231           // check the point is within bounding box of the face
232           if (!isPointWithinBB(thePoint, aCurFace, TOLERANCE))
233             continue;
234           std::list<GeomShapePtr> aSubshapes =
235               findSubShape(aCurFace, theShapeType, thePoint, TOLERANCE);
236           if (!aSubshapes.empty()) {
237             appendSubshapeOfResult(theSelected, *aResIt, aSubshapes);
238             isSubshapeFound = true;
239           }
240         }
241       }
242       if (isSubshapeFound)
243         continue;
244
245       // next special case: the full sketch is selected
246       // the selection type is a COMPOUND
247       if (aSketchEdges && theShapeType == GeomAPI_Shape::COMPOUND &&
248           aSketchEdges->middlePoint()->distance(thePoint) < TOLERANCE) {
249         // select whole result
250         appendSubshapeOfResult(theSelected, *aResIt, GeomShapePtr());
251         continue;
252       }
253
254       // another special case: the center of circle or the focus of ellipse is selected;
255       // return the corresponding edge and a status of the center
256       if (theShapeType == GeomAPI_Shape::VERTEX) {
257         int aCenterType;
258         GeomShapePtr aSubshape = findEdgeByCenter(aCurShape, thePoint, TOLERANCE, aCenterType);
259         if (aSubshape) {
260           appendSubshapeOfResult(theSelected, *aResIt, aSubshape, aCenterType);
261           continue;
262         }
263       }
264     }
265
266     // one more special case: the selected entity is a separated sketch point
267     // or an auxiliary sketch edge; they are not included into the sketch result;
268     // thus, it is necessary to pass through the sketch sub-features and find selected.
269     if (theSelected.empty() && !aResults.empty() &&
270        (theShapeType == GeomAPI_Shape::VERTEX || theShapeType == GeomAPI_Shape::EDGE)) {
271       CompositeFeaturePtr aCF = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
272       std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
273           std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aResults.front()->shape());
274
275       if (aSketchEdges && aCF) {
276         int aNbSubs = aCF->numberOfSubs();
277         for (int aSubInd = 0; aSubInd < aNbSubs; ++aSubInd) {
278           FeaturePtr aSub = aCF->subFeature(aSubInd);
279           const std::list<ResultPtr>& aSubResults = aSub->results();
280           for (std::list<ResultPtr>::const_iterator aSRIt = aSubResults.begin();
281                aSRIt != aSubResults.end(); ++aSRIt) {
282             GeomShapePtr aCurShape = (*aSRIt)->shape();
283             std::list<GeomShapePtr> aSubshapes =
284                 findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
285             if (!aSubshapes.empty()) {
286               appendSubshapeOfResult(theSelected, aResults.front(), aSubshapes);
287               break;
288             }
289           }
290         }
291       }
292     }
293
294     return !theSelected.empty();
295   }
296 } // namespace ModelGeomAlgo_Shape