Salome HOME
05929ba1c882a6bdee15a686a3b613ef6b409b13
[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_ResultCompSolid.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 GeomShapePtr findSubShape(const GeomShapePtr& theShape,
73                                    const GeomAPI_Shape::ShapeType& theType,
74                                    const GeomPointPtr& thePoint,
75                                    const double theTolerance)
76   {
77     std::list<GeomShapePtr> aSubs = theShape->subShapes(theType);
78     for (std::list<GeomShapePtr>::const_iterator aSubIt = aSubs.begin();
79          aSubIt != aSubs.end(); ++aSubIt) {
80       GeomPointPtr aMiddlePoint = (*aSubIt)->middlePoint();
81       if (aMiddlePoint && aMiddlePoint->distance(thePoint) < theTolerance)
82         return *aSubIt;
83     }
84
85     // not found
86     return GeomShapePtr();
87   }
88
89   // Find circular/elliptical edge, which center/focus coincide with the given point
90   static GeomShapePtr findEdgeByCenter(const GeomShapePtr& theBaseShape,
91                                        const GeomPointPtr& theCenter,
92                                        const double theTolerance,
93                                        int& theCenterType)
94   {
95     theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER;
96     std::list<GeomShapePtr> anEdges = theBaseShape->subShapes(GeomAPI_Shape::EDGE);
97     for (std::list<GeomShapePtr>::const_iterator anIt = anEdges.begin();
98          anIt != anEdges.end(); ++anIt) {
99       GeomEdgePtr anEdge = (*anIt)->edge();
100       if (!anEdge)
101         continue;
102
103       if (anEdge->isCircle()) {
104         GeomCirclePtr aCircle = anEdge->circle();
105         if (aCircle->center()->distance(theCenter) < theTolerance) {
106           theCenterType = (int)ModelAPI_AttributeSelection::CIRCLE_CENTER;
107           return *anIt;
108         }
109       }
110       else if (anEdge->isEllipse()) {
111         GeomEllipsePtr anEllipse = anEdge->ellipse();
112         if (anEllipse->firstFocus()->distance(theCenter) < theTolerance)
113           theCenterType = (int)ModelAPI_AttributeSelection::ELLIPSE_FIRST_FOCUS;
114         else if (anEllipse->secondFocus()->distance(theCenter) < theTolerance)
115           theCenterType = (int)ModelAPI_AttributeSelection::ELLIPSE_SECOND_FOCUS;
116
117         if (theCenterType != (int)ModelAPI_AttributeSelection::NOT_CENTER)
118           return *anIt;
119       }
120     }
121
122     // not found
123     return GeomShapePtr();
124   }
125
126   bool findSubshapeByPoint(const std::shared_ptr<ModelAPI_Feature>& theFeature,
127                            const std::shared_ptr<GeomAPI_Pnt>& thePoint,
128                            const GeomAPI_Shape::ShapeType& theShapeType,
129                            std::shared_ptr<ModelAPI_Result>& theResult,
130                            std::shared_ptr<GeomAPI_Shape>& theSubshape,
131                            int& theCenterType)
132   {
133     static const double TOLERANCE = 1.e-7;
134
135     theResult = ResultPtr();
136     theSubshape = GeomShapePtr();
137     theCenterType = (int)ModelAPI_AttributeSelection::NOT_CENTER;
138
139     const std::list<ResultPtr>& aResults = theFeature->results();
140     for (std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
141          aResIt != aResults.end(); ++aResIt) {
142       GeomShapePtr aCurShape = (*aResIt)->shape();
143       // first of all, check the point is within bounding box of the result
144       if (!aCurShape || !isPointWithinBB(thePoint, aCurShape, TOLERANCE))
145         continue;
146       // now, process all sub-shapes of the given type and check their inner points,
147       // but skip the case the selected type is COMPOUND and the shape is a list of sketch edges
148       // (it will be processed later)
149       std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
150           std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aCurShape);
151       if (theShapeType != GeomAPI_Shape::COMPOUND || !aSketchEdges) {
152         ResultCompSolidPtr aCompSolid =
153             std::dynamic_pointer_cast<ModelAPI_ResultCompSolid>(*aResIt);
154         if (aCompSolid) {
155           // process solids
156           int aNbSolids = aCompSolid->numberOfSubs();
157           for (int i = 0; i < aNbSolids && !theSubshape; ++i) {
158             ResultPtr aSubResult = aCompSolid->subResult(i);
159             GeomShapePtr aSubSolid = aSubResult->shape();
160             if (aSubSolid && isPointWithinBB(thePoint, aSubSolid, TOLERANCE)) {
161               theSubshape = findSubShape(aSubSolid, theShapeType, thePoint, TOLERANCE);
162               if (theSubshape)
163                 theResult = aSubResult;
164             }
165           }
166           if (theSubshape)
167             break;
168         }
169
170         if (!theSubshape)
171           theSubshape = findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
172         if (theSubshape) {
173           theResult = *aResIt;
174           break;
175         }
176       }
177
178       // special case for ResultConstruction if the FACE is selected
179       ResultConstructionPtr aResConstr =
180           std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(*aResIt);
181       if (aResConstr && theShapeType >= GeomAPI_Shape::FACE) {
182         int aNbFaces = aResConstr->facesNum();
183         for (int aFaceInd = 0; aFaceInd < aNbFaces; ++aFaceInd) {
184           GeomFacePtr aCurFace = aResConstr->face(aFaceInd);
185           // check the point is within bounding box of the face
186           if (!isPointWithinBB(thePoint, aCurFace, TOLERANCE))
187             continue;
188           theSubshape = findSubShape(aCurFace, theShapeType, thePoint, TOLERANCE);
189           if (theSubshape) {
190             theResult = *aResIt;
191             break;
192           }
193         }
194       }
195       if (theResult)
196         break;
197
198       // next special case: the full sketch is selected
199       // the selection type is a COMPOUND
200       if (aSketchEdges &&
201           aSketchEdges->middlePoint()->distance(thePoint) < TOLERANCE) {
202         // select whole result
203         theResult = *aResIt;
204         theSubshape = GeomShapePtr();
205         break;
206       }
207
208       // another special case: the center of circle or the focus of ellipse is selected;
209       // return the corresponding edge and a status of the center
210       if (theShapeType == GeomAPI_Shape::VERTEX) {
211         theSubshape = findEdgeByCenter(aCurShape, thePoint, TOLERANCE, theCenterType);
212         if (theSubshape) {
213           theResult = *aResIt;
214           break;
215         }
216       }
217     }
218
219     // one more special case: a vertex selected is a sketch point;
220     // it is not included into sketch result; thus, it is necessary
221     // to pass through the sketch sub-features and verify all points
222     if (!theResult && theShapeType == GeomAPI_Shape::VERTEX && !aResults.empty()) {
223       CompositeFeaturePtr aCF = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(theFeature);
224       std::shared_ptr<GeomAPI_PlanarEdges> aSketchEdges =
225           std::dynamic_pointer_cast<GeomAPI_PlanarEdges>(aResults.front()->shape());
226
227       if (aSketchEdges && aCF) {
228         bool isContinue = true;
229         int aNbSubs = aCF->numberOfSubs();
230         for (int aSubInd = 0; aSubInd < aNbSubs && isContinue; ++aSubInd) {
231           FeaturePtr aSub = aCF->subFeature(aSubInd);
232           const std::list<ResultPtr>& aSubResults = aSub->results();
233           for (std::list<ResultPtr>::const_iterator aSRIt = aSubResults.begin();
234                aSRIt != aSubResults.end(); ++aSRIt) {
235             GeomShapePtr aCurShape = (*aSRIt)->shape();
236             theSubshape = findSubShape(aCurShape, theShapeType, thePoint, TOLERANCE);
237             if (theSubshape) {
238               theResult = aResults.front();
239               isContinue = false;
240               break;
241             }
242           }
243         }
244       }
245     }
246
247     return (bool)theResult;
248   }
249 } // namespace ModelGeomAlgo_Shape