Salome HOME
Issue #1112 tab key doesn't work on the last field of left panels
[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_MakeShapeList.h>
13 #include <GeomAlgoAPI_ShapeTools.h>
14
15 #include <BRep_Builder.hxx>
16 #include <BRep_Tool.hxx>
17 #include <BRepAlgoAPI_Cut.hxx>
18 #include <BRepBuilderAPI_MakeFace.hxx>
19 #include <BRepBuilderAPI_Transform.hxx>
20 #include <BRepCheck_Analyzer.hxx>
21 #include <BRepPrimAPI_MakeRevol.hxx>
22 #include <BRepGProp.hxx>
23 #include <Geom_Plane.hxx>
24 #include <GeomLib_IsPlanarSurface.hxx>
25 #include <gp_Pln.hxx>
26 #include <GProp_GProps.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <TopoDS.hxx>
29 #include <TopTools_ListIteratorOfListOfShape.hxx>
30
31 /// \brief Constructs infinite face from thePlane, and with axis located on the same side
32 /// of the plane as thePoint. Modifies thePlane axis direction.
33 /// \param[in,out] thePlane plane to construct face.
34 /// \param[in] thePoint point to locate plane axis.
35 /// \return constructed face.
36 static TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint);
37
38 /// \return solid created from face or shell.
39 static TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape);
40
41 /// \brief Selects solid from theShape with closest center of mass to thePoint
42 /// \param[in] theShape compound with solids.
43 /// \param[in] thePoint point.
44 /// \return solid.
45 static TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint);
46
47 //=================================================================================================
48 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(std::shared_ptr<GeomAPI_Shape> theBaseShape,
49                                                std::shared_ptr<GeomAPI_Ax1>   theAxis,
50                                                double                         theToAngle,
51                                                double                         theFromAngle)
52 {
53   build(theBaseShape, theAxis, std::shared_ptr<GeomAPI_Shape>(), theToAngle, std::shared_ptr<GeomAPI_Shape>(), theFromAngle);
54 }
55
56 //=================================================================================================
57 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(std::shared_ptr<GeomAPI_Shape> theBaseShape,
58                                                std::shared_ptr<GeomAPI_Ax1>   theAxis,
59                                                std::shared_ptr<GeomAPI_Shape> theToShape,
60                                                double                         theToAngle,
61                                                std::shared_ptr<GeomAPI_Shape> theFromShape,
62                                                double                         theFromAngle)
63 {
64   build(theBaseShape, theAxis, theToShape, theToAngle, theFromShape, theFromAngle);
65 }
66
67 //=================================================================================================
68 void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
69                                    const std::shared_ptr<GeomAPI_Ax1>&   theAxis,
70                                    const std::shared_ptr<GeomAPI_Shape>& theToShape,
71                                    double                                theToAngle,
72                                    const std::shared_ptr<GeomAPI_Shape>& theFromShape,
73                                    double                                theFromAngle)
74 {
75   if(!theBaseShape || !theAxis ||
76     (((!theFromShape && !theToShape) || (theFromShape && theToShape && theFromShape->isEqual(theToShape)))
77     && (theFromAngle == -theToAngle))) {
78     return;
79   }
80
81   // Geting base plane.
82   const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
83   TopoDS_Face aBaseFace;
84   if(theBaseShape->shapeType() == GeomAPI_Shape::FACE) {
85     aBaseFace = TopoDS::Face(theBaseShape->impl<TopoDS_Shape>());
86   } else if(theBaseShape->shapeType() == GeomAPI_Shape::SHELL) {
87     GeomAPI_ShapeExplorer anExp(theBaseShape, GeomAPI_Shape::FACE);
88     if(anExp.more()) {
89       std::shared_ptr<GeomAPI_Shape> aFaceOnShell = anExp.current();
90       aBaseFace = TopoDS::Face(aFaceOnShell->impl<TopoDS_Shape>());
91     }
92   }
93   if(aBaseFace.IsNull()) {
94     return;
95   }
96   GeomLib_IsPlanarSurface isBasePlanar(BRep_Tool::Surface(aBaseFace));
97   gp_Pln aBasePln = isBasePlanar.Plan();
98   Geom_Plane aBasePlane(aBasePln);
99   gp_Ax1 anAxis = theAxis->impl<gp_Ax1>();
100   if(aBasePlane.Axis().Angle(anAxis) < Precision::Confusion()) {
101     return;
102   }
103
104   gp_Pnt aBaseCentre = GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape)->impl<gp_Pnt>();
105
106   TopoDS_Shape aResult;
107   if(!theFromShape && !theToShape) { // Case 1: When only angles was set.
108     // Rotating base face with the negative value of "from angle".
109     gp_Trsf aBaseTrsf;
110     aBaseTrsf.SetRotation(anAxis, -theFromAngle / 180.0 * M_PI);
111     BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBaseShape,
112                                                                             aBaseTrsf,
113                                                                             true);
114     if(!aBaseTransform) {
115       return;
116     }
117     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseTransform)));
118     if(!aBaseTransform->IsDone()) {
119       return;
120     }
121     TopoDS_Shape aRotatedBase = aBaseTransform->Shape();
122
123     // Making revolution to the angle equal to the sum of "from angle" and "to angle".
124     BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aRotatedBase,
125                                                                       anAxis,
126                                                                       (theFromAngle + theToAngle) / 180 * M_PI,
127                                                                       Standard_True);
128     if(!aRevolBuilder) {
129       return;
130     }
131     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
132     if(!aRevolBuilder->IsDone()) {
133       return;
134     }
135     aResult = aRevolBuilder->Shape();
136
137     // Setting naming.
138     for(TopExp_Explorer anExp(aRotatedBase, TopAbs_FACE); anExp.More(); anExp.Next()) {
139       const TopoDS_Shape& aFace = anExp.Current();
140       std::shared_ptr<GeomAPI_Shape> aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
141       aFromShape->setImpl(new TopoDS_Shape(aRevolBuilder->FirstShape(aFace)));
142       aToShape->setImpl(new TopoDS_Shape(aRevolBuilder->LastShape(aFace)));
143       this->addFromFace(aFromShape);
144       this->addToFace(aToShape);
145     }
146   } else if(theFromShape && theToShape) { // Case 2: When both bounding planes were set.
147     // Making revolution to the 360 angle.
148     BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
149     if(!aRevolBuilder) {
150       return;
151     }
152     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
153     if(!aRevolBuilder->IsDone()) {
154       return;
155     }
156     aResult = aRevolBuilder->Shape();
157
158     // Getting bounding faces.
159     TopoDS_Face aFromFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
160     TopoDS_Face aToFace   = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
161
162     // Getting planes from bounding face.
163     GeomLib_IsPlanarSurface isFromPlanar(BRep_Tool::Surface(aFromFace));
164     GeomLib_IsPlanarSurface isToPlanar(BRep_Tool::Surface(aToFace));
165     if(!isFromPlanar.IsPlanar() || !isToPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution bounding
166       return;
167     }
168     gp_Pln aFromPln = isFromPlanar.Plan();
169     gp_Pln aToPln   = isToPlanar.Plan();
170
171     // Orienting bounding planes properly so that the center of mass of the base face stays
172     // on the result shape after cut.
173     aFromFace = makeFaceFromPlane(aFromPln, aBaseCentre);
174     aToFace   = makeFaceFromPlane(aToPln, aBaseCentre);
175
176     // Making solids from bounding planes and putting them in compound.
177     TopoDS_Shape aFromSolid = makeSolidFromShape(aFromFace);
178     TopoDS_Shape aToSolid   = makeSolidFromShape(aToFace);
179
180     // Rotating bounding planes to the specified angle.
181     gp_Trsf aFromTrsf;
182     gp_Trsf aToTrsf;
183     double aFromRotAngle = ((aFromPln.Axis().Direction() * aBasePln.Axis().Direction()) > 0) ? -theFromAngle : theFromAngle;
184     double aToRotAngle = ((aToPln.Axis().Direction() * aBasePln.Axis().Direction()) > 0) ? -theToAngle : theToAngle;
185     aFromTrsf.SetRotation(anAxis,aFromRotAngle / 180.0 * M_PI);
186     aToTrsf.SetRotation(anAxis, aToRotAngle / 180.0 * M_PI);
187     BRepBuilderAPI_Transform aFromTransform(aFromSolid, aFromTrsf, true);
188     BRepBuilderAPI_Transform aToTransform(aToSolid, aToTrsf, true);
189     TopoDS_Shape aRotatedFromFace = aFromTransform.Modified(aFromFace).First();
190     TopoDS_Shape aRotatedToFace = aToTransform.Modified(aToFace).First();
191     aFromSolid = aFromTransform.Shape();
192     aToSolid = aToTransform.Shape();
193
194     // Cutting revolution with from plane.
195     BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
196     aFromCutBuilder->Build();
197     if(!aFromCutBuilder->IsDone()) {
198       return;
199     }
200     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aFromCutBuilder)));
201     aResult = aFromCutBuilder->Shape();
202
203     // Cutting revolution with to plane.
204     BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
205     aToCutBuilder->Build();
206     if(!aToCutBuilder->IsDone()) {
207       return;
208     }
209     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aToCutBuilder)));
210     aResult = aToCutBuilder->Shape();
211
212     TopExp_Explorer anExp(aResult, TopAbs_SOLID);
213     if(!anExp.More()) {
214       return;
215     }
216     if(aResult.ShapeType() == TopAbs_COMPOUND) {
217       aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
218     }
219     if(aResult.ShapeType() == TopAbs_COMPOUND) {
220       std::shared_ptr<GeomAPI_Shape> aCompound(new GeomAPI_Shape);
221       aCompound->setImpl(new TopoDS_Shape(aResult));
222       ListOfShape aCompSolids, aFreeSolids;
223       GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCompSolids, aFreeSolids);
224       if(aCompSolids.size() == 1 && aFreeSolids.size() == 0) {
225         aResult = aCompSolids.front()->impl<TopoDS_Shape>();
226       } else if (aCompSolids.size() > 1 || (aCompSolids.size() >= 1 && aFreeSolids.size() >= 1)) {
227         TopoDS_Compound aResultComp;
228         TopoDS_Builder aBuilder;
229         aBuilder.MakeCompound(aResultComp);
230         for(ListOfShape::const_iterator anIter = aCompSolids.cbegin(); anIter != aCompSolids.cend(); anIter++) {
231           aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
232         }
233         for(ListOfShape::const_iterator anIter = aFreeSolids.cbegin(); anIter != aFreeSolids.cend(); anIter++) {
234           aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
235         }
236         aResult = aResultComp;
237       }
238     }
239
240     // If after cut we got more than one solids then take closest to the center of mass of the base face.
241     aResult = findClosest(aResult, aBaseCentre);
242
243     // Setting naming.
244     for(TopExp_Explorer anExp(aResult, TopAbs_FACE); anExp.More (); anExp.Next ()) {
245       const TopoDS_Shape& aFaceOnResult = anExp.Current();
246       Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aFaceOnResult));
247       Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedFromFace));
248       Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedToFace));
249       if(aFaceSurface == aFromSurface) {
250         std::shared_ptr<GeomAPI_Shape> aFSHape(new GeomAPI_Shape);
251         aFSHape->setImpl(new TopoDS_Shape(aFaceOnResult));
252         this->addFromFace(aFSHape);
253       }
254       if(aFaceSurface == aToSurface) {
255         std::shared_ptr<GeomAPI_Shape> aTSHape(new GeomAPI_Shape);
256         aTSHape->setImpl(new TopoDS_Shape(aFaceOnResult));
257         this->addToFace(aTSHape);
258       }
259     }
260   } else { //Case 3: When only one bounding plane was set.
261     // Making revolution to the 360 angle.
262     BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
263     if(!aRevolBuilder) {
264       return;
265     }
266     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
267     if(!aRevolBuilder->IsDone()) {
268       return;
269     }
270     aResult = aRevolBuilder->Shape();
271
272     // Getting bounding face.
273     TopoDS_Face aBoundingFace;
274     bool isFromFaceSet = false;
275     if(theFromShape) {
276       aBoundingFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
277       isFromFaceSet = true;
278     } else if(theToShape) {
279       aBoundingFace = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
280     }
281
282     // Getting plane from bounding face.
283     GeomLib_IsPlanarSurface isBoundingPlanar(BRep_Tool::Surface(aBoundingFace));
284     if(!isBoundingPlanar.IsPlanar()) { // non-planar shapes is not supported for revolution bounding
285       return;
286     }
287     gp_Pln aBoundingPln = isBoundingPlanar.Plan();
288
289     // Orienting bounding plane properly so that the center of mass of the base face stays
290     // on the result shape after cut.
291     aBoundingFace = makeFaceFromPlane(aBoundingPln, aBaseCentre);
292
293     // Making solid from bounding plane.
294     TopoDS_Shape aBoundingSolid = makeSolidFromShape(aBoundingFace);
295
296     // Rotating bounding plane to the specified angle.
297     double aBoundingRotAngle = isFromFaceSet ? theFromAngle : theToAngle;
298     if(aBoundingPln.Axis().IsParallel(aBasePln.Axis(), Precision::Confusion())) {
299       if(isFromFaceSet) aBoundingRotAngle = -aBoundingRotAngle;
300     } else {
301       double aSign = (aBoundingPln.Axis().Direction() ^ aBasePln.Axis().Direction()) *
302                      anAxis.Direction();
303       if((aSign <= 0 && !isFromFaceSet) || (aSign > 0 && isFromFaceSet)) {
304         aBoundingRotAngle = -aBoundingRotAngle;
305       }
306     }
307     gp_Trsf aBoundingTrsf;
308     aBoundingTrsf.SetRotation(anAxis, aBoundingRotAngle / 180.0 * M_PI);
309     BRepBuilderAPI_Transform aBoundingTransform(aBoundingSolid, aBoundingTrsf, true);
310     TopoDS_Shape aRotatedBoundingFace = aBoundingTransform.Modified(aBoundingFace).First();
311     aBoundingSolid = aBoundingTransform.Shape();
312
313     // Cutting revolution with bounding plane.
314     BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aResult, aBoundingSolid);
315     aBoundingCutBuilder->Build();
316     if(!aBoundingCutBuilder->IsDone()) {
317       return;
318     }
319     this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBoundingCutBuilder)));
320     aResult = aBoundingCutBuilder->Shape();
321
322     // Setting naming.
323     const TopTools_ListOfShape& aBndShapes = aBoundingCutBuilder->Modified(aBoundingFace);
324     for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) {
325       std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
326       aShape->setImpl(new TopoDS_Shape(anIt.Value()));
327       isFromFaceSet ? this->addFromFace(aShape) : this->addToFace(aShape);
328     }
329
330     // Try to cut with base face. If it can not be done then keep result of cut with bounding plane.
331     TopoDS_Shape aModifiedBaseShape = aBaseShape;
332     if(isFromFaceSet) {
333       if(aModifiedBaseShape.ShapeType() == TopAbs_FACE) {
334         aModifiedBaseShape.Orientation(TopAbs_REVERSED);
335       } else {
336         gp_Trsf aMirrorTrsf;
337         aMirrorTrsf.SetMirror(aBasePlane.Position().Ax2());
338         BRepBuilderAPI_Transform aMirrorTransform(aModifiedBaseShape, aMirrorTrsf, true);
339         aModifiedBaseShape = aMirrorTransform.Shape();
340       }
341     }
342
343     // Making solid from base face.
344     TopoDS_Shape aBaseSolid = makeSolidFromShape(aModifiedBaseShape);
345
346     // Rotating base face to the specified angle.
347     gp_Trsf aBaseTrsf;
348     double aBaseRotAngle = isFromFaceSet ? theToAngle : -theFromAngle;
349     aBaseTrsf.SetRotation(anAxis, aBaseRotAngle / 180.0 * M_PI);
350     BRepBuilderAPI_Transform aBaseTransform(aBaseSolid, aBaseTrsf, true);
351     aBaseSolid = aBaseTransform.Shape();
352
353     // Cutting revolution with base.
354     BRepAlgoAPI_Cut* aBaseCutBuilder = new BRepAlgoAPI_Cut(aResult, aBaseSolid);
355     aBaseCutBuilder->Build();
356     if(aBaseCutBuilder->IsDone()) {
357       TopoDS_Shape aCutResult = aBaseCutBuilder->Shape();
358       TopExp_Explorer anExp(aCutResult, TopAbs_SOLID);
359       if(anExp.More()) {
360         this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseCutBuilder)));
361         aResult = aCutResult;
362       }
363     }
364
365     const TopTools_ListOfShape& aBsShapes = aBaseCutBuilder->Modified(aBoundingFace);
366     for(TopTools_ListIteratorOfListOfShape anIt(aBsShapes); anIt.More(); anIt.Next()) {
367       std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
368       aShape->setImpl(new TopoDS_Shape(anIt.Value()));
369       isFromFaceSet ? this->addToFace(aShape) : this->addFromFace(aShape);
370     }
371
372     TopExp_Explorer anExp(aResult, TopAbs_SOLID);
373     if(!anExp.More()) {
374       return;
375     }
376     if(aResult.ShapeType() == TopAbs_COMPOUND) {
377       aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
378     }
379     if(aResult.ShapeType() == TopAbs_COMPOUND) {
380       std::shared_ptr<GeomAPI_Shape> aCompound(new GeomAPI_Shape);
381       aCompound->setImpl(new TopoDS_Shape(aResult));
382       ListOfShape aCompSolids, aFreeSolids;
383       GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCompSolids, aFreeSolids);
384       if(aCompSolids.size() == 1 && aFreeSolids.size() == 0) {
385         aResult = aCompSolids.front()->impl<TopoDS_Shape>();
386       } else if (aCompSolids.size() > 1 || (aCompSolids.size() >= 1 && aFreeSolids.size() >= 1)) {
387         TopoDS_Compound aResultComp;
388         TopoDS_Builder aBuilder;
389         aBuilder.MakeCompound(aResultComp);
390         for(ListOfShape::const_iterator anIter = aCompSolids.cbegin(); anIter != aCompSolids.cend(); anIter++) {
391           aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
392         }
393         for(ListOfShape::const_iterator anIter = aFreeSolids.cbegin(); anIter != aFreeSolids.cend(); anIter++) {
394           aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
395         }
396         aResult = aResultComp;
397       }
398     }
399
400     // If after cut we got more than one solids then take closest to the center of mass of the base face.
401     aResult = findClosest(aResult, aBaseCentre);
402
403     // Setting naming.
404     for(TopExp_Explorer anExp(aResult, TopAbs_FACE); anExp.More (); anExp.Next ()) {
405       const TopoDS_Shape& aFaceOnResult = anExp.Current();
406       Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aFaceOnResult));
407       Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedBoundingFace));
408       if(aFaceSurface == aBoundingSurface) {
409         std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
410         aShape->setImpl(new TopoDS_Shape(aFaceOnResult));
411         isFromFaceSet ? this->addFromFace(aShape) : this->addToFace(aShape);
412       }
413     }
414   }
415
416   // Setting result.
417   if(aResult.IsNull()) {
418     return;
419   }
420   std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
421   aShape->setImpl(new TopoDS_Shape(aResult));
422   this->setShape(aShape);
423   this->setDone(true);
424 }
425
426 //=================================================================================================
427 TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
428 {
429   if(!thePlane.Contains(thePoint, Precision::Confusion())) {
430     gp_XYZ aVec = thePoint.XYZ() - thePlane.Location().XYZ();
431     double aSign = aVec * thePlane.Axis().Direction().XYZ();
432     if(aSign < 0) thePlane.SetAxis(thePlane.Axis().Reversed());
433   }
434
435   BRepBuilderAPI_MakeFace aMakeFace(thePlane);
436   TopoDS_Face aResultFace = TopoDS::Face(aMakeFace.Shape());
437
438   return aResultFace;
439 }
440
441 //=================================================================================================
442 TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape)
443 {
444   TopoDS_Shell aShell;
445   TopoDS_Solid aSolid;
446
447   BRep_Builder aBoundingBuilder;
448   if(theShape.ShapeType() == TopAbs_SHELL) {
449     aShell = TopoDS::Shell(theShape);
450   } else {
451     aBoundingBuilder.MakeShell(aShell);
452     aBoundingBuilder.Add(aShell, theShape);
453   }
454   aBoundingBuilder.MakeSolid(aSolid);
455   aBoundingBuilder.Add(aSolid, aShell);
456
457   return aSolid;
458 }
459
460 //=================================================================================================
461 TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
462 {
463   TopoDS_Shape aResult = theShape;
464
465   if(theShape.ShapeType() == TopAbs_COMPOUND) {
466     double aMinDistance = Precision::Infinite();
467     double aCurDistance;
468     GProp_GProps aGProps;
469     gp_Pnt aCentr;
470
471     for (TopoDS_Iterator anItr(theShape); anItr.More(); anItr.Next()) {
472       TopoDS_Shape aValue = anItr.Value();
473       BRepGProp::VolumeProperties(aValue, aGProps);
474       aCentr = aGProps.CentreOfMass();
475       aCurDistance = aCentr.Distance(thePoint);
476
477       if(aCurDistance < aMinDistance) {
478         aMinDistance = aCurDistance;
479         aResult = aValue;
480       }
481     }
482   }
483
484   return aResult;
485 }