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_Pln.h>
11 #include <GeomAPI_ShapeExplorer.h>
12 #include <GeomAlgoAPI_DFLoader.h>
13 #include <GeomAlgoAPI_FaceBuilder.h>
14 #include <GeomAlgoAPI_MakeShapeList.h>
15 #include <GeomAlgoAPI_ShapeTools.h>
17 #include <BRep_Builder.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepAlgoAPI_Cut.hxx>
20 #include <BRepBuilderAPI_FindPlane.hxx>
21 #include <BRepBuilderAPI_MakeFace.hxx>
22 #include <BRepBuilderAPI_Transform.hxx>
23 #include <BRepCheck_Analyzer.hxx>
24 #include <Geom_Curve.hxx>
25 #include <Geom2d_Curve.hxx>
26 #include <BRepLib_CheckCurveOnSurface.hxx>
27 #include <BRepPrimAPI_MakeRevol.hxx>
28 #include <BRepGProp.hxx>
29 #include <GC_MakePlane.hxx>
30 #include <Geom_Plane.hxx>
31 #include <GeomLib_IsPlanarSurface.hxx>
33 #include <GProp_GProps.hxx>
34 #include <IntTools_Context.hxx>
35 #include <TopExp_Explorer.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopTools_ListIteratorOfListOfShape.hxx>
40 /// \brief Constructs infinite face from thePlane, and with axis located on the same side
41 /// of the plane as thePoint. Modifies thePlane axis direction.
42 /// \param[in,out] thePlane plane to construct face.
43 /// \param[in] thePoint point to locate plane axis.
44 /// \return constructed face.
45 static TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint);
47 /// \return solid created from face or shell.
48 static TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape);
50 /// \brief return centre of mass for theShape.
51 /// \param[in] theShape shape.
52 static gp_Pnt centreOfMass(const TopoDS_Shape& theShape);
54 /// \brief Selects solid from theShape with closest center of mass to thePoint
55 /// \param[in] theShape compound with solids.
56 /// \param[in] thePoint point.
58 static TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint);
60 static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
61 const TopoDS_Shape& theBase,
62 const TopAbs_ShapeEnum theType,
63 BRepPrimAPI_MakeRevol* theRevolBuilder);
65 static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
66 const TopoDS_Shape& theResult,
67 const TopAbs_ShapeEnum theType,
68 const TopoDS_Shape& theToFace,
69 const TopoDS_Shape& theFromFace);
71 static void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
72 const TopoDS_Shape& theResult,
73 const TopAbs_ShapeEnum theType,
74 const TopoDS_Shape& theRotatedBoundingFace,
75 const TopoDS_Shape& theModifiedBaseShape,
76 const bool theIsFromFaceSet);
78 //==================================================================================================
79 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr theBaseShape,
80 const std::shared_ptr<GeomAPI_Ax1> theAxis,
81 const double theToAngle,
82 const double theFromAngle)
84 build(theBaseShape, theAxis, GeomShapePtr(), theToAngle, GeomShapePtr(), theFromAngle);
87 //==================================================================================================
88 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(const GeomShapePtr theBaseShape,
89 const std::shared_ptr<GeomAPI_Ax1> theAxis,
90 const GeomShapePtr theToShape,
91 const double theToAngle,
92 const GeomShapePtr theFromShape,
93 const double theFromAngle)
95 build(theBaseShape, theAxis, theToShape, theToAngle, theFromShape, theFromAngle);
98 //==================================================================================================
99 void GeomAlgoAPI_Revolution::build(const GeomShapePtr& theBaseShape,
100 const std::shared_ptr<GeomAPI_Ax1>& theAxis,
101 const GeomShapePtr& theToShape,
102 const double theToAngle,
103 const GeomShapePtr& theFromShape,
104 const double theFromAngle)
106 if(!theBaseShape || !theAxis ||
107 (((!theFromShape && !theToShape) || (theFromShape && theToShape && theFromShape->isEqual(theToShape)))
108 && (theFromAngle == -theToAngle))) {
112 // Getting base shape.
113 const TopoDS_Shape& aBaseShape = theBaseShape->impl<TopoDS_Shape>();
114 TopAbs_ShapeEnum aShapeTypeToExp;
115 switch(aBaseShape.ShapeType()) {
117 aShapeTypeToExp = TopAbs_VERTEX;
121 aShapeTypeToExp = TopAbs_EDGE;
125 aShapeTypeToExp = TopAbs_FACE;
127 case TopAbs_COMPOUND:
128 aShapeTypeToExp = TopAbs_COMPOUND;
135 gp_Ax1 anAxis = theAxis->impl<gp_Ax1>();
137 // Getting base plane.
138 Handle(Geom_Plane) aBasePlane;
139 BRepBuilderAPI_FindPlane aFindPlane(aBaseShape);
140 if(aShapeTypeToExp == TopAbs_FACE && aFindPlane.Found() == Standard_True) {
141 aBasePlane = aFindPlane.Plane();
143 gp_Pnt aPnt1 = anAxis.Location();
144 gp_Pnt aPnt2 = aPnt1;
145 aPnt2.Translate(anAxis.Direction());
148 for(TopExp_Explorer anExp(aBaseShape, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
149 aPnt3 = BRep_Tool::Pnt(TopoDS::Vertex(anExp.Current()));
151 GC_MakePlane aMkPlane(aPnt1, aPnt2, aPnt3);
152 if(aMkPlane.IsDone() != Standard_True) {
156 aBasePlane = aMkPlane.Value();
160 if(aBasePlane.IsNull()) {
161 aPnt3 = centreOfMass(aBaseShape);
163 GC_MakePlane aMkPlane(aPnt1, aPnt2, aPnt3);
164 if(aMkPlane.IsDone() != Standard_True) {
168 aBasePlane = aMkPlane.Value();
172 if(aShapeTypeToExp == TopAbs_FACE) {
173 if(aBasePlane->Axis().Angle(anAxis) < Precision::Confusion()) {
178 gp_Pnt aBaseCentre = GeomAlgoAPI_ShapeTools::centreOfMass(theBaseShape)->impl<gp_Pnt>();
180 TopoDS_Shape aResult;
181 if(!theFromShape && !theToShape) { // Case 1: When only angles was set.
182 // Rotating base face with the negative value of "from angle".
184 aBaseTrsf.SetRotation(anAxis, -theFromAngle / 180.0 * M_PI);
185 BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBaseShape,
188 if(!aBaseTransform) {
191 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseTransform)));
192 if(!aBaseTransform->IsDone()) {
195 TopoDS_Shape aRotatedBase = aBaseTransform->Shape();
197 // Making revolution to the angle equal to the sum of "from angle" and "to angle".
198 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aRotatedBase,
200 (theFromAngle + theToAngle) / 180 * M_PI,
205 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
206 if(!aRevolBuilder->IsDone()) {
209 aResult = aRevolBuilder->Shape();
212 if(aShapeTypeToExp == TopAbs_COMPOUND) {
213 storeGenerationHistory(this, aRotatedBase, TopAbs_EDGE, aRevolBuilder);
214 storeGenerationHistory(this, aRotatedBase, TopAbs_FACE, aRevolBuilder);
216 storeGenerationHistory(this, aRotatedBase, aShapeTypeToExp, aRevolBuilder);
218 } else if(theFromShape && theToShape) { // Case 2: When both bounding planes were set.
219 // Making revolution to the 360 angle.
220 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
224 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
225 if(!aRevolBuilder->IsDone()) {
228 aResult = aRevolBuilder->Shape();
230 // Getting bounding faces.
231 TopoDS_Face aFromFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
232 TopoDS_Face aToFace = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
234 // Getting planes from bounding face.
235 GeomLib_IsPlanarSurface isFromPlanar(BRep_Tool::Surface(aFromFace));
236 GeomLib_IsPlanarSurface isToPlanar(BRep_Tool::Surface(aToFace));
237 if(!isFromPlanar.IsPlanar() || !isToPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution bounding
241 std::shared_ptr<GeomAPI_Face> aGeomFromFace(new GeomAPI_Face(theFromShape));
242 std::shared_ptr<GeomAPI_Face> aGeomToFace(new GeomAPI_Face(theToShape));
244 gp_Pln aFromPln = aGeomFromFace->getPlane()->impl<gp_Pln>();
245 gp_Pln aToPln = aGeomToFace->getPlane()->impl<gp_Pln>();
247 // Orienting bounding planes properly so that the center of mass of the base face stays
248 // on the result shape after cut.
249 aFromFace = makeFaceFromPlane(aFromPln, aBaseCentre);
250 aToFace = makeFaceFromPlane(aToPln, aBaseCentre);
252 // Making solids from bounding planes and putting them in compound.
253 TopoDS_Shape aFromSolid = makeSolidFromShape(aFromFace);
254 TopoDS_Shape aToSolid = makeSolidFromShape(aToFace);
256 // Rotating bounding planes to the specified angle.
259 double aFromRotAngle = ((aFromPln.Axis().Direction() * aBasePlane->Axis().Direction()) > 0) ? -theFromAngle : theFromAngle;
260 double aToRotAngle = ((aToPln.Axis().Direction() * aBasePlane->Axis().Direction()) > 0) ? -theToAngle : theToAngle;
261 aFromTrsf.SetRotation(anAxis,aFromRotAngle / 180.0 * M_PI);
262 aToTrsf.SetRotation(anAxis, aToRotAngle / 180.0 * M_PI);
263 BRepBuilderAPI_Transform aFromTransform(aFromSolid, aFromTrsf, true);
264 BRepBuilderAPI_Transform aToTransform(aToSolid, aToTrsf, true);
265 TopoDS_Shape aRotatedFromFace = aFromTransform.Modified(aFromFace).First();
266 TopoDS_Shape aRotatedToFace = aToTransform.Modified(aToFace).First();
267 aFromSolid = aFromTransform.Shape();
268 aToSolid = aToTransform.Shape();
270 // Cutting revolution with from plane.
271 BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aResult, aFromSolid);
272 aFromCutBuilder->Build();
273 if(!aFromCutBuilder->IsDone()) {
276 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aFromCutBuilder)));
277 aResult = aFromCutBuilder->Shape();
278 if(aResult.ShapeType() == TopAbs_COMPOUND) {
279 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
282 // Cutting revolution with to plane.
283 BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
284 aToCutBuilder->Build();
285 if(!aToCutBuilder->IsDone()) {
288 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aToCutBuilder)));
289 aResult = aToCutBuilder->Shape();
290 TopoDS_Iterator aCheckIt(aResult);
291 if(!aCheckIt.More()) {
294 if(aResult.ShapeType() == TopAbs_COMPOUND) {
295 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
297 if(aResult.ShapeType() == TopAbs_COMPOUND) {
298 std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
299 aGeomShape->setImpl(new TopoDS_Shape(aResult));
300 ListOfShape aCompSolids, aFreeSolids;
301 aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
302 GeomAPI_Shape::COMPSOLID,
305 aResult = aGeomShape->impl<TopoDS_Shape>();
308 // If after cut we got more than one solids then take closest to the center of mass of the base face.
309 aResult = findClosest(aResult, aBaseCentre);
312 if(aShapeTypeToExp == TopAbs_COMPOUND) {
313 storeGenerationHistory(this, aResult, TopAbs_EDGE, aRotatedToFace, aRotatedFromFace);
314 storeGenerationHistory(this, aResult, TopAbs_FACE, aRotatedToFace, aRotatedFromFace);
316 storeGenerationHistory(this, aResult, aShapeTypeToExp, aRotatedToFace, aRotatedFromFace);
318 } else { //Case 3: When only one bounding plane was set.
319 // Making revolution to the 360 angle.
320 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBaseShape, anAxis, 2 * M_PI, Standard_True);
324 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aRevolBuilder)));
325 if(!aRevolBuilder->IsDone()) {
328 aResult = aRevolBuilder->Shape();
330 // Getting bounding face.
331 bool isFromFaceSet = false;
332 std::shared_ptr<GeomAPI_Face> aGeomBoundingFace;
334 aGeomBoundingFace.reset(new GeomAPI_Face(theFromShape));
335 isFromFaceSet = true;
336 } else if(theToShape) {
337 aGeomBoundingFace.reset(new GeomAPI_Face(theToShape));
339 TopoDS_Face aBoundingFace = TopoDS::Face(aGeomBoundingFace->impl<TopoDS_Shape>());
341 // Getting plane from bounding face.
342 GeomLib_IsPlanarSurface isBoundingPlanar(BRep_Tool::Surface(aBoundingFace));
343 if(!isBoundingPlanar.IsPlanar()) { // non-planar shapes is not supported for revolution bounding
347 gp_Pln aBoundingPln = aGeomBoundingFace->getPlane()->impl<gp_Pln>();
349 // Orienting bounding plane properly so that the center of mass of the base face stays
350 // on the result shape after cut.
351 aBoundingFace = makeFaceFromPlane(aBoundingPln, aBaseCentre);
353 // Making solid from bounding plane.
354 TopoDS_Shape aBoundingSolid = makeSolidFromShape(aBoundingFace);
356 // Rotating bounding plane to the specified angle.
357 double aBoundingRotAngle = isFromFaceSet ? theFromAngle : theToAngle;
358 if(aBoundingPln.Axis().IsParallel(aBasePlane->Axis(), Precision::Confusion())) {
359 if(isFromFaceSet) aBoundingRotAngle = -aBoundingRotAngle;
361 double aSign = (aBoundingPln.Axis().Direction() ^ aBasePlane->Axis().Direction()) *
363 if((aSign <= 0 && !isFromFaceSet) || (aSign > 0 && isFromFaceSet)) {
364 aBoundingRotAngle = -aBoundingRotAngle;
367 gp_Trsf aBoundingTrsf;
368 aBoundingTrsf.SetRotation(anAxis, aBoundingRotAngle / 180.0 * M_PI);
369 BRepBuilderAPI_Transform aBoundingTransform(aBoundingSolid, aBoundingTrsf, true);
370 TopoDS_Shape aRotatedBoundingFace = aBoundingTransform.Modified(aBoundingFace).First();
371 aBoundingSolid = aBoundingTransform.Shape();
373 // Cutting revolution with bounding plane.
374 BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aResult, aBoundingSolid);
375 aBoundingCutBuilder->Build();
376 if(!aBoundingCutBuilder->IsDone()) {
379 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBoundingCutBuilder)));
380 aResult = aBoundingCutBuilder->Shape();
381 if(aResult.ShapeType() == TopAbs_COMPOUND) {
382 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
386 if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
387 const TopTools_ListOfShape& aBndShapes = aBoundingCutBuilder->Modified(aBoundingFace);
388 for(TopTools_ListIteratorOfListOfShape anIt(aBndShapes); anIt.More(); anIt.Next()) {
389 GeomShapePtr aShape(new GeomAPI_Shape());
390 aShape->setImpl(new TopoDS_Shape(anIt.Value()));
391 isFromFaceSet ? this->addFromShape(aShape) : this->addToShape(aShape);
395 // Try to cut with base face. If it can not be done then keep result of cut with bounding plane.
396 TopoDS_Shape aModifiedBaseShape;
397 if(aShapeTypeToExp != TopAbs_FACE) {
399 GeomShapePtr aSh(new GeomAPI_Shape());
400 aSh->setImpl(new TopoDS_Shape(aBaseShape));
401 std::shared_ptr<GeomAPI_Pnt> theCenter(new GeomAPI_Pnt(aBasePlane->Location().X(),
402 aBasePlane->Location().Y(),
403 aBasePlane->Location().Z()));
404 std::shared_ptr<GeomAPI_Dir> theNormal(new GeomAPI_Dir(aBasePlane->Axis().Direction().X(),
405 aBasePlane->Axis().Direction().Y(),
406 aBasePlane->Axis().Direction().Z()));
407 GeomShapePtr aPln = GeomAlgoAPI_FaceBuilder::planarFace(theCenter, theNormal);
408 aList.push_back(aSh);
409 std::list<std::shared_ptr<GeomAPI_Pnt> > aBoundingPoints = GeomAlgoAPI_ShapeTools::getBoundingBox(aList);
410 aSh = GeomAlgoAPI_ShapeTools::fitPlaneToBox(aPln, aBoundingPoints);
411 aModifiedBaseShape = aSh->impl<TopoDS_Shape>();
413 aModifiedBaseShape = aBaseShape;
416 if(aModifiedBaseShape.ShapeType() == TopAbs_FACE) {
417 aModifiedBaseShape.Orientation(TopAbs_REVERSED);
420 aMirrorTrsf.SetMirror(aBasePlane->Position().Ax2());
421 BRepBuilderAPI_Transform aMirrorTransform(aModifiedBaseShape, aMirrorTrsf, true);
422 aModifiedBaseShape = aMirrorTransform.Shape();
426 // Making solid from base face.
427 TopoDS_Shape aBaseSolid = makeSolidFromShape(aModifiedBaseShape);
429 // Rotating base face to the specified angle.
431 double aBaseRotAngle = isFromFaceSet ? theToAngle : -theFromAngle;
432 aBaseTrsf.SetRotation(anAxis, aBaseRotAngle / 180.0 * M_PI);
433 BRepBuilderAPI_Transform aBaseTransform(aBaseSolid, aBaseTrsf, true);
434 aBaseSolid = aBaseTransform.Shape();
436 // Cutting revolution with base.
437 BRepAlgoAPI_Cut* aBaseCutBuilder = new BRepAlgoAPI_Cut(aResult, aBaseSolid);
438 aBaseCutBuilder->Build();
439 if(aBaseCutBuilder->IsDone()) {
440 TopoDS_Shape aCutResult = aBaseCutBuilder->Shape();
441 TopoDS_Iterator aCheckIt(aCutResult);
442 if(aCheckIt.More()) {
443 this->appendAlgo(std::shared_ptr<GeomAlgoAPI_MakeShape>(new GeomAlgoAPI_MakeShape(aBaseCutBuilder)));
444 aResult = aCutResult;
445 if(aResult.ShapeType() == TopAbs_COMPOUND) {
446 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
448 if(aShapeTypeToExp == TopAbs_FACE || aShapeTypeToExp == TopAbs_COMPOUND) {
449 const TopTools_ListOfShape& aBsShapes = aBaseCutBuilder->Modified(aBoundingFace);
450 for(TopTools_ListIteratorOfListOfShape anIt(aBsShapes); anIt.More(); anIt.Next()) {
451 GeomShapePtr aShape(new GeomAPI_Shape());
452 aShape->setImpl(new TopoDS_Shape(anIt.Value()));
453 isFromFaceSet ? this->addToShape(aShape) : this->addFromShape(aShape);
459 if(aResult.ShapeType() == TopAbs_COMPOUND) {
460 std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
461 aGeomShape->setImpl(new TopoDS_Shape(aResult));
462 ListOfShape aCompSolids, aFreeSolids;
463 aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
464 GeomAPI_Shape::COMPSOLID,
467 aResult = aGeomShape->impl<TopoDS_Shape>();
470 // If after cut we got more than one solids then take closest to the center of mass of the base face.
471 aResult = findClosest(aResult, aBaseCentre);
474 if(aShapeTypeToExp == TopAbs_COMPOUND) {
475 storeGenerationHistory(this, aResult, TopAbs_EDGE, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
476 storeGenerationHistory(this, aResult, TopAbs_FACE, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
478 storeGenerationHistory(this, aResult, aShapeTypeToExp, aRotatedBoundingFace, aModifiedBaseShape, isFromFaceSet);
483 if(aResult.IsNull()) {
486 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
487 GeomShapePtr aShape(new GeomAPI_Shape());
488 aShape->setImpl(new TopoDS_Shape(aResult));
489 this->setShape(aShape);
493 //==================================================================================================
494 TopoDS_Face makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
496 if(!thePlane.Contains(thePoint, Precision::Confusion())) {
497 gp_XYZ aVec = thePoint.XYZ() - thePlane.Location().XYZ();
498 double aSign = aVec * thePlane.Axis().Direction().XYZ();
499 if(aSign < 0) thePlane.SetAxis(thePlane.Axis().Reversed());
502 BRepBuilderAPI_MakeFace aMakeFace(thePlane);
503 TopoDS_Face aResultFace = TopoDS::Face(aMakeFace.Shape());
508 //==================================================================================================
509 TopoDS_Solid makeSolidFromShape(const TopoDS_Shape& theShape)
514 BRep_Builder aBoundingBuilder;
515 if(theShape.ShapeType() == TopAbs_SHELL) {
516 aShell = TopoDS::Shell(theShape);
518 aBoundingBuilder.MakeShell(aShell);
519 aBoundingBuilder.Add(aShell, theShape);
521 aBoundingBuilder.MakeSolid(aSolid);
522 aBoundingBuilder.Add(aSolid, aShell);
527 //==================================================================================================
528 gp_Pnt centreOfMass(const TopoDS_Shape& theShape)
530 TopAbs_ShapeEnum aShType = theShape.ShapeType();
531 GProp_GProps aGProps;
533 if(aShType == TopAbs_EDGE || aShType == TopAbs_WIRE) {
534 BRepGProp::LinearProperties(theShape, aGProps);
535 } else if(aShType == TopAbs_FACE || aShType == TopAbs_SHELL) {
536 BRepGProp::SurfaceProperties(theShape, aGProps);
537 } else if(aShType == TopAbs_SOLID || aShType == TopAbs_COMPSOLID) {
538 BRepGProp::VolumeProperties(theShape, aGProps);
541 return aGProps.CentreOfMass();
544 //==================================================================================================
545 TopoDS_Shape findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
547 TopoDS_Shape aResult = theShape;
549 if(theShape.ShapeType() == TopAbs_COMPOUND) {
550 double aMinDistance = Precision::Infinite();
553 for (TopoDS_Iterator anItr(theShape); anItr.More(); anItr.Next()) {
554 TopoDS_Shape aValue = anItr.Value();
555 aCentr = centreOfMass(aValue);
556 aCurDistance = aCentr.Distance(thePoint);
558 if(aCurDistance < aMinDistance) {
559 aMinDistance = aCurDistance;
568 //==================================================================================================
569 void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
570 const TopoDS_Shape& theBase,
571 const TopAbs_ShapeEnum theType,
572 BRepPrimAPI_MakeRevol* theRevolBuilder)
574 for(TopExp_Explorer anExp(theBase, theType); anExp.More(); anExp.Next()) {
575 const TopoDS_Shape& aShape = anExp.Current();
576 GeomShapePtr aFromShape(new GeomAPI_Shape), aToShape(new GeomAPI_Shape);
577 aFromShape->setImpl(new TopoDS_Shape(theRevolBuilder->FirstShape(aShape)));
578 aToShape->setImpl(new TopoDS_Shape(theRevolBuilder->LastShape(aShape)));
579 theRevolutionAlgo->addFromShape(aFromShape);
580 theRevolutionAlgo->addToShape(aToShape);
584 //==================================================================================================
585 void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
586 const TopoDS_Shape& theResult,
587 const TopAbs_ShapeEnum theType,
588 const TopoDS_Shape& theToFace,
589 const TopoDS_Shape& theFromFace)
591 for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
592 const TopoDS_Shape& aShape = anExp.Current();
593 GeomShapePtr aGeomSh(new GeomAPI_Shape());
594 if(theType == TopAbs_VERTEX) {
595 gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
596 IntTools_Context anIntTools;
597 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theToFace), Precision::Confusion()) == Standard_True) {
598 aGeomSh->setImpl(new TopoDS_Shape(aShape));
599 theRevolutionAlgo->addToShape(aGeomSh);
601 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theFromFace), Precision::Confusion()) == Standard_True) {
602 aGeomSh->setImpl(new TopoDS_Shape(aShape));
603 theRevolutionAlgo->addFromShape(aGeomSh);
605 } else if(theType == TopAbs_EDGE) {
606 TopoDS_Edge anEdge = TopoDS::Edge(aShape);
607 BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theToFace));
608 anEdgeCheck.Perform();
609 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
610 aGeomSh->setImpl(new TopoDS_Shape(aShape));
611 theRevolutionAlgo->addToShape(aGeomSh);
613 anEdgeCheck.Init(anEdge, TopoDS::Face(theFromFace));
614 anEdgeCheck.Perform();
615 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
616 aGeomSh->setImpl(new TopoDS_Shape(aShape));
617 theRevolutionAlgo->addFromShape(aGeomSh);
620 Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
621 Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(theFromFace));
622 Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(theToFace));
623 if(aFaceSurface == aFromSurface) {
624 aGeomSh->setImpl(new TopoDS_Shape(aShape));
625 theRevolutionAlgo->addFromShape(aGeomSh);
627 if(aFaceSurface == aToSurface) {
628 aGeomSh->setImpl(new TopoDS_Shape(aShape));
629 theRevolutionAlgo->addToShape(aGeomSh);
635 void storeGenerationHistory(GeomAlgoAPI_Revolution* theRevolutionAlgo,
636 const TopoDS_Shape& theResult,
637 const TopAbs_ShapeEnum theType,
638 const TopoDS_Shape& theRotatedBoundingFace,
639 const TopoDS_Shape& theModifiedBaseShape,
640 const bool theIsFromFaceSet)
642 for(TopExp_Explorer anExp(theResult, theType); anExp.More (); anExp.Next ()) {
643 const TopoDS_Shape& aShape = anExp.Current();
644 GeomShapePtr aGeomSh(new GeomAPI_Shape());
645 if(theType == TopAbs_VERTEX) {
646 gp_Pnt aPnt = BRep_Tool::Pnt(TopoDS::Vertex(aShape));
647 IntTools_Context anIntTools;
648 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theRotatedBoundingFace), Precision::Confusion()) == Standard_True) {
649 aGeomSh->setImpl(new TopoDS_Shape(aShape));
650 theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
652 if(anIntTools.IsValidPointForFace(aPnt, TopoDS::Face(theModifiedBaseShape), Precision::Confusion()) == Standard_True) {
653 aGeomSh->setImpl(new TopoDS_Shape(aShape));
654 theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
656 } else if(theType == TopAbs_EDGE) {
657 TopoDS_Edge anEdge = TopoDS::Edge(aShape);
658 BRepLib_CheckCurveOnSurface anEdgeCheck(anEdge, TopoDS::Face(theRotatedBoundingFace));
659 anEdgeCheck.Perform();
660 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
661 aGeomSh->setImpl(new TopoDS_Shape(aShape));
662 theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
664 anEdgeCheck.Init(anEdge, TopoDS::Face(theModifiedBaseShape));
665 anEdgeCheck.Perform();
666 if(anEdgeCheck.MaxDistance() < Precision::Confusion()) {
667 aGeomSh->setImpl(new TopoDS_Shape(aShape));
668 theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);
671 Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aShape));
672 Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(theRotatedBoundingFace));
673 Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(TopoDS::Face(theModifiedBaseShape));
674 if(aFaceSurface == aBoundingSurface) {
675 aGeomSh->setImpl(new TopoDS_Shape(aShape));
676 theIsFromFaceSet ? theRevolutionAlgo->addFromShape(aGeomSh) : theRevolutionAlgo->addToShape(aGeomSh);
678 if(aFaceSurface == aBaseSurface) {
679 aGeomSh->setImpl(new TopoDS_Shape(aShape));
680 theIsFromFaceSet ? theRevolutionAlgo->addToShape(aGeomSh) : theRevolutionAlgo->addFromShape(aGeomSh);