1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: GeomAlgoAPI_Revolution.cpp
4 // Created: 12 May 2015
5 // Author: Dmitry Bobylev
7 #include "GeomAlgoAPI_Revolution.h"
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>
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>
32 #include <GProp_GProps.hxx>
33 #include <IntTools_Context.hxx>
34 #include <TopExp_Explorer.hxx>
36 #include <TopoDS_Edge.hxx>
37 #include <TopTools_ListIteratorOfListOfShape.hxx>
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);
46 /// \return solid created from face or shell.
47 static TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape);
49 /// \brief return centre of mass for theShape.
50 /// \param[in] theShape shape.
51 static gp_Pnt centreOfMass(const TopoDS_Shape& theShape);
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.
57 static TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint);
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)
65 build(theBaseShape, theAxis, GeomShapePtr(), theToAngle, GeomShapePtr(), theFromAngle);
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)
76 build(theBaseShape, theAxis, theToShape, theToAngle, theFromShape, theFromAngle);
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)
87 if(!theBaseShape || !theAxis ||
88 (((!theFromShape && !theToShape) || (theFromShape && theToShape && theFromShape->isEqual(theToShape)))
89 && (theFromAngle == -theToAngle))) {
93 // Getting base shape.
94 const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
95 TopAbs_ShapeEnum aShapeTypeToExp;
96 switch(aBaseShape.ShapeType()) {
98 aShapeTypeToExp = TopAbs_VERTEX;
102 aShapeTypeToExp = TopAbs_EDGE;
106 aShapeTypeToExp = TopAbs_FACE;
113 gp_Ax1 anAxis = theAxis->impl<gp_Ax1>();
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();
121 gp_Pnt aPnt1 = anAxis.Location();
122 gp_Pnt aPnt2 = aPnt1;
123 aPnt2.Translate(anAxis.Direction());
126 for(TopExp_Explorer anExp(aBaseShape, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
127 aPnt3 = BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current()));
129 GC_MakePlane aMkPlane(aPnt1, aPnt2, aPnt3);
130 if(aMkPlane.IsDone() != Standard_True) {
134 aBasePlane = aMkPlane.Value();
138 if(aBasePlane.IsNull()) {
139 aPnt3 = centreOfMass(aBaseShape);
141 GC_MakePlane aMkPlane(aPnt1, aPnt2, aPnt3);
142 if(aMkPlane.IsDone() != Standard_True) {
146 aBasePlane = aMkPlane.Value();
150 if(aShapeTypeToExp == TopAbs_FACE) {
151 if(aBasePlane->Axis().Angle(anAxis) < Precision::Confusion()) {
156 gp_Pnt aBaseCentre = GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape)->impl<gp_Pnt>();
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".
162 aBaseTrsf.SetRotation(anAxis, -theFromAngle / 180.0 * M_PI);
163 BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBaseShape,
166 if(!aBaseTransform) {
169 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseTransform)));
170 if(!aBaseTransform->IsDone()) {
173 TopoDS_Shape aRotatedBase = aBaseTransform->Shape();
175 // Making revolution to the angle equal to the sum of "from angle" and "to angle".
176 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aRotatedBase,
178 (theFromAngle + theToAngle) / 180 * M_PI,
183 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
184 if(!aRevolBuilder->IsDone()) {
187 aResult = aRevolBuilder->Shape();
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);
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);
204 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
205 if(!aRevolBuilder->IsDone()) {
208 aResult = aRevolBuilder->Shape();
210 // Getting bounding faces.
211 TopoDS_Face aFromFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
212 TopoDS_Face aToFace = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
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
220 gp_Pln aFromPln = isFromPlanar.Plan();
221 gp_Pln aToPln = isToPlanar.Plan();
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);
228 // Making solids from bounding planes and putting them in compound.
229 TopoDS_Shape aFromSolid = makeSolidFromShape(aFromFace);
230 TopoDS_Shape aToSolid = makeSolidFromShape(aToFace);
232 // Rotating bounding planes to the specified angle.
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();
246 // Cutting revolution with from plane.
247 BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
248 aFromCutBuilder->Build();
249 if(!aFromCutBuilder->IsDone()) {
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);
258 // Cutting revolution with to plane.
259 BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
260 aToCutBuilder->Build();
261 if(!aToCutBuilder->IsDone()) {
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()) {
270 if(aResult.ShapeType() == TopAbs_COMPOUND) {
271 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
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>());
287 for(ListOfShape::const_iterator anIter = aFreeSolids.cbegin(); anIter != aFreeSolids.cend(); anIter++) {
288 aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
290 aResult = aResultComp;
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);
298 for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More (); anExp.Next ()) {
299 const TopoDS_Shape& aShape = anExp.Current();
300 GeomShapePtr aGeomSh(new GeomAPI_Shape());
301 if(aShapeTypeToExp == TopAbs_VERTEX) {
302 gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
303 IntTools_Context anIntTools;
304 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedToFace), Precision::Confusion()) == Standard_True) {
305 aGeomSh->setImpl(new TopoDS_Shape(aShape));
306 this->addToShape(aGeomSh);
308 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedFromFace), Precision::Confusion()) == Standard_True) {
309 aGeomSh->setImpl(new TopoDS_Shape(aShape));
310 this->addFromShape(aGeomSh);
312 } else if(aShapeTypeToExp == TopAbs_EDGE) {
313 TopoDS_Edge anEdge = TopoDS::Edge(aShape);
314 BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(aRotatedToFace));
315 anEdgeCheck.Perform();
316 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
317 aGeomSh->setImpl(new TopoDS_Shape(aShape));
318 this->addToShape(aGeomSh);
320 anEdgeCheck.Init(anEdge, TopoDS::Face(aRotatedFromFace));
321 anEdgeCheck.Perform();
322 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
323 aGeomSh->setImpl(new TopoDS_Shape(aShape));
324 this->addFromShape(aGeomSh);
327 Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
328 Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedFromFace));
329 Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedToFace));
330 if(aFaceSurface == aFromSurface) {
331 aGeomSh->setImpl(new TopoDS_Shape(aShape));
332 this->addFromShape(aGeomSh);
334 if(aFaceSurface == aToSurface) {
335 aGeomSh->setImpl(new TopoDS_Shape(aShape));
336 this->addToShape(aGeomSh);
340 } else { //Case 3: When only one bounding plane was set.
341 // Making revolution to the 360 angle.
342 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
346 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
347 if(!aRevolBuilder->IsDone()) {
350 aResult = aRevolBuilder->Shape();
352 // Getting bounding face.
353 TopoDS_Face aBoundingFace;
354 bool isFromFaceSet = false;
356 aBoundingFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
357 isFromFaceSet = true;
358 } else if(theToShape) {
359 aBoundingFace = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
362 // Getting plane from bounding face.
363 GeomLib_IsPlanarSurface isBoundingPlanar(BRep_Tool::Surface(aBoundingFace));
364 if(!isBoundingPlanar.IsPlanar()) { // non-planar shapes is not supported for revolution bounding
367 gp_Pln aBoundingPln = isBoundingPlanar.Plan();
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);
373 // Making solid from bounding plane.
374 TopoDS_Shape aBoundingSolid = makeSolidFromShape(aBoundingFace);
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;
381 double aSign = (aBoundingPln.Axis().Direction() ^ aBasePlane->Axis().Direction()) *
383 if((aSign <= 0 && !isFromFaceSet) || (aSign > 0 && isFromFaceSet)) {
384 aBoundingRotAngle = -aBoundingRotAngle;
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();
393 // Cutting revolution with bounding plane.
394 BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aResult, aBoundingSolid);
395 aBoundingCutBuilder->Build();
396 if(!aBoundingCutBuilder->IsDone()) {
399 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBoundingCutBuilder)));
400 aResult = aBoundingCutBuilder->Shape();
401 if(aResult.ShapeType() == TopAbs_COMPOUND) {
402 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
406 if(aShapeTypeToExp == TopAbs_FACE) {
407 const TopTools_ListOfShape& aBndShapes = aBoundingCutBuilder->Modified(aBoundingFace);
408 for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) {
409 GeomShapePtr aShape(new GeomAPI_Shape());
410 aShape->setImpl(new TopoDS_Shape(anIt.Value()));
411 isFromFaceSet ? this->addFromShape(aShape) : this->addToShape(aShape);
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) {
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 aList.push_back(aSh);
429 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(aList);
430 aSh = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPln, aBoundingPoints);
431 aModifiedBaseShape = aSh->impl<TopoDS_Shape>();
433 aModifiedBaseShape = aBaseShape;
436 if(aModifiedBaseShape.ShapeType() == TopAbs_FACE) {
437 aModifiedBaseShape.Orientation(TopAbs_REVERSED);
440 aMirrorTrsf.SetMirror(aBasePlane->Position().Ax2());
441 BRepBuilderAPI_Transform aMirrorTransform(aModifiedBaseShape, aMirrorTrsf, true);
442 aModifiedBaseShape = aMirrorTransform.Shape();
446 // Making solid from base face.
447 TopoDS_Shape aBaseSolid = makeSolidFromShape(aModifiedBaseShape);
449 // Rotating base face to the specified angle.
451 double aBaseRotAngle = isFromFaceSet ? theToAngle : -theFromAngle;
452 aBaseTrsf.SetRotation(anAxis, aBaseRotAngle / 180.0 * M_PI);
453 BRepBuilderAPI_Transform aBaseTransform(aBaseSolid, aBaseTrsf, true);
454 aBaseSolid = aBaseTransform.Shape();
456 // Cutting revolution with base.
457 BRepAlgoAPI_Cut* aBaseCutBuilder = new BRepAlgoAPI_Cut(aResult, aBaseSolid);
458 aBaseCutBuilder->Build();
459 if(aBaseCutBuilder->IsDone()) {
460 TopoDS_Shape aCutResult = aBaseCutBuilder->Shape();
461 TopoDS_Iterator aCheckIt(aCutResult);
462 if(aCheckIt.More()) {
463 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseCutBuilder)));
464 aResult = aCutResult;
465 if(aResult.ShapeType() == TopAbs_COMPOUND) {
466 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
468 if(aShapeTypeToExp == TopAbs_FACE) {
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);
479 if(aResult.ShapeType() == TopAbs_COMPOUND) {
480 GeomShapePtr aCompound(new GeomAPI_Shape);
481 aCompound->setImpl(new TopoDS_Shape(aResult));
482 ListOfShape aCompSolids, aFreeSolids;
483 GeomAlgoAPI_ShapeTools::combineShapes(aCompound, GeomAPI_Shape::COMPSOLID, aCompSolids, aFreeSolids);
484 if(aCompSolids.size() == 1 && aFreeSolids.size() == 0) {
485 aResult = aCompSolids.front()->impl<TopoDS_Shape>();
486 } else if (aCompSolids.size() > 1 || (aCompSolids.size() >= 1 && aFreeSolids.size() >= 1)) {
487 TopoDS_Compound aResultComp;
488 TopoDS_Builder aBuilder;
489 aBuilder.MakeCompound(aResultComp);
490 for(ListOfShape::const_iterator anIter = aCompSolids.cbegin(); anIter != aCompSolids.cend(); anIter++) {
491 aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
493 for(ListOfShape::const_iterator anIter = aFreeSolids.cbegin(); anIter != aFreeSolids.cend(); anIter++) {
494 aBuilder.Add(aResultComp, (*anIter)->impl<TopoDS_Shape>());
496 aResult = aResultComp;
500 // If after cut we got more than one solids then take closest to the center of mass of the base face.
501 aResult = findClosest(aResult, aBaseCentre);
504 for(TopExp_Explorer anExp(aResult, aShapeTypeToExp); anExp.More (); anExp.Next ()) {
505 const TopoDS_Shape& aShape = anExp.Current();
506 GeomShapePtr aGeomSh(new GeomAPI_Shape());
507 if(aShapeTypeToExp == TopAbs_VERTEX) {
508 gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
509 IntTools_Context anIntTools;
510 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aRotatedBoundingFace), Precision::Confusion()) == Standard_True) {
511 aGeomSh->setImpl(new TopoDS_Shape(aShape));
512 isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
514 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(aModifiedBaseShape), Precision::Confusion()) == Standard_True) {
515 aGeomSh->setImpl(new TopoDS_Shape(aShape));
516 isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
518 } else if(aShapeTypeToExp == TopAbs_EDGE) {
519 TopoDS_Edge anEdge = TopoDS::Edge(aShape);
520 BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(aRotatedBoundingFace));
521 anEdgeCheck.Perform();
522 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
523 aGeomSh->setImpl(new TopoDS_Shape(aShape));
524 isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
526 anEdgeCheck.Init(anEdge, TopoDS::Face(aModifiedBaseShape));
527 anEdgeCheck.Perform();
528 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
529 aGeomSh->setImpl(new TopoDS_Shape(aShape));
530 isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
533 Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
534 Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedBoundingFace));
535 Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(TopoDS::Face(aModifiedBaseShape));
536 if(aFaceSurface == aBoundingSurface) {
537 aGeomSh->setImpl(new TopoDS_Shape(aShape));
538 isFromFaceSet ? this->addFromShape(aGeomSh) : this->addToShape(aGeomSh);
540 if(aFaceSurface == aBaseSurface) {
541 aGeomSh->setImpl(new TopoDS_Shape(aShape));
542 isFromFaceSet ? this->addToShape(aGeomSh) : this->addFromShape(aGeomSh);
549 if(aResult.IsNull()) {
552 GeomShapePtr aShape(new GeomAPI_Shape());
553 aShape->setImpl(new TopoDS_Shape(aResult));
554 this->setShape(aShape);
558 //=================================================================================================
559 TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
561 if(!thePlane.Contains(thePoint, Precision::Confusion())) {
562 gp_XYZ aVec = thePoint.XYZ() - thePlane.Location().XYZ();
563 double aSign = aVec * thePlane.Axis().Direction().XYZ();
564 if(aSign < 0) thePlane.SetAxis(thePlane.Axis().Reversed());
567 BRepBuilderAPI_MakeFace aMakeFace(thePlane);
568 TopoDS_Face aResultFace = TopoDS::Face(aMakeFace.Shape());
573 //=================================================================================================
574 TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape)
579 BRep_Builder aBoundingBuilder;
580 if(theShape.ShapeType() == TopAbs_SHELL) {
581 aShell = TopoDS::Shell(theShape);
583 aBoundingBuilder.MakeShell(aShell);
584 aBoundingBuilder.Add(aShell, theShape);
586 aBoundingBuilder.MakeSolid(aSolid);
587 aBoundingBuilder.Add(aSolid, aShell);
592 //=================================================================================================
593 gp_Pnt centreOfMass(const TopoDS_Shape& theShape)
595 TopAbs_ShapeEnum aShType = theShape.ShapeType();
596 GProp_GProps aGProps;
598 if(aShType == TopAbs_EDGE || aShType == TopAbs_WIRE) {
599 BRepGProp::LinearProperties(theShape, aGProps);
600 } else if(aShType == TopAbs_FACE || aShType == TopAbs_SHELL) {
601 BRepGProp::SurfaceProperties(theShape, aGProps);
602 } else if(aShType == TopAbs_SOLID || aShType == TopAbs_COMPSOLID) {
603 BRepGProp::VolumeProperties(theShape, aGProps);
606 return aGProps.CentreOfMass();
609 //=================================================================================================
610 TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
612 TopoDS_Shape aResult = theShape;
614 if(theShape.ShapeType() == TopAbs_COMPOUND) {
615 double aMinDistance = Precision::Infinite();
618 for (TopoDS_Iterator anItr(theShape); anItr.More(); anItr.Next()) {
619 TopoDS_Shape aValue = anItr.Value();
620 aCentr = centreOfMass(aValue);
621 aCurDistance = aCentr.Distance(thePoint);
623 if(aCurDistance < aMinDistance) {
624 aMinDistance = aCurDistance;