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 static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
60 const TopoDS_Shape& theBase,
61 const TopAbs_ShapeEnum theType,
62 BRepPrimAPI_MakeRevol* theRevolBuilder);
64 static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
65 const TopoDS_Shape& theResult,
66 const TopAbs_ShapeEnum theType,
67 const TopoDS_Shape& theToFace,
68 const TopoDS_Shape& theFromFace);
70 static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
71 const TopoDS_Shape& theResult,
72 const TopAbs_ShapeEnum theType,
73 const TopoDS_Shape& theRotatedBoundingFace,
74 const TopoDS_Shape& theModifiedBaseShape,
75 const bool theIsFromFaceSet);
77 //==================================================================================================
78 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr theBaseShape,
79 const std::shared_ptr<GeomAPI_Ax1> theAxis,
80 const double theToAngle,
81 const double theFromAngle)
83 build(theBaseShape, theAxis, GeomShapePtr(), theToAngle, GeomShapePtr(), theFromAngle);
86 //==================================================================================================
87 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr theBaseShape,
88 const std::shared_ptr<GeomAPI_Ax1> theAxis,
89 const GeomShapePtr theToShape,
90 const double theToAngle,
91 const GeomShapePtr theFromShape,
92 const double theFromAngle)
94 build(theBaseShape, theAxis, theToShape, theToAngle, theFromShape, theFromAngle);
97 //==================================================================================================
98 void GeomAlgoAPI_Revolution::build(const GeomShapePtr& theBaseShape,
99 const std::shared_ptr<GeomAPI_Ax1>& theAxis,
100 const GeomShapePtr& theToShape,
101 const double theToAngle,
102 const GeomShapePtr& theFromShape,
103 const double theFromAngle)
105 if(!theBaseShape || !theAxis ||
106 (((!theFromShape && !theToShape) || (theFromShape && theToShape && theFromShape->isEqual(theToShape)))
107 && (theFromAngle == -theToAngle))) {
111 // Getting base shape.
112 const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
113 TopAbs_ShapeEnum aShapeTypeToExp;
114 switch(aBaseShape.ShapeType()) {
116 aShapeTypeToExp = TopAbs_VERTEX;
120 aShapeTypeToExp = TopAbs_EDGE;
124 aShapeTypeToExp = TopAbs_FACE;
126 case TopAbs_COMPOUND:
127 aShapeTypeToExp = TopAbs_COMPOUND;
134 gp_Ax1 anAxis = theAxis->impl<gp_Ax1>();
136 // Getting base plane.
137 Handle(Geom_Plane) aBasePlane;
138 BRepBuilderAPI_FindPlane aFindPlane(aBaseShape);
139 if(aShapeTypeToExp == TopAbs_FACE && aFindPlane.Found() == Standard_True) {
140 aBasePlane = aFindPlane.Plane();
142 gp_Pnt aPnt1 = anAxis.Location();
143 gp_Pnt aPnt2 = aPnt1;
144 aPnt2.Translate(anAxis.Direction());
147 for(TopExp_Explorer anExp(aBaseShape, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
148 aPnt3 = BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current()));
150 GC_MakePlane aMkPlane(aPnt1, aPnt2, aPnt3);
151 if(aMkPlane.IsDone() != Standard_True) {
155 aBasePlane = aMkPlane.Value();
159 if(aBasePlane.IsNull()) {
160 aPnt3 = centreOfMass(aBaseShape);
162 GC_MakePlane aMkPlane(aPnt1, aPnt2, aPnt3);
163 if(aMkPlane.IsDone() != Standard_True) {
167 aBasePlane = aMkPlane.Value();
171 if(aShapeTypeToExp == TopAbs_FACE) {
172 if(aBasePlane->Axis().Angle(anAxis) < Precision::Confusion()) {
177 gp_Pnt aBaseCentre = GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape)->impl<gp_Pnt>();
179 TopoDS_Shape aResult;
180 if(!theFromShape && !theToShape) { // Case 1: When only angles was set.
181 // Rotating base face with the negative value of "from angle".
183 aBaseTrsf.SetRotation(anAxis, -theFromAngle / 180.0 * M_PI);
184 BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBaseShape,
187 if(!aBaseTransform) {
190 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseTransform)));
191 if(!aBaseTransform->IsDone()) {
194 TopoDS_Shape aRotatedBase = aBaseTransform->Shape();
196 // Making revolution to the angle equal to the sum of "from angle" and "to angle".
197 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aRotatedBase,
199 (theFromAngle + theToAngle) / 180 * M_PI,
204 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
205 if(!aRevolBuilder->IsDone()) {
208 aResult = aRevolBuilder->Shape();
211 if(aShapeTypeToExp == TopAbs_COMPOUND) {
212 storeGenerationHistory(this, aRotatedBase, TopAbs_EDGE, aRevolBuilder);
213 storeGenerationHistory(this, aRotatedBase, TopAbs_FACE, aRevolBuilder);
215 storeGenerationHistory(this, aRotatedBase, aShapeTypeToExp, aRevolBuilder);
217 } else if(theFromShape && theToShape) { // Case 2: When both bounding planes were set.
218 // Making revolution to the 360 angle.
219 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
223 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
224 if(!aRevolBuilder->IsDone()) {
227 aResult = aRevolBuilder->Shape();
229 // Getting bounding faces.
230 TopoDS_Face aFromFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
231 TopoDS_Face aToFace = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
233 // Getting planes from bounding face.
234 GeomLib_IsPlanarSurface isFromPlanar(BRep_Tool::Surface(aFromFace));
235 GeomLib_IsPlanarSurface isToPlanar(BRep_Tool::Surface(aToFace));
236 if(!isFromPlanar.IsPlanar() || !isToPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution bounding
239 gp_Pln aFromPln = isFromPlanar.Plan();
240 gp_Pln aToPln = isToPlanar.Plan();
242 // Orienting bounding planes properly so that the center of mass of the base face stays
243 // on the result shape after cut.
244 aFromFace = makeFaceFromPlane(aFromPln, aBaseCentre);
245 aToFace = makeFaceFromPlane(aToPln, aBaseCentre);
247 // Making solids from bounding planes and putting them in compound.
248 TopoDS_Shape aFromSolid = makeSolidFromShape(aFromFace);
249 TopoDS_Shape aToSolid = makeSolidFromShape(aToFace);
251 // Rotating bounding planes to the specified angle.
254 double aFromRotAngle = ((aFromPln.Axis().Direction() * aBasePlane->Axis().Direction()) > 0) ? -theFromAngle : theFromAngle;
255 double aToRotAngle = ((aToPln.Axis().Direction() * aBasePlane->Axis().Direction()) > 0) ? -theToAngle : theToAngle;
256 aFromTrsf.SetRotation(anAxis,aFromRotAngle / 180.0 * M_PI);
257 aToTrsf.SetRotation(anAxis, aToRotAngle / 180.0 * M_PI);
258 BRepBuilderAPI_Transform aFromTransform(aFromSolid, aFromTrsf, true);
259 BRepBuilderAPI_Transform aToTransform(aToSolid, aToTrsf, true);
260 TopoDS_Shape aRotatedFromFace = aFromTransform.Modified(aFromFace).First();
261 TopoDS_Shape aRotatedToFace = aToTransform.Modified(aToFace).First();
262 aFromSolid = aFromTransform.Shape();
263 aToSolid = aToTransform.Shape();
265 // Cutting revolution with from plane.
266 BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
267 aFromCutBuilder->Build();
268 if(!aFromCutBuilder->IsDone()) {
271 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aFromCutBuilder)));
272 aResult = aFromCutBuilder->Shape();
273 if(aResult.ShapeType() == TopAbs_COMPOUND) {
274 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
277 // Cutting revolution with to plane.
278 BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
279 aToCutBuilder->Build();
280 if(!aToCutBuilder->IsDone()) {
283 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aToCutBuilder)));
284 aResult = aToCutBuilder->Shape();
285 TopoDS_Iterator aCheckIt(aResult);
286 if(!aCheckIt.More()) {
289 if(aResult.ShapeType() == TopAbs_COMPOUND) {
290 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
292 if(aResult.ShapeType() == TopAbs_COMPOUND) {
293 std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
294 aGeomShape->setImpl(new TopoDS_Shape(aResult));
295 ListOfShape aCompSolids, aFreeSolids;
296 aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
297 GeomAPI_Shape::COMPSOLID,
300 aResult = aGeomShape->impl<TopoDS_Shape>();
303 // If after cut we got more than one solids then take closest to the center of mass of the base face.
304 aResult = findClosest(aResult, aBaseCentre);
307 if(aShapeTypeToExp == TopAbs_COMPOUND) {
308 storeGenerationHistory(this, aResult, TopAbs_EDGE, aRotatedToFace, aRotatedFromFace);
309 storeGenerationHistory(this, aResult, TopAbs_FACE, aRotatedToFace, aRotatedFromFace);
311 storeGenerationHistory(this, aResult, aShapeTypeToExp, aRotatedToFace, aRotatedFromFace);
313 } else { //Case 3: When only one bounding plane was set.
314 // Making revolution to the 360 angle.
315 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
319 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
320 if(!aRevolBuilder->IsDone()) {
323 aResult = aRevolBuilder->Shape();
325 // Getting bounding face.
326 TopoDS_Face aBoundingFace;
327 bool isFromFaceSet = false;
329 aBoundingFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
330 isFromFaceSet = true;
331 } else if(theToShape) {
332 aBoundingFace = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
335 // Getting plane from bounding face.
336 GeomLib_IsPlanarSurface isBoundingPlanar(BRep_Tool::Surface(aBoundingFace));
337 if(!isBoundingPlanar.IsPlanar()) { // non-planar shapes is not supported for revolution bounding
340 gp_Pln aBoundingPln = isBoundingPlanar.Plan();
342 // Orienting bounding plane properly so that the center of mass of the base face stays
343 // on the result shape after cut.
344 aBoundingFace = makeFaceFromPlane(aBoundingPln, aBaseCentre);
346 // Making solid from bounding plane.
347 TopoDS_Shape aBoundingSolid = makeSolidFromShape(aBoundingFace);
349 // Rotating bounding plane to the specified angle.
350 double aBoundingRotAngle = isFromFaceSet ? theFromAngle : theToAngle;
351 if(aBoundingPln.Axis().IsParallel(aBasePlane->Axis(), Precision::Confusion())) {
352 if(isFromFaceSet) aBoundingRotAngle = -aBoundingRotAngle;
354 double aSign = (aBoundingPln.Axis().Direction() ^ aBasePlane->Axis().Direction()) *
356 if((aSign <= 0 && !isFromFaceSet) || (aSign > 0 && isFromFaceSet)) {
357 aBoundingRotAngle = -aBoundingRotAngle;
360 gp_Trsf aBoundingTrsf;
361 aBoundingTrsf.SetRotation(anAxis, aBoundingRotAngle / 180.0 * M_PI);
362 BRepBuilderAPI_Transform aBoundingTransform(aBoundingSolid, aBoundingTrsf, true);
363 TopoDS_Shape aRotatedBoundingFace = aBoundingTransform.Modified(aBoundingFace).First();
364 aBoundingSolid = aBoundingTransform.Shape();
366 // Cutting revolution with bounding plane.
367 BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aResult, aBoundingSolid);
368 aBoundingCutBuilder->Build();
369 if(!aBoundingCutBuilder->IsDone()) {
372 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBoundingCutBuilder)));
373 aResult = aBoundingCutBuilder->Shape();
374 if(aResult.ShapeType() == TopAbs_COMPOUND) {
375 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
379 if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
380 const TopTools_ListOfShape& aBndShapes = aBoundingCutBuilder->Modified(aBoundingFace);
381 for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) {
382 GeomShapePtr aShape(new GeomAPI_Shape());
383 aShape->setImpl(new TopoDS_Shape(anIt.Value()));
384 isFromFaceSet ? this->addFromShape(aShape) : this->addToShape(aShape);
388 // Try to cut with base face. If it can not be done then keep result of cut with bounding plane.
389 TopoDS_Shape aModifiedBaseShape;
390 if(aShapeTypeToExp != TopAbs_FACE) {
392 GeomShapePtr aSh(new GeomAPI_Shape());
393 aSh->setImpl(new TopoDS_Shape(aBaseShape));
394 std::shared_ptr<GeomAPI_Pnt> theCenter(new GeomAPI_Pnt(aBasePlane->Location().X(),
395 aBasePlane->Location().Y(),
396 aBasePlane->Location().Z()));
397 std::shared_ptr<GeomAPI_Dir> theNormal(new GeomAPI_Dir(aBasePlane->Axis().Direction().X(),
398 aBasePlane->Axis().Direction().Y(),
399 aBasePlane->Axis().Direction().Z()));
400 GeomShapePtr aPln = GeomAlgoAPI_FaceBuilder::planarFace(theCenter, theNormal);
401 aList.push_back(aSh);
402 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(aList);
403 aSh = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPln, aBoundingPoints);
404 aModifiedBaseShape = aSh->impl<TopoDS_Shape>();
406 aModifiedBaseShape = aBaseShape;
409 if(aModifiedBaseShape.ShapeType() == TopAbs_FACE) {
410 aModifiedBaseShape.Orientation(TopAbs_REVERSED);
413 aMirrorTrsf.SetMirror(aBasePlane->Position().Ax2());
414 BRepBuilderAPI_Transform aMirrorTransform(aModifiedBaseShape, aMirrorTrsf, true);
415 aModifiedBaseShape = aMirrorTransform.Shape();
419 // Making solid from base face.
420 TopoDS_Shape aBaseSolid = makeSolidFromShape(aModifiedBaseShape);
422 // Rotating base face to the specified angle.
424 double aBaseRotAngle = isFromFaceSet ? theToAngle : -theFromAngle;
425 aBaseTrsf.SetRotation(anAxis, aBaseRotAngle / 180.0 * M_PI);
426 BRepBuilderAPI_Transform aBaseTransform(aBaseSolid, aBaseTrsf, true);
427 aBaseSolid = aBaseTransform.Shape();
429 // Cutting revolution with base.
430 BRepAlgoAPI_Cut* aBaseCutBuilder = new BRepAlgoAPI_Cut(aResult, aBaseSolid);
431 aBaseCutBuilder->Build();
432 if(aBaseCutBuilder->IsDone()) {
433 TopoDS_Shape aCutResult = aBaseCutBuilder->Shape();
434 TopoDS_Iterator aCheckIt(aCutResult);
435 if(aCheckIt.More()) {
436 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseCutBuilder)));
437 aResult = aCutResult;
438 if(aResult.ShapeType() == TopAbs_COMPOUND) {
439 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
441 if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
442 const TopTools_ListOfShape& aBsShapes = aBaseCutBuilder->Modified(aBoundingFace);
443 for(TopTools_ListIteratorOfListOfShape anIt(aBsShapes); anIt.More(); anIt.Next()) {
444 GeomShapePtr aShape(new GeomAPI_Shape());
445 aShape->setImpl(new TopoDS_Shape(anIt.Value()));
446 isFromFaceSet ? this->addToShape(aShape) : this->addFromShape(aShape);
452 if(aResult.ShapeType() == TopAbs_COMPOUND) {
453 std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
454 aGeomShape->setImpl(new TopoDS_Shape(aResult));
455 ListOfShape aCompSolids, aFreeSolids;
456 aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
457 GeomAPI_Shape::COMPSOLID,
460 aResult = aGeomShape->impl<TopoDS_Shape>();
463 // If after cut we got more than one solids then take closest to the center of mass of the base face.
464 aResult = findClosest(aResult, aBaseCentre);
467 if(aShapeTypeToExp == TopAbs_COMPOUND) {
468 storeGenerationHistory(this, aResult, TopAbs_EDGE, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
469 storeGenerationHistory(this, aResult, TopAbs_FACE, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
471 storeGenerationHistory(this, aResult, aShapeTypeToExp, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
476 if(aResult.IsNull()) {
479 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
480 GeomShapePtr aShape(new GeomAPI_Shape());
481 aShape->setImpl(new TopoDS_Shape(aResult));
482 this->setShape(aShape);
486 //==================================================================================================
487 TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
489 if(!thePlane.Contains(thePoint, Precision::Confusion())) {
490 gp_XYZ aVec = thePoint.XYZ() - thePlane.Location().XYZ();
491 double aSign = aVec * thePlane.Axis().Direction().XYZ();
492 if(aSign < 0) thePlane.SetAxis(thePlane.Axis().Reversed());
495 BRepBuilderAPI_MakeFace aMakeFace(thePlane);
496 TopoDS_Face aResultFace = TopoDS::Face(aMakeFace.Shape());
501 //==================================================================================================
502 TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape)
507 BRep_Builder aBoundingBuilder;
508 if(theShape.ShapeType() == TopAbs_SHELL) {
509 aShell = TopoDS::Shell(theShape);
511 aBoundingBuilder.MakeShell(aShell);
512 aBoundingBuilder.Add(aShell, theShape);
514 aBoundingBuilder.MakeSolid(aSolid);
515 aBoundingBuilder.Add(aSolid, aShell);
520 //==================================================================================================
521 gp_Pnt centreOfMass(const TopoDS_Shape& theShape)
523 TopAbs_ShapeEnum aShType = theShape.ShapeType();
524 GProp_GProps aGProps;
526 if(aShType == TopAbs_EDGE || aShType == TopAbs_WIRE) {
527 BRepGProp::LinearProperties(theShape, aGProps);
528 } else if(aShType == TopAbs_FACE || aShType == TopAbs_SHELL) {
529 BRepGProp::SurfaceProperties(theShape, aGProps);
530 } else if(aShType == TopAbs_SOLID || aShType == TopAbs_COMPSOLID) {
531 BRepGProp::VolumeProperties(theShape, aGProps);
534 return aGProps.CentreOfMass();
537 //==================================================================================================
538 TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
540 TopoDS_Shape aResult = theShape;
542 if(theShape.ShapeType() == TopAbs_COMPOUND) {
543 double aMinDistance = Precision::Infinite();
546 for (TopoDS_Iterator anItr(theShape); anItr.More(); anItr.Next()) {
547 TopoDS_Shape aValue = anItr.Value();
548 aCentr = centreOfMass(aValue);
549 aCurDistance = aCentr.Distance(thePoint);
551 if(aCurDistance < aMinDistance) {
552 aMinDistance = aCurDistance;
561 //==================================================================================================
562 void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
563 const TopoDS_Shape& theBase,
564 const TopAbs_ShapeEnum theType,
565 BRepPrimAPI_MakeRevol* theRevolBuilder)
567 for(TopExp_Explorer anExp(theBase, theType); anExp.More(); anExp.Next()) {
568 const TopoDS_Shape& aShape = anExp.Current();
569 GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
570 aFromShape->setImpl(new TopoDS_Shape(theRevolBuilder->FirstShape(aShape)));
571 aToShape->setImpl(new TopoDS_Shape(theRevolBuilder->LastShape(aShape)));
572 theRevolutionAlgo->addFromShape(aFromShape);
573 theRevolutionAlgo->addToShape(aToShape);
577 //==================================================================================================
578 void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
579 const TopoDS_Shape& theResult,
580 const TopAbs_ShapeEnum theType,
581 const TopoDS_Shape& theToFace,
582 const TopoDS_Shape& theFromFace)
584 for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
585 const TopoDS_Shape& aShape = anExp.Current();
586 GeomShapePtr aGeomSh(new GeomAPI_Shape());
587 if(theType == TopAbs_VERTEX) {
588 gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
589 IntTools_Context anIntTools;
590 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theToFace), Precision::Confusion()) == Standard_True) {
591 aGeomSh->setImpl(new TopoDS_Shape(aShape));
592 theRevolutionAlgo->addToShape(aGeomSh);
594 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theFromFace), Precision::Confusion()) == Standard_True) {
595 aGeomSh->setImpl(new TopoDS_Shape(aShape));
596 theRevolutionAlgo->addFromShape(aGeomSh);
598 } else if(theType == TopAbs_EDGE) {
599 TopoDS_Edge anEdge = TopoDS::Edge(aShape);
600 BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theToFace));
601 anEdgeCheck.Perform();
602 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
603 aGeomSh->setImpl(new TopoDS_Shape(aShape));
604 theRevolutionAlgo->addToShape(aGeomSh);
606 anEdgeCheck.Init(anEdge, TopoDS::Face(theFromFace));
607 anEdgeCheck.Perform();
608 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
609 aGeomSh->setImpl(new TopoDS_Shape(aShape));
610 theRevolutionAlgo->addFromShape(aGeomSh);
613 Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
614 Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(theFromFace));
615 Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(theToFace));
616 if(aFaceSurface == aFromSurface) {
617 aGeomSh->setImpl(new TopoDS_Shape(aShape));
618 theRevolutionAlgo->addFromShape(aGeomSh);
620 if(aFaceSurface == aToSurface) {
621 aGeomSh->setImpl(new TopoDS_Shape(aShape));
622 theRevolutionAlgo->addToShape(aGeomSh);
628 void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
629 const TopoDS_Shape& theResult,
630 const TopAbs_ShapeEnum theType,
631 const TopoDS_Shape& theRotatedBoundingFace,
632 const TopoDS_Shape& theModifiedBaseShape,
633 const bool theIsFromFaceSet)
635 for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
636 const TopoDS_Shape& aShape = anExp.Current();
637 GeomShapePtr aGeomSh(new GeomAPI_Shape());
638 if(theType == TopAbs_VERTEX) {
639 gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
640 IntTools_Context anIntTools;
641 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theRotatedBoundingFace), Precision::Confusion()) == Standard_True) {
642 aGeomSh->setImpl(new TopoDS_Shape(aShape));
643 theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
645 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theModifiedBaseShape), Precision::Confusion()) == Standard_True) {
646 aGeomSh->setImpl(new TopoDS_Shape(aShape));
647 theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
649 } else if(theType == TopAbs_EDGE) {
650 TopoDS_Edge anEdge = TopoDS::Edge(aShape);
651 BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theRotatedBoundingFace));
652 anEdgeCheck.Perform();
653 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
654 aGeomSh->setImpl(new TopoDS_Shape(aShape));
655 theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
657 anEdgeCheck.Init(anEdge, TopoDS::Face(theModifiedBaseShape));
658 anEdgeCheck.Perform();
659 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
660 aGeomSh->setImpl(new TopoDS_Shape(aShape));
661 theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
664 Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
665 Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(theRotatedBoundingFace));
666 Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(TopoDS::Face(theModifiedBaseShape));
667 if(aFaceSurface == aBoundingSurface) {
668 aGeomSh->setImpl(new TopoDS_Shape(aShape));
669 theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
671 if(aFaceSurface == aBaseSurface) {
672 aGeomSh->setImpl(new TopoDS_Shape(aShape));
673 theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);