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