]> SALOME platform Git repositories - modules/shaper.git/blob - src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp
Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_Revolution.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 email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
18 //
19
20 #include "GeomAlgoAPI_Revolution.h"
21
22 #include <GeomAPI_Face.h>
23 #include <GeomAPI_Pln.h>
24 #include <GeomAPI_ShapeExplorer.h>
25 #include <GeomAlgoAPI_DFLoader.h>
26 #include <GeomAlgoAPI_FaceBuilder.h>
27 #include <GeomAlgoAPI_MakeShapeList.h>
28 #include <GeomAlgoAPI_ShapeTools.h>
29
30 #include <BRep_Builder.hxx>
31 #include <BRep_Tool.hxx>
32 #include <BRepAlgoAPI_Cut.hxx>
33 #include <BRepBuilderAPI_FindPlane.hxx>
34 #include <BRepBuilderAPI_MakeFace.hxx>
35 #include <BRepBuilderAPI_Transform.hxx>
36 #include <BRepCheck_Analyzer.hxx>
37 #include <Geom_Curve.hxx>
38 #include <Geom2d_Curve.hxx>
39 #include <BRepLib_CheckCurveOnSurface.hxx>
40 #include <BRepPrimAPI_MakeRevol.hxx>
41 #include <BRepGProp.hxx>
42 #include <GC_MakePlane.hxx>
43 #include <Geom_Plane.hxx>
44 #include <GeomLib_IsPlanarSurface.hxx>
45 #include <gp_Pln.hxx>
46 #include <GProp_GProps.hxx>
47 #include <IntTools_Context.hxx>
48 #include <TopExp_Explorer.hxx>
49 #include <TopoDS.hxx>
50 #include <TopoDS_Edge.hxx>
51 #include <TopTools_ListIteratorOfListOfShape.hxx>
52
53 /// \brief Constructs infinite face from thePlane, and with axis located on the same side
54 /// of the plane as thePoint. Modifies thePlane axis direction.
55 /// \param[in,out] thePlane plane to construct face.
56 /// \param[in] thePoint point to locate plane axis.
57 /// \return constructed face.
58 static TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint);
59
60 /// \return solid created from face or shell.
61 static TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape);
62
63 /// \brief return centre of mass for theShape.
64 /// \param[in] theShape shape.
65 static gp_Pnt centreOfMass(const TopoDS_Shape& theShape);
66
67 /// \brief Selects solid from theShape with closest center of mass to thePoint
68 /// \param[in] theShape compound with solids.
69 /// \param[in] thePoint point.
70 /// \return solid.
71 static TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint);
72
73 static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
74                                    const TopoDS_Shape& theBase,
75                                    const TopAbs_ShapeEnum theType,
76                                    BRepPrimAPI_MakeRevol* theRevolBuilder);
77
78 static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
79                                    const TopoDS_Shape& theResult,
80                                    const TopAbs_ShapeEnum theType,
81                                    const TopoDS_Shape& theToFace,
82                                    const TopoDS_Shape& theFromFace);
83
84 static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
85                                    const TopoDS_Shape& theResult,
86                                    const TopAbs_ShapeEnum theType,
87                                    const TopoDS_Shape& theRotatedBoundingFace,
88                                    const TopoDS_Shape& theModifiedBaseShape,
89                                    const bool theIsFromFaceSet);
90
91 //==================================================================================================
92 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr                 theBaseShape,
93                                                const std::shared_ptr<GeomAPI_Ax1> theAxis,
94                                                const double                       theToAngle,
95                                                const double                       theFromAngle)
96 {
97   build(theBaseShape, theAxis, GeomShapePtr(), theToAngle, GeomShapePtr(), theFromAngle);
98 }
99
100 //==================================================================================================
101 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr                 theBaseShape,
102                                                const std::shared_ptr<GeomAPI_Ax1> theAxis,
103                                                const GeomShapePtr                 theToShape,
104                                                const double                       theToAngle,
105                                                const GeomShapePtr                 theFromShape,
106                                                const double                       theFromAngle)
107 {
108   build(theBaseShape, theAxis, theToShape, theToAngle, theFromShape, theFromAngle);
109 }
110
111 //==================================================================================================
112 void GeomAlgoAPI_Revolution::build(const GeomShapePtr&                 theBaseShape,
113                                    const std::shared_ptr<GeomAPI_Ax1>& theAxis,
114                                    const GeomShapePtr&                 theToShape,
115                                    const double                        theToAngle,
116                                    const GeomShapePtr&                 theFromShape,
117                                    const double                        theFromAngle)
118 {
119   if(!theBaseShape || !theAxis ||
120     (((!theFromShape && !theToShape) ||
121     (theFromShape && theToShape && theFromShape->isEqual(theToShape)))
122     && (theFromAngle == -theToAngle))) {
123     return;
124   }
125
126   // Getting base shape.
127   const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
128   TopAbs_ShapeEnum aShapeTypeToExp;
129   switch(aBaseShape.ShapeType()) {
130     case TopAbs_VERTEX:
131       aShapeTypeToExp = TopAbs_VERTEX;
132       break;
133     case TopAbs_EDGE:
134     case TopAbs_WIRE:
135       aShapeTypeToExp = TopAbs_EDGE;
136       break;
137     case TopAbs_FACE:
138     case TopAbs_SHELL:
139       aShapeTypeToExp = TopAbs_FACE;
140       break;
141     case TopAbs_COMPOUND:
142       aShapeTypeToExp = TopAbs_COMPOUND;
143       break;
144     default:
145       return;
146   }
147
148   // Getting axis.
149   gp_Ax1 anAxis = theAxis->impl<gp_Ax1>();
150
151   // Getting base plane.
152   Handle(Geom_Plane) aBasePlane;
153   BRepBuilderAPI_FindPlane aFindPlane(aBaseShape);
154   if(aShapeTypeToExp == TopAbs_FACE && aFindPlane.Found() == Standard_True) {
155     aBasePlane = aFindPlane.Plane();
156   } else {
157     gp_Pnt aPnt1 = anAxis.Location();
158     gp_Pnt aPnt2 = aPnt1;
159     aPnt2.Translate(anAxis.Direction());
160     gp_Pnt aPnt3;
161
162     for(TopExp_Explorer anExp(aBaseShape, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
163       aPnt3 = BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current()));
164
165       GC_MakePlane aMkPlane(aPnt1, aPnt2, aPnt3);
166       if(aMkPlane.IsDone() != Standard_True) {
167         continue;
168       }
169
170       aBasePlane = aMkPlane.Value();
171       break;
172     }
173
174     if(aBasePlane.IsNull()) {
175       aPnt3 = centreOfMass(aBaseShape);
176
177       GC_MakePlane aMkPlane(aPnt1, aPnt2, aPnt3);
178       if(aMkPlane.IsDone() != Standard_True) {
179         return;
180       }
181
182       aBasePlane = aMkPlane.Value();
183     }
184   }
185
186   if(aShapeTypeToExp == TopAbs_FACE) {
187     if(aBasePlane->Axis().Angle(anAxis) < Precision::Confusion()) {
188       return;
189     }
190   }
191
192   gp_Pnt aBaseCentre = GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape)->impl<gp_Pnt>();
193
194   TopoDS_Shape aResult;
195   if(!theFromShape && !theToShape) { // Case 1: When only angles was set.
196     // Rotating base face with the negative value of "from angle".
197     gp_Trsf aBaseTrsf;
198     aBaseTrsf.SetRotation(anAxis, -theFromAngle / 180.0 * M_PI);
199     BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBaseShape,
200                                                                             aBaseTrsf,
201                                                                             true);
202     if(!aBaseTransform) {
203       return;
204     }
205     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
206       new GeomAlgoAPI_MakeShape(aBaseTransform)));
207     if(!aBaseTransform->IsDone()) {
208       return;
209     }
210     TopoDS_Shape aRotatedBase = aBaseTransform->Shape();
211
212     // Making revolution to the angle equal to the sum of "from angle" and "to angle".
213     BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aRotatedBase,
214                                                         anAxis,
215                                                         (theFromAngle + theToAngle) / 180 * M_PI,
216                                                         Standard_True);
217     if(!aRevolBuilder) {
218       return;
219     }
220     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
221       new GeomAlgoAPI_MakeShape(aRevolBuilder)));
222     if(!aRevolBuilder->IsDone()) {
223       return;
224     }
225     aResult = aRevolBuilder->Shape();
226
227     // Setting naming.
228     if(aShapeTypeToExp == TopAbs_COMPOUND) {
229       storeGenerationHistory(this, aRotatedBase, TopAbs_EDGE, aRevolBuilder);
230       storeGenerationHistory(this, aRotatedBase, TopAbs_FACE, aRevolBuilder);
231     } else {
232       storeGenerationHistory(this, aRotatedBase, aShapeTypeToExp, aRevolBuilder);
233     }
234   } else if(theFromShape && theToShape) { // Case 2: When both bounding planes were set.
235     // Making revolution to the 360 angle.
236     BRepPrimAPI_MakeRevol* aRevolBuilder =
237       new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
238     if(!aRevolBuilder) {
239       return;
240     }
241     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
242       new GeomAlgoAPI_MakeShape(aRevolBuilder)));
243     if(!aRevolBuilder->IsDone()) {
244       return;
245     }
246     aResult = aRevolBuilder->Shape();
247
248     // Getting bounding faces.
249     TopoDS_Face aFromFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
250     TopoDS_Face aToFace   = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
251
252     // Getting planes from bounding face.
253     GeomLib_IsPlanarSurface isFromPlanar(BRep_Tool::Surface(aFromFace));
254     GeomLib_IsPlanarSurface isToPlanar(BRep_Tool::Surface(aToFace));
255     if(!isFromPlanar.IsPlanar() || !isToPlanar.IsPlanar()) {
256       // non-planar shapes is not supported for revolution bounding
257       return;
258     }
259
260     std::shared_ptr<GeomAPI_Face> aGeomFromFace(new GeomAPI_Face(theFromShape));
261     std::shared_ptr<GeomAPI_Face> aGeomToFace(new GeomAPI_Face(theToShape));
262
263     gp_Pln aFromPln = aGeomFromFace->getPlane()->impl<gp_Pln>();
264     gp_Pln aToPln   = aGeomToFace->getPlane()->impl<gp_Pln>();
265
266     // Orienting bounding planes properly so that the center of mass of the base face stays
267     // on the result shape after cut.
268     aFromFace = makeFaceFromPlane(aFromPln, aBaseCentre);
269     aToFace   = makeFaceFromPlane(aToPln, aBaseCentre);
270
271     // Making solids from bounding planes and putting them in compound.
272     TopoDS_Shape aFromSolid = makeSolidFromShape(aFromFace);
273     TopoDS_Shape aToSolid   = makeSolidFromShape(aToFace);
274
275     // Rotating bounding planes to the specified angle.
276     gp_Trsf aFromTrsf;
277     gp_Trsf aToTrsf;
278     double aFromRotAngle =
279       ((aFromPln.Axis().Direction() * aBasePlane->Axis().Direction()) > 0) ? -theFromAngle :
280                                                                               theFromAngle;
281     double aToRotAngle =
282       ((aToPln.Axis().Direction() * aBasePlane->Axis().Direction()) > 0) ? -theToAngle :
283                                                                             theToAngle;
284     aFromTrsf.SetRotation(anAxis,aFromRotAngle / 180.0 * M_PI);
285     aToTrsf.SetRotation(anAxis, aToRotAngle / 180.0 * M_PI);
286     BRepBuilderAPI_Transform aFromTransform(aFromSolid, aFromTrsf, true);
287     BRepBuilderAPI_Transform aToTransform(aToSolid, aToTrsf, true);
288     TopoDS_Shape aRotatedFromFace = aFromTransform.Modified(aFromFace).First();
289     TopoDS_Shape aRotatedToFace = aToTransform.Modified(aToFace).First();
290     aFromSolid = aFromTransform.Shape();
291     aToSolid = aToTransform.Shape();
292
293     // Cutting revolution with from plane.
294     BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
295     aFromCutBuilder->Build();
296     if(!aFromCutBuilder->IsDone()) {
297       return;
298     }
299     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
300       new GeomAlgoAPI_MakeShape(aFromCutBuilder)));
301     aResult = aFromCutBuilder->Shape();
302     if(aResult.ShapeType() == TopAbs_COMPOUND) {
303       aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
304     }
305
306     // Cutting revolution with to plane.
307     BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
308     aToCutBuilder->Build();
309     if(!aToCutBuilder->IsDone()) {
310       return;
311     }
312     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
313       new GeomAlgoAPI_MakeShape(aToCutBuilder)));
314     aResult = aToCutBuilder->Shape();
315     TopoDS_Iterator aCheckIt(aResult);
316     if(!aCheckIt.More()) {
317       return;
318     }
319     if(aResult.ShapeType() == TopAbs_COMPOUND) {
320       aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
321     }
322     if(aResult.ShapeType() == TopAbs_COMPOUND) {
323       std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
324       aGeomShape->setImpl(new TopoDS_Shape(aResult));
325       ListOfShape aCompSolids, aFreeSolids;
326       aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
327                                                          GeomAPI_Shape::COMPSOLID,
328                                                          aCompSolids,
329                                                          aFreeSolids);
330       aResult = aGeomShape->impl<TopoDS_Shape>();
331     }
332
333     // If after cut we got more than one solids then take closest
334     // to the center of mass of the base face.
335     aResult = findClosest(aResult, aBaseCentre);
336
337     // Setting naming.
338     if(aShapeTypeToExp == TopAbs_COMPOUND) {
339       storeGenerationHistory(this, aResult, TopAbs_EDGE, aRotatedToFace, aRotatedFromFace);
340       storeGenerationHistory(this, aResult, TopAbs_FACE, aRotatedToFace, aRotatedFromFace);
341     } else {
342       storeGenerationHistory(this, aResult, aShapeTypeToExp, aRotatedToFace, aRotatedFromFace);
343     }
344   } else { //Case 3: When only one bounding plane was set.
345     // Making revolution to the 360 angle.
346     BRepPrimAPI_MakeRevol* aRevolBuilder =
347       new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
348     if(!aRevolBuilder) {
349       return;
350     }
351     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
352       new GeomAlgoAPI_MakeShape(aRevolBuilder)));
353     if(!aRevolBuilder->IsDone()) {
354       return;
355     }
356     aResult = aRevolBuilder->Shape();
357
358     // Getting bounding face.
359     bool isFromFaceSet = false;
360     std::shared_ptr<GeomAPI_Face> aGeomBoundingFace;
361     if(theFromShape) {
362       aGeomBoundingFace.reset(new GeomAPI_Face(theFromShape));
363       isFromFaceSet = true;
364     } else if(theToShape) {
365       aGeomBoundingFace.reset(new GeomAPI_Face(theToShape));
366     }
367     TopoDS_Face aBoundingFace = TopoDS::Face(aGeomBoundingFace->impl<TopoDS_Shape>());
368
369     // Getting plane from bounding face.
370     GeomLib_IsPlanarSurface isBoundingPlanar(BRep_Tool::Surface(aBoundingFace));
371     if(!isBoundingPlanar.IsPlanar()) { // non-planar shapes is not supported for revolution bounding
372       return;
373     }
374
375     gp_Pln aBoundingPln = aGeomBoundingFace->getPlane()->impl<gp_Pln>();
376
377     // Orienting bounding plane properly so that the center of mass of the base face stays
378     // on the result shape after cut.
379     aBoundingFace = makeFaceFromPlane(aBoundingPln, aBaseCentre);
380
381     // Making solid from bounding plane.
382     TopoDS_Shape aBoundingSolid = makeSolidFromShape(aBoundingFace);
383
384     // Rotating bounding plane to the specified angle.
385     double aBoundingRotAngle = isFromFaceSet ? theFromAngle : theToAngle;
386     if(aBoundingPln.Axis().IsParallel(aBasePlane->Axis(), Precision::Confusion())) {
387       if(isFromFaceSet) aBoundingRotAngle = -aBoundingRotAngle;
388     } else {
389       double aSign = (aBoundingPln.Axis().Direction() ^ aBasePlane->Axis().Direction()) *
390                      anAxis.Direction();
391       if((aSign <= 0 && !isFromFaceSet) || (aSign > 0 && isFromFaceSet)) {
392         aBoundingRotAngle = -aBoundingRotAngle;
393       }
394     }
395     gp_Trsf aBoundingTrsf;
396     aBoundingTrsf.SetRotation(anAxis, aBoundingRotAngle / 180.0 * M_PI);
397     BRepBuilderAPI_Transform aBoundingTransform(aBoundingSolid, aBoundingTrsf, true);
398     TopoDS_Shape aRotatedBoundingFace = aBoundingTransform.Modified(aBoundingFace).First();
399     aBoundingSolid = aBoundingTransform.Shape();
400
401     // Cutting revolution with bounding plane.
402     BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aResult, aBoundingSolid);
403     aBoundingCutBuilder->Build();
404     if(!aBoundingCutBuilder->IsDone()) {
405       return;
406     }
407     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
408       new GeomAlgoAPI_MakeShape(aBoundingCutBuilder)));
409     aResult = aBoundingCutBuilder->Shape();
410     if(aResult.ShapeType() == TopAbs_COMPOUND) {
411       aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
412     }
413
414     // Setting naming.
415     if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
416       const TopTools_ListOfShape& aBndShapes = aBoundingCutBuilder->Modified(aBoundingFace);
417       for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) {
418         GeomShapePtr aShape(new GeomAPI_Shape());
419         aShape->setImpl(new TopoDS_Shape(anIt.Value()));
420         isFromFaceSet ? this->addFromShape(aShape) : this->addToShape(aShape);
421       }
422     }
423
424     // Try to cut with base face. If it can not be done then keep result of cut with bounding plane.
425     TopoDS_Shape aModifiedBaseShape;
426     if(aShapeTypeToExp != TopAbs_FACE) {
427       ListOfShape aList;
428       GeomShapePtr aSh(new GeomAPI_Shape());
429       aSh->setImpl(new TopoDS_Shape(aBaseShape));
430       std::shared_ptr<GeomAPI_Pnt> theCenter(new GeomAPI_Pnt(aBasePlane->Location().X(),
431                                                              aBasePlane->Location().Y(),
432                                                              aBasePlane->Location().Z()));
433       std::shared_ptr<GeomAPI_Dir> theNormal(new GeomAPI_Dir(aBasePlane->Axis().Direction().X(),
434                                                              aBasePlane->Axis().Direction().Y(),
435                                                              aBasePlane->Axis().Direction().Z()));
436       GeomShapePtr aPln = GeomAlgoAPI_FaceBuilder::planarFace(theCenter, theNormal);
437       aList.push_back(aSh);
438       std::list<std::shared_ptr<GeomAPI_Pnt> >
439         aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(aList);
440       aSh = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPln, aBoundingPoints);
441       aModifiedBaseShape = aSh->impl<TopoDS_Shape>();
442     } else {
443       aModifiedBaseShape = aBaseShape;
444     }
445     if(isFromFaceSet) {
446       if(aModifiedBaseShape.ShapeType() == TopAbs_FACE) {
447         aModifiedBaseShape.Orientation(TopAbs_REVERSED);
448       } else {
449         gp_Trsf aMirrorTrsf;
450         aMirrorTrsf.SetMirror(aBasePlane->Position().Ax2());
451         BRepBuilderAPI_Transform aMirrorTransform(aModifiedBaseShape, aMirrorTrsf, true);
452         aModifiedBaseShape = aMirrorTransform.Shape();
453       }
454     }
455
456     // Making solid from base face.
457     TopoDS_Shape aBaseSolid = makeSolidFromShape(aModifiedBaseShape);
458
459     // Rotating base face to the specified angle.
460     gp_Trsf aBaseTrsf;
461     double aBaseRotAngle = isFromFaceSet ? theToAngle : -theFromAngle;
462     aBaseTrsf.SetRotation(anAxis, aBaseRotAngle / 180.0 * M_PI);
463     BRepBuilderAPI_Transform aBaseTransform(aBaseSolid, aBaseTrsf, true);
464     aBaseSolid = aBaseTransform.Shape();
465
466     // Cutting revolution with base.
467     BRepAlgoAPI_Cut* aBaseCutBuilder = new BRepAlgoAPI_Cut(aResult, aBaseSolid);
468     aBaseCutBuilder->Build();
469     if(aBaseCutBuilder->IsDone()) {
470       TopoDS_Shape aCutResult = aBaseCutBuilder->Shape();
471       TopoDS_Iterator aCheckIt(aCutResult);
472       if(aCheckIt.More()) {
473         this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(
474           new GeomAlgoAPI_MakeShape(aBaseCutBuilder)));
475         aResult = aCutResult;
476         if(aResult.ShapeType() == TopAbs_COMPOUND) {
477           aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
478         }
479         if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
480           const TopTools_ListOfShape& aBsShapes = aBaseCutBuilder->Modified(aBoundingFace);
481           for(TopTools_ListIteratorOfListOfShape anIt(aBsShapes); anIt.More(); anIt.Next()) {
482             GeomShapePtr aShape(new GeomAPI_Shape());
483             aShape->setImpl(new TopoDS_Shape(anIt.Value()));
484             isFromFaceSet ? this->addToShape(aShape) : this->addFromShape(aShape);
485           }
486         }
487       }
488     }
489
490     if(aResult.ShapeType() == TopAbs_COMPOUND) {
491       std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
492       aGeomShape->setImpl(new TopoDS_Shape(aResult));
493       ListOfShape aCompSolids, aFreeSolids;
494       aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
495                                                          GeomAPI_Shape::COMPSOLID,
496                                                          aCompSolids,
497                                                          aFreeSolids);
498       aResult = aGeomShape->impl<TopoDS_Shape>();
499     }
500
501     // If after cut we got more than one solids then take
502     // closest to the center of mass of the base face.
503     aResult = findClosest(aResult, aBaseCentre);
504
505     // Setting naming.
506     if(aShapeTypeToExp == TopAbs_COMPOUND) {
507       storeGenerationHistory(this, aResult, TopAbs_EDGE,
508         aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
509       storeGenerationHistory(this, aResult, TopAbs_FACE,
510         aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
511     } else {
512       storeGenerationHistory(this, aResult, aShapeTypeToExp,
513         aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
514     }
515   }
516
517   // Setting result.
518   if(aResult.IsNull()) {
519     return;
520   }
521   aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
522   GeomShapePtr aShape(new GeomAPI_Shape());
523   aShape->setImpl(new TopoDS_Shape(aResult));
524   this->setShape(aShape);
525   this->setDone(true);
526 }
527
528 //==================================================================================================
529 TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
530 {
531   if(!thePlane.Contains(thePoint, Precision::Confusion())) {
532     gp_XYZ aVec = thePoint.XYZ() - thePlane.Location().XYZ();
533     double aSign = aVec * thePlane.Axis().Direction().XYZ();
534     if(aSign < 0) thePlane.SetAxis(thePlane.Axis().Reversed());
535   }
536
537   BRepBuilderAPI_MakeFace aMakeFace(thePlane);
538   TopoDS_Face aResultFace = TopoDS::Face(aMakeFace.Shape());
539
540   return aResultFace;
541 }
542
543 //==================================================================================================
544 TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape)
545 {
546   TopoDS_Shell aShell;
547   TopoDS_Solid aSolid;
548
549   BRep_Builder aBoundingBuilder;
550   if(theShape.ShapeType() == TopAbs_SHELL) {
551     aShell = TopoDS::Shell(theShape);
552   } else {
553     aBoundingBuilder.MakeShell(aShell);
554     aBoundingBuilder.Add(aShell, theShape);
555   }
556   aBoundingBuilder.MakeSolid(aSolid);
557   aBoundingBuilder.Add(aSolid, aShell);
558
559   return aSolid;
560 }
561
562 //================================================================================================
563 gp_Pnt centreOfMass(const TopoDS_Shape& theShape)
564 {
565   TopAbs_ShapeEnum aShType = theShape.ShapeType();
566   GProp_GProps aGProps;
567
568   if(aShType == TopAbs_EDGE || aShType == TopAbs_WIRE) {
569     BRepGProp::LinearProperties(theShape, aGProps);
570   } else if(aShType == TopAbs_FACE || aShType == TopAbs_SHELL) {
571     BRepGProp::SurfaceProperties(theShape, aGProps);
572   } else if(aShType == TopAbs_SOLID || aShType == TopAbs_COMPSOLID) {
573     BRepGProp::VolumeProperties(theShape, aGProps);
574   }
575
576   return aGProps.CentreOfMass();
577 }
578
579 //================================================================================================
580 TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
581 {
582   TopoDS_Shape aResult = theShape;
583
584   if(theShape.ShapeType() == TopAbs_COMPOUND) {
585     double aMinDistance = Precision::Infinite();
586     double aCurDistance;
587     gp_Pnt aCentr;
588     for (TopoDS_Iterator anItr(theShape); anItr.More(); anItr.Next()) {
589       TopoDS_Shape aValue = anItr.Value();
590       aCentr = centreOfMass(aValue);
591       aCurDistance = aCentr.Distance(thePoint);
592
593       if(aCurDistance < aMinDistance) {
594         aMinDistance = aCurDistance;
595         aResult = aValue;
596       }
597     }
598   }
599
600   return aResult;
601 }
602
603 //================================================================================================
604 void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
605                             const TopoDS_Shape& theBase,
606                             const TopAbs_ShapeEnum theType,
607                             BRepPrimAPI_MakeRevol* theRevolBuilder)
608 {
609   for(TopExp_Explorer anExp(theBase, theType); anExp.More(); anExp.Next()) {
610     const TopoDS_Shape& aShape = anExp.Current();
611     GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
612     aFromShape->setImpl(new TopoDS_Shape(theRevolBuilder->FirstShape(aShape)));
613     aToShape->setImpl(new TopoDS_Shape(theRevolBuilder->LastShape(aShape)));
614     theRevolutionAlgo->addFromShape(aFromShape);
615     theRevolutionAlgo->addToShape(aToShape);
616   }
617 }
618
619 //================================================================================================
620 void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
621                             const TopoDS_Shape& theResult,
622                             const TopAbs_ShapeEnum theType,
623                             const TopoDS_Shape& theToFace,
624                             const TopoDS_Shape& theFromFace)
625 {
626   for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
627     const TopoDS_Shape& aShape = anExp.Current();
628     GeomShapePtr aGeomSh(new GeomAPI_Shape());
629     if(theType == TopAbs_VERTEX) {
630       gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
631       IntTools_Context anIntTools;
632       if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theToFace),
633           Precision::Confusion()) == Standard_True) {
634         aGeomSh->setImpl(new TopoDS_Shape(aShape));
635         theRevolutionAlgo->addToShape(aGeomSh);
636       }
637       if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theFromFace),
638           Precision::Confusion()) == Standard_True) {
639         aGeomSh->setImpl(new TopoDS_Shape(aShape));
640         theRevolutionAlgo->addFromShape(aGeomSh);
641       }
642     } else if(theType == TopAbs_EDGE) {
643       TopoDS_Edge anEdge = TopoDS::Edge(aShape);
644       BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theToFace));
645       anEdgeCheck.Perform();
646       if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
647         aGeomSh->setImpl(new TopoDS_Shape(aShape));
648         theRevolutionAlgo->addToShape(aGeomSh);
649       }
650       anEdgeCheck.Init(anEdge, TopoDS::Face(theFromFace));
651       anEdgeCheck.Perform();
652       if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
653         aGeomSh->setImpl(new TopoDS_Shape(aShape));
654         theRevolutionAlgo->addFromShape(aGeomSh);
655       }
656     } else {
657       Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
658       Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(theFromFace));
659       Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(theToFace));
660       if(aFaceSurface == aFromSurface) {
661         aGeomSh->setImpl(new TopoDS_Shape(aShape));
662         theRevolutionAlgo->addFromShape(aGeomSh);
663       }
664       if(aFaceSurface == aToSurface) {
665         aGeomSh->setImpl(new TopoDS_Shape(aShape));
666         theRevolutionAlgo->addToShape(aGeomSh);
667       }
668     }
669   }
670 }
671
672 void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
673                             const TopoDS_Shape& theResult,
674                             const TopAbs_ShapeEnum theType,
675                             const TopoDS_Shape& theRotatedBoundingFace,
676                             const TopoDS_Shape& theModifiedBaseShape,
677                             const bool theIsFromFaceSet)
678 {
679   for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
680     const TopoDS_Shape& aShape = anExp.Current();
681     GeomShapePtr aGeomSh(new GeomAPI_Shape());
682     if(theType == TopAbs_VERTEX) {
683       gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
684       IntTools_Context anIntTools;
685       if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theRotatedBoundingFace),
686           Precision::Confusion()) == Standard_True) {
687         aGeomSh->setImpl(new TopoDS_Shape(aShape));
688         theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) :
689                            theRevolutionAlgo->addToShape(aGeomSh);
690       }
691       if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theModifiedBaseShape),
692          Precision::Confusion()) == Standard_True) {
693         aGeomSh->setImpl(new TopoDS_Shape(aShape));
694         theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) :
695                            theRevolutionAlgo->addFromShape(aGeomSh);
696       }
697     } else if(theType == TopAbs_EDGE) {
698       TopoDS_Edge anEdge = TopoDS::Edge(aShape);
699       BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theRotatedBoundingFace));
700       anEdgeCheck.Perform();
701       if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
702         aGeomSh->setImpl(new TopoDS_Shape(aShape));
703         theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) :
704                            theRevolutionAlgo->addToShape(aGeomSh);
705       }
706       anEdgeCheck.Init(anEdge, TopoDS::Face(theModifiedBaseShape));
707       anEdgeCheck.Perform();
708       if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
709         aGeomSh->setImpl(new TopoDS_Shape(aShape));
710         theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) :
711                            theRevolutionAlgo->addFromShape(aGeomSh);
712       }
713     } else {
714       Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
715       Handle(Geom_Surface) aBoundingSurface =
716         BRep_Tool::Surface(TopoDS::Face(theRotatedBoundingFace));
717       Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(TopoDS::Face(theModifiedBaseShape));
718       if(aFaceSurface == aBoundingSurface) {
719         aGeomSh->setImpl(new TopoDS_Shape(aShape));
720         theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) :
721                            theRevolutionAlgo->addToShape(aGeomSh);
722       }
723       if(aFaceSurface == aBaseSurface) {
724         aGeomSh->setImpl(new TopoDS_Shape(aShape));
725         theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) :
726                            theRevolutionAlgo->addFromShape(aGeomSh);
727       }
728     }
729   }
730 }