]> SALOME platform Git repositories - modules/shaper.git/blob - src/GeomAlgoAPI/GeomAlgoAPI_Revolution.cpp
Salome HOME
Issue #1367: Fill feature.
[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       std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
275       aGeomShape->setImpl(new TopoDS_Shape(aResult));
276       ListOfShape aCompSolids, aFreeSolids;
277       aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
278                                                          GeomAPI_Shape::COMPSOLID,
279                                                          aCompSolids,
280                                                          aFreeSolids);
281       aResult = aGeomShape->impl<TopoDS_Shape>();
282     }
283
284     // If after cut we got more than one solids then take closest to the center of mass of the base face.
285     aResult = findClosest(aResult, aBaseCentre);
286
287     // Setting naming.
288     for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More (); anExp.Next ()) {
289       const TopoDS_Shape& aShape = anExp.Current();
290       GeomShapePtr aGeomSh(new GeomAPI_Shape());
291       if(aShapeTypeToExp == TopAbs_VERTEX) {
292         gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
293         IntTools_Context anIntTools;
294         if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedToFace), Precision::Confusion()) == Standard_True) {
295           aGeomSh->setImpl(new TopoDS_Shape(aShape));
296           this->addToShape(aGeomSh);
297         }
298         if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedFromFace), Precision::Confusion()) == Standard_True) {
299           aGeomSh->setImpl(new TopoDS_Shape(aShape));
300           this->addFromShape(aGeomSh);
301         }
302       } else if(aShapeTypeToExp == TopAbs_EDGE) {
303         TopoDS_Edge anEdge = TopoDS::Edge(aShape);
304         BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(aRotatedToFace));
305         anEdgeCheck.Perform();
306         if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
307           aGeomSh->setImpl(new TopoDS_Shape(aShape));
308           this->addToShape(aGeomSh);
309         }
310         anEdgeCheck.Init(anEdge, TopoDS::Face(aRotatedFromFace));
311         anEdgeCheck.Perform();
312         if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
313           aGeomSh->setImpl(new TopoDS_Shape(aShape));
314           this->addFromShape(aGeomSh);
315         }
316       } else {
317         Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
318         Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedFromFace));
319         Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedToFace));
320         if(aFaceSurface == aFromSurface) {
321           aGeomSh->setImpl(new TopoDS_Shape(aShape));
322           this->addFromShape(aGeomSh);
323         }
324         if(aFaceSurface == aToSurface) {
325           aGeomSh->setImpl(new TopoDS_Shape(aShape));
326           this->addToShape(aGeomSh);
327         }
328       }
329     }
330   } else { //Case 3: When only one bounding plane was set.
331     // Making revolution to the 360 angle.
332     BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
333     if(!aRevolBuilder) {
334       return;
335     }
336     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
337     if(!aRevolBuilder->IsDone()) {
338       return;
339     }
340     aResult = aRevolBuilder->Shape();
341
342     // Getting bounding face.
343     TopoDS_Face aBoundingFace;
344     bool isFromFaceSet = false;
345     if(theFromShape) {
346       aBoundingFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
347       isFromFaceSet = true;
348     } else if(theToShape) {
349       aBoundingFace = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
350     }
351
352     // Getting plane from bounding face.
353     GeomLib_IsPlanarSurface isBoundingPlanar(BRep_Tool::Surface(aBoundingFace));
354     if(!isBoundingPlanar.IsPlanar()) { // non-planar shapes is not supported for revolution bounding
355       return;
356     }
357     gp_Pln aBoundingPln = isBoundingPlanar.Plan();
358
359     // Orienting bounding plane properly so that the center of mass of the base face stays
360     // on the result shape after cut.
361     aBoundingFace = makeFaceFromPlane(aBoundingPln, aBaseCentre);
362
363     // Making solid from bounding plane.
364     TopoDS_Shape aBoundingSolid = makeSolidFromShape(aBoundingFace);
365
366     // Rotating bounding plane to the specified angle.
367     double aBoundingRotAngle = isFromFaceSet ? theFromAngle : theToAngle;
368     if(aBoundingPln.Axis().IsParallel(aBasePlane->Axis(), Precision::Confusion())) {
369       if(isFromFaceSet) aBoundingRotAngle = -aBoundingRotAngle;
370     } else {
371       double aSign = (aBoundingPln.Axis().Direction() ^ aBasePlane->Axis().Direction()) *
372                      anAxis.Direction();
373       if((aSign <= 0 && !isFromFaceSet) || (aSign > 0 && isFromFaceSet)) {
374         aBoundingRotAngle = -aBoundingRotAngle;
375       }
376     }
377     gp_Trsf aBoundingTrsf;
378     aBoundingTrsf.SetRotation(anAxis, aBoundingRotAngle / 180.0 * M_PI);
379     BRepBuilderAPI_Transform aBoundingTransform(aBoundingSolid, aBoundingTrsf, true);
380     TopoDS_Shape aRotatedBoundingFace = aBoundingTransform.Modified(aBoundingFace).First();
381     aBoundingSolid = aBoundingTransform.Shape();
382
383     // Cutting revolution with bounding plane.
384     BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aResult, aBoundingSolid);
385     aBoundingCutBuilder->Build();
386     if(!aBoundingCutBuilder->IsDone()) {
387       return;
388     }
389     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBoundingCutBuilder)));
390     aResult = aBoundingCutBuilder->Shape();
391     if(aResult.ShapeType() == TopAbs_COMPOUND) {
392       aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
393     }
394
395     // Setting naming.
396     if(aShapeTypeToExp == TopAbs_FACE) {
397       const TopTools_ListOfShape& aBndShapes = aBoundingCutBuilder->Modified(aBoundingFace);
398       for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) {
399         GeomShapePtr aShape(new GeomAPI_Shape());
400         aShape->setImpl(new TopoDS_Shape(anIt.Value()));
401         isFromFaceSet ? this->addFromShape(aShape) : this->addToShape(aShape);
402       }
403     }
404
405     // Try to cut with base face. If it can not be done then keep result of cut with bounding plane.
406     TopoDS_Shape aModifiedBaseShape;
407     if(aShapeTypeToExp != TopAbs_FACE) {
408       ListOfShape aList;
409       GeomShapePtr aSh(new GeomAPI_Shape());
410       aSh->setImpl(new TopoDS_Shape(aBaseShape));
411       std::shared_ptr<GeomAPI_Pnt> theCenter(new GeomAPI_Pnt(aBasePlane->Location().X(),
412                                                              aBasePlane->Location().Y(),
413                                                              aBasePlane->Location().Z()));
414       std::shared_ptr<GeomAPI_Dir> theNormal(new GeomAPI_Dir(aBasePlane->Axis().Direction().X(),
415                                                              aBasePlane->Axis().Direction().Y(),
416                                                              aBasePlane->Axis().Direction().Z()));
417       GeomShapePtr aPln = GeomAlgoAPI_FaceBuilder::planarFace(theCenter, theNormal);
418       aList.push_back(aSh);
419       std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(aList);
420       aSh = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPln, aBoundingPoints);
421       aModifiedBaseShape = aSh->impl<TopoDS_Shape>();
422     } else {
423       aModifiedBaseShape = aBaseShape;
424     }
425     if(isFromFaceSet) {
426       if(aModifiedBaseShape.ShapeType() == TopAbs_FACE) {
427         aModifiedBaseShape.Orientation(TopAbs_REVERSED);
428       } else {
429         gp_Trsf aMirrorTrsf;
430         aMirrorTrsf.SetMirror(aBasePlane->Position().Ax2());
431         BRepBuilderAPI_Transform aMirrorTransform(aModifiedBaseShape, aMirrorTrsf, true);
432         aModifiedBaseShape = aMirrorTransform.Shape();
433       }
434     }
435
436     // Making solid from base face.
437     TopoDS_Shape aBaseSolid = makeSolidFromShape(aModifiedBaseShape);
438
439     // Rotating base face to the specified angle.
440     gp_Trsf aBaseTrsf;
441     double aBaseRotAngle = isFromFaceSet ? theToAngle : -theFromAngle;
442     aBaseTrsf.SetRotation(anAxis, aBaseRotAngle / 180.0 * M_PI);
443     BRepBuilderAPI_Transform aBaseTransform(aBaseSolid, aBaseTrsf, true);
444     aBaseSolid = aBaseTransform.Shape();
445
446     // Cutting revolution with base.
447     BRepAlgoAPI_Cut* aBaseCutBuilder = new BRepAlgoAPI_Cut(aResult, aBaseSolid);
448     aBaseCutBuilder->Build();
449     if(aBaseCutBuilder->IsDone()) {
450       TopoDS_Shape aCutResult = aBaseCutBuilder->Shape();
451       TopoDS_Iterator aCheckIt(aCutResult);
452       if(aCheckIt.More()) {
453         this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseCutBuilder)));
454         aResult = aCutResult;
455         if(aResult.ShapeType() == TopAbs_COMPOUND) {
456           aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
457         }
458         if(aShapeTypeToExp == TopAbs_FACE) {
459           const TopTools_ListOfShape& aBsShapes = aBaseCutBuilder->Modified(aBoundingFace);
460           for(TopTools_ListIteratorOfListOfShape anIt(aBsShapes); anIt.More(); anIt.Next()) {
461             GeomShapePtr aShape(new GeomAPI_Shape());
462             aShape->setImpl(new TopoDS_Shape(anIt.Value()));
463             isFromFaceSet ? this->addToShape(aShape) : this->addFromShape(aShape);
464           }
465         }
466       }
467     }
468
469     if(aResult.ShapeType() == TopAbs_COMPOUND) {
470       std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
471       aGeomShape->setImpl(new TopoDS_Shape(aResult));
472       ListOfShape aCompSolids, aFreeSolids;
473       aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
474                                                          GeomAPI_Shape::COMPSOLID,
475                                                          aCompSolids,
476                                                          aFreeSolids);
477       aResult = aGeomShape->impl<TopoDS_Shape>();
478     }
479
480     // If after cut we got more than one solids then take closest to the center of mass of the base face.
481     aResult = findClosest(aResult, aBaseCentre);
482
483     // Setting naming.
484     for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More (); anExp.Next ()) {
485       const TopoDS_Shape& aShape = anExp.Current();
486       GeomShapePtr aGeomSh(new GeomAPI_Shape());
487       if(aShapeTypeToExp == TopAbs_VERTEX) {
488         gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
489         IntTools_Context anIntTools;
490         if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedBoundingFace), Precision::Confusion()) == Standard_True) {
491           aGeomSh->setImpl(new TopoDS_Shape(aShape));
492           isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
493         }
494         if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aModifiedBaseShape), Precision::Confusion()) == Standard_True) {
495           aGeomSh->setImpl(new TopoDS_Shape(aShape));
496           isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
497         }
498       } else if(aShapeTypeToExp == TopAbs_EDGE) {
499         TopoDS_Edge anEdge = TopoDS::Edge(aShape);
500         BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(aRotatedBoundingFace));
501         anEdgeCheck.Perform();
502         if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
503           aGeomSh->setImpl(new TopoDS_Shape(aShape));
504           isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
505         }
506         anEdgeCheck.Init(anEdge, TopoDS::Face(aModifiedBaseShape));
507         anEdgeCheck.Perform();
508         if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
509           aGeomSh->setImpl(new TopoDS_Shape(aShape));
510           isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
511         }
512       } else {
513         Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
514         Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedBoundingFace));
515         Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(TopoDS::Face(aModifiedBaseShape));
516         if(aFaceSurface == aBoundingSurface) {
517           aGeomSh->setImpl(new TopoDS_Shape(aShape));
518           isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
519         }
520         if(aFaceSurface == aBaseSurface) {
521           aGeomSh->setImpl(new TopoDS_Shape(aShape));
522           isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
523         }
524       }
525     }
526   }
527
528   // Setting result.
529   if(aResult.IsNull()) {
530     return;
531   }
532   aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
533   GeomShapePtr aShape(new GeomAPI_Shape());
534   aShape->setImpl(new TopoDS_Shape(aResult));
535   this->setShape(aShape);
536   this->setDone(true);
537 }
538
539 //=================================================================================================
540 TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
541 {
542   if(!thePlane.Contains(thePoint, Precision::Confusion())) {
543     gp_XYZ aVec = thePoint.XYZ() - thePlane.Location().XYZ();
544     double aSign = aVec * thePlane.Axis().Direction().XYZ();
545     if(aSign < 0) thePlane.SetAxis(thePlane.Axis().Reversed());
546   }
547
548   BRepBuilderAPI_MakeFace aMakeFace(thePlane);
549   TopoDS_Face aResultFace = TopoDS::Face(aMakeFace.Shape());
550
551   return aResultFace;
552 }
553
554 //=================================================================================================
555 TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape)
556 {
557   TopoDS_Shell aShell;
558   TopoDS_Solid aSolid;
559
560   BRep_Builder aBoundingBuilder;
561   if(theShape.ShapeType() == TopAbs_SHELL) {
562     aShell = TopoDS::Shell(theShape);
563   } else {
564     aBoundingBuilder.MakeShell(aShell);
565     aBoundingBuilder.Add(aShell, theShape);
566   }
567   aBoundingBuilder.MakeSolid(aSolid);
568   aBoundingBuilder.Add(aSolid, aShell);
569
570   return aSolid;
571 }
572
573 //=================================================================================================
574 gp_Pnt centreOfMass(const TopoDS_Shape& theShape)
575 {
576   TopAbs_ShapeEnum aShType = theShape.ShapeType();
577   GProp_GProps aGProps;
578
579   if(aShType == TopAbs_EDGE || aShType == TopAbs_WIRE) {
580     BRepGProp::LinearProperties(theShape, aGProps);
581   } else if(aShType == TopAbs_FACE || aShType == TopAbs_SHELL) {
582     BRepGProp::SurfaceProperties(theShape, aGProps);
583   } else if(aShType == TopAbs_SOLID || aShType == TopAbs_COMPSOLID) {
584     BRepGProp::VolumeProperties(theShape, aGProps);
585   }
586
587   return aGProps.CentreOfMass();
588 }
589
590 //=================================================================================================
591 TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
592 {
593   TopoDS_Shape aResult = theShape;
594
595   if(theShape.ShapeType() == TopAbs_COMPOUND) {
596     double aMinDistance = Precision::Infinite();
597     double aCurDistance;
598     gp_Pnt aCentr;
599     for (TopoDS_Iterator anItr(theShape); anItr.More(); anItr.Next()) {
600       TopoDS_Shape aValue = anItr.Value();
601       aCentr = centreOfMass(aValue);
602       aCurDistance = aCentr.Distance(thePoint);
603
604       if(aCurDistance < aMinDistance) {
605         aMinDistance = aCurDistance;
606         aResult = aValue;
607       }
608     }
609   }
610
611   return aResult;
612 }