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