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 <GeomAlgoAPI_DFLoader.h>
10 #include <GeomAlgoAPI_MakeShapeList.h>
11 #include <GeomAlgoAPI_Rotation.h>
12 #include <GeomAlgoAPI_ShapeProps.h>
14 #include <BRep_Builder.hxx>
15 #include <BRep_Tool.hxx>
16 #include <BRepAlgoAPI_Cut.hxx>
17 #include <BRepBuilderAPI_MakeFace.hxx>
18 #include <BRepBuilderAPI_Transform.hxx>
19 #include <BRepCheck_Analyzer.hxx>
20 #include <BRepPrimAPI_MakeRevol.hxx>
21 #include <BRepGProp.hxx>
22 #include <Geom_Plane.hxx>
23 #include <Geom_RectangularTrimmedSurface.hxx>
24 #include <GeomLib_IsPlanarSurface.hxx>
26 #include <GProp_GProps.hxx>
27 #include <TopExp_Explorer.hxx>
30 //=================================================================================================
31 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(std::shared_ptr<GeomAPI_Shape> theBasis,
32 std::shared_ptr<GeomAPI_Ax1> theAxis,
37 build(theBasis, theAxis, std::shared_ptr<GeomAPI_Shape>(), theToAngle, std::shared_ptr<GeomAPI_Shape>(), theFromAngle);
40 //=================================================================================================
41 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(std::shared_ptr<GeomAPI_Shape> theBasis,
42 std::shared_ptr<GeomAPI_Ax1> theAxis,
43 std::shared_ptr<GeomAPI_Shape> theToShape,
45 std::shared_ptr<GeomAPI_Shape> theFromShape,
49 build(theBasis, theAxis, theToShape, theToAngle, theFromShape, theFromAngle);
52 //=================================================================================================
53 TopoDS_Face GeomAlgoAPI_Revolution::makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
55 gp_XYZ aVec = thePoint.XYZ() - thePlane.Location().XYZ();
56 double aSign = aVec * thePlane.Axis().Direction().XYZ();
57 if(aSign < 0) thePlane.SetAxis(thePlane.Axis().Reversed());
59 BRepBuilderAPI_MakeFace aMakeFace(thePlane);
60 TopoDS_Face aResultFace = TopoDS::Face(aMakeFace.Shape());
65 //=================================================================================================
66 TopoDS_Solid GeomAlgoAPI_Revolution::makeSolidFromFace(const TopoDS_Face& theFace)
71 BRep_Builder aBoundingBuilder;
72 aBoundingBuilder.MakeShell(aShell);
73 aBoundingBuilder.Add(aShell, theFace);
74 aBoundingBuilder.MakeSolid(aSolid);
75 aBoundingBuilder.Add(aSolid, aShell);
80 //=================================================================================================
81 TopoDS_Shape GeomAlgoAPI_Revolution::findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
83 TopoDS_Shape aResult = theShape;
85 if(theShape.ShapeType() == TopAbs_COMPOUND) {
86 double aMinDistance = Precision::Infinite();
91 for (TopoDS_Iterator anItr(theShape); anItr.More(); anItr.Next()) {
92 TopoDS_Shape aValue = anItr.Value();
93 BRepGProp::VolumeProperties(aValue, aGProps);
94 aCentr = aGProps.CentreOfMass();
95 aCurDistance = aCentr.Distance(thePoint);
97 if(aCurDistance < aMinDistance) {
98 aMinDistance = aCurDistance;
107 //=================================================================================================
108 void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasis,
109 const std::shared_ptr<GeomAPI_Ax1>& theAxis,
110 const std::shared_ptr<GeomAPI_Shape>& theToShape,
112 const std::shared_ptr<GeomAPI_Shape>& theFromShape,
115 if(!theBasis || !theAxis ||
116 (((!theFromShape && !theToShape) || (theFromShape && theToShape && theFromShape->isEqual(theToShape)))
117 && (theFromAngle == 0.0 && theToAngle == 0.0))) {
121 TopoDS_Face aBasisFace = TopoDS::Face(theBasis->impl<TopoDS_Shape>());
122 GeomLib_IsPlanarSurface isBasisPlanar(BRep_Tool::Surface(aBasisFace));
123 if(!isBasisPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution
126 gp_Pln aBasisPln = isBasisPlanar.Plan();
127 gp_Ax1 anAxis = theAxis->impl<gp_Ax1>();
129 ListOfMakeShape aListOfMakeShape;
130 myFirst = std::make_shared<GeomAPI_Shape>();
131 myLast = std::make_shared<GeomAPI_Shape>();
133 TopoDS_Shape aResult;
134 if(!theFromShape && !theToShape) { // Case 1: When only angles was set.
135 // Rotating base face with the negative value of "from angle".
137 aBaseTrsf.SetRotation(anAxis, -theFromAngle / 180.0 * M_PI);
138 BRepBuilderAPI_Transform* aBaseTransform = new BRepBuilderAPI_Transform(aBasisFace,
141 aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aBaseTransform));
142 TopoDS_Shape aRotatedBaseShape = aBaseTransform->Shape();
144 // Making revolution to the angle equal to the sum of "from angle" and "to angle".
145 double anAngle = theFromAngle + theToAngle;
146 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aRotatedBaseShape,
148 anAngle / 180 * M_PI,
150 aRevolBuilder->Build();
151 if(!aRevolBuilder->IsDone()) {
154 aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aRevolBuilder));
155 aResult = aRevolBuilder->Shape();
158 myFirst->setImpl(new TopoDS_Shape(aRevolBuilder->FirstShape()));
159 myLast->setImpl(new TopoDS_Shape(aRevolBuilder->LastShape()));
160 } else if(theFromShape && theToShape) { // Case 2: When both bounding planes were set.
161 // Getting bounding faces.
162 TopoDS_Face aFromFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
163 TopoDS_Face aToFace = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
165 // Getting planes from bounding face.
166 GeomLib_IsPlanarSurface isFromPlanar(BRep_Tool::Surface(aFromFace));
167 GeomLib_IsPlanarSurface isToPlanar(BRep_Tool::Surface(aToFace));
168 if(!isFromPlanar.IsPlanar() || !isToPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution bounding
171 gp_Pln aFromPln = isFromPlanar.Plan();
172 gp_Pln aToPln = isToPlanar.Plan();
174 // Orienting bounding planes properly so that the center of mass of the base face stays
175 // on the result shape after cut.
176 gp_Pnt aBasisCentr = GeomAlgoAPI_ShapeProps::centreOfMass(theBasis)->impl<gp_Pnt>();
177 aFromFace = makeFaceFromPlane(aFromPln, aBasisCentr);
178 aToFace = makeFaceFromPlane(aToPln, aBasisCentr);
180 // Making solids from bounding planes and putting them in compound.
181 TopoDS_Shape aFromSolid = makeSolidFromFace(aFromFace);
182 TopoDS_Shape aToSolid = makeSolidFromFace(aToFace);
184 // Rotating bounding planes to the specified angle.
187 double aFromRotAngle = ((aFromPln.Axis().Direction() * aBasisPln.Axis().Direction()) > 0) ? -theFromAngle : theFromAngle;
188 double aToRotAngle = ((aToPln.Axis().Direction() * aBasisPln.Axis().Direction()) > 0) ? -theToAngle : theToAngle;
189 aFromTrsf.SetRotation(anAxis,aFromRotAngle / 180.0 * M_PI);
190 aToTrsf.SetRotation(anAxis, aToRotAngle / 180.0 * M_PI);
191 BRepBuilderAPI_Transform aFromTransform(aFromSolid, aFromTrsf, true);
192 BRepBuilderAPI_Transform aToTransform(aToSolid, aToTrsf, true);
193 TopoDS_Shape aRotatedFromFace = aFromTransform.Modified(aFromFace).First();
194 TopoDS_Shape aRotatedToFace = aToTransform.Modified(aToFace).First();
195 aFromSolid = aFromTransform.Shape();
196 aToSolid = aToTransform.Shape();
198 // Making revolution to the 360 angle.
199 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBasisFace, anAxis, 2 * M_PI, Standard_True);
200 aRevolBuilder->Build();
201 aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aRevolBuilder));
202 TopoDS_Shape aRevolShape = aRevolBuilder->Shape();
204 // Cutting revolution with from plane.
205 BRepAlgoAPI_Cut* aFromCutBuilder = new BRepAlgoAPI_Cut(aRevolShape, aFromSolid);
206 aFromCutBuilder->Build();
207 if(!aFromCutBuilder->IsDone()) {
210 aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aFromCutBuilder));
211 aResult = aFromCutBuilder->Shape();
213 // Cutting revolution with to plane.
214 BRepAlgoAPI_Cut* aToCutBuilder = new BRepAlgoAPI_Cut(aResult, aToSolid);
215 aToCutBuilder->Build();
216 if(!aToCutBuilder->IsDone()) {
219 aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aToCutBuilder));
220 aResult = aToCutBuilder->Shape();
222 // If after cut we got more than one solids then take closest to the center of mass of the base face.
223 aResult = findClosest(aResult, aBasisCentr);
226 for(TopExp_Explorer anExp(aResult, TopAbs_FACE); anExp.More (); anExp.Next ()) {
227 const TopoDS_Shape& aFaceOnResult = anExp.Current();
228 Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aFaceOnResult));
229 Handle(Geom_Surface) aFromSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedFromFace));
230 Handle(Geom_Surface) aToSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedToFace));
231 if(aFaceSurface == aFromSurface) {
232 myFirst->setImpl(new TopoDS_Shape(aFaceOnResult));
234 if(aFaceSurface == aToSurface) {
235 myLast->setImpl(new TopoDS_Shape(aFaceOnResult));
238 } else { //Case 3: When only one bounding plane was set.
239 // Getting bounding face.
240 TopoDS_Face aBoundingFace;
241 bool isFromFaceSet = false;
243 aBoundingFace = TopoDS::Face(theFromShape->impl<TopoDS_Shape>());
244 isFromFaceSet = true;
245 } else if(theToShape) {
246 aBoundingFace = TopoDS::Face(theToShape->impl<TopoDS_Shape>());
249 // Getting plane from bounding face.
250 GeomLib_IsPlanarSurface isBoundingPlanar(BRep_Tool::Surface(aBoundingFace));
251 if(!isBoundingPlanar.IsPlanar()) { // non-planar shapes is not supported for revolution bounding
254 gp_Pln aBoundingPln = isBoundingPlanar.Plan();
256 // Orienting bounding plane properly so that the center of mass of the base face stays
257 // on the result shape after cut.
258 gp_Pnt aBasisCentr = GeomAlgoAPI_ShapeProps::centreOfMass(theBasis)->impl<gp_Pnt>();
259 aBoundingFace = makeFaceFromPlane(aBoundingPln, aBasisCentr);
261 // Making solid from bounding plane.
262 TopoDS_Shape aBoundingSolid = makeSolidFromFace(aBoundingFace);
264 // Rotating bounding plane to the specified angle.
265 double aBoundingRotAngle = isFromFaceSet ? theFromAngle : theToAngle;
266 if(aBoundingPln.Axis().IsParallel(aBasisPln.Axis(), Precision::Confusion())) {
267 if(isFromFaceSet) aBoundingRotAngle = -aBoundingRotAngle;
269 double aSign = (aBoundingPln.Axis().Direction() ^ aBasisPln.Axis().Direction()) *
271 if((aSign <= 0 && !isFromFaceSet) || (aSign > 0 && isFromFaceSet)) {
272 aBoundingRotAngle = -aBoundingRotAngle;
275 gp_Trsf aBoundingTrsf;
276 aBoundingTrsf.SetRotation(anAxis, aBoundingRotAngle / 180.0 * M_PI);
277 BRepBuilderAPI_Transform aBoundingTransform(aBoundingSolid, aBoundingTrsf, true);
278 TopoDS_Shape aRotatedBoundingFace = aBoundingTransform.Modified(aBoundingFace).First();
279 aBoundingSolid = aBoundingTransform.Shape();
281 // Making revolution to the 360 angle.
282 BRepPrimAPI_MakeRevol* aRevolBuilder = new BRepPrimAPI_MakeRevol(aBasisFace, anAxis, 2 * M_PI, Standard_True);
283 aRevolBuilder->Build();
284 aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aRevolBuilder));
285 TopoDS_Shape aRevolShape = aRevolBuilder->Shape();
287 // Cutting revolution with bounding plane.
288 BRepAlgoAPI_Cut* aBoundingCutBuilder = new BRepAlgoAPI_Cut(aRevolShape, aBoundingSolid);
289 aBoundingCutBuilder->Build();
290 if(!aBoundingCutBuilder->IsDone()) {
293 aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aBoundingCutBuilder));
294 aResult = aBoundingCutBuilder->Shape();
295 TopExp_Explorer anExp1(aResult, TopAbs_SOLID);
298 if(aBoundingCutBuilder->Modified(aBoundingFace).Extent() > 0) {
299 std::shared_ptr<GeomAPI_Shape> aPtr = isFromFaceSet ? myFirst : myLast;
300 aPtr->setImpl(new TopoDS_Shape(aBoundingCutBuilder->Modified(aBoundingFace).First()));
303 // Try to cut with base face. If it can not be done then keep result of cut with bounding plane.
305 aBasisFace.Orientation(TopAbs_REVERSED);
308 // Making solid from basis face.
309 TopoDS_Shape aBasisSolid = makeSolidFromFace(aBasisFace);
311 // Rotating basis face to the specified angle.
313 double aBasisRotAngle = isFromFaceSet ? theToAngle : -theFromAngle;
314 aBasisTrsf.SetRotation(anAxis, aBasisRotAngle / 180.0 * M_PI);
315 BRepBuilderAPI_Transform aBasisTransform(aBasisSolid, aBasisTrsf, true);
316 TopoDS_Shape aRotatedBasisFace = aBasisTransform.Modified(aBasisFace).First();
317 aBasisSolid = aBasisTransform.Shape();
319 // Cutting revolution with basis face.
320 BRepAlgoAPI_Cut* aBasisCutBuilder = new BRepAlgoAPI_Cut(aResult, aBasisSolid);
321 aBasisCutBuilder->Build();
322 if(aBasisCutBuilder->IsDone()) {
323 TopoDS_Shape aCutResult = aBasisCutBuilder->Shape();
324 TopExp_Explorer anExp(aCutResult, TopAbs_SOLID);
326 aListOfMakeShape.push_back(std::make_shared<GeomAlgoAPI_MakeShape>(aBasisCutBuilder));
327 aResult = aCutResult;
331 // If after cut we got more than one solids then take closest to the center of mass of the base face.
332 aResult = findClosest(aResult, aBasisCentr);
335 for(TopExp_Explorer anExp(aResult, TopAbs_FACE); anExp.More (); anExp.Next ()) {
336 const TopoDS_Shape& aFaceOnResult = anExp.Current();
337 Handle(Geom_Surface) aFaceSurface = BRep_Tool::Surface(TopoDS::Face(aFaceOnResult));
338 Handle(Geom_Surface) aBoundingSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedBoundingFace));
339 Handle(Geom_Surface) aBasisSurface = BRep_Tool::Surface(TopoDS::Face(aRotatedBasisFace));
340 if(aFaceSurface == aBoundingSurface) {
341 std::shared_ptr<GeomAPI_Shape> aPtr = isFromFaceSet ? myFirst : myLast;
342 aPtr->setImpl(new TopoDS_Shape(aFaceOnResult));
344 if(aFaceSurface == aBasisSurface) {
345 std::shared_ptr<GeomAPI_Shape> aPtr = isFromFaceSet ? myLast : myFirst;
346 aPtr->setImpl(new TopoDS_Shape(aFaceOnResult));
351 TopExp_Explorer anExp(aResult, TopAbs_SOLID);
356 // fill data map to keep correct orientation of sub-shapes
357 myMap = std::make_shared<GeomAPI_DataMapOfShapeShape>();
358 for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) {
359 std::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
360 aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current()));
361 myMap->bind(aCurrentShape, aCurrentShape);
363 myShape = std::make_shared<GeomAPI_Shape>();
364 myShape->setImpl(new TopoDS_Shape(aResult));
365 myMkShape = std::make_shared<GeomAlgoAPI_MakeShapeList>();
370 //=================================================================================================
371 const bool GeomAlgoAPI_Revolution::isDone() const
376 //=================================================================================================
377 const bool GeomAlgoAPI_Revolution::isValid() const
379 BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
380 return (aChecker.IsValid() == Standard_True);
383 //=================================================================================================
384 const bool GeomAlgoAPI_Revolution::hasVolume() const
386 bool hasVolume(false);
388 const TopoDS_Shape& aRShape = myShape->impl<TopoDS_Shape>();
390 BRepGProp::VolumeProperties(aRShape, aGProp);
391 if(aGProp.Mass() > Precision::Confusion())
397 //=================================================================================================
398 const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Revolution::shape () const
403 //=================================================================================================
404 const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Revolution::firstShape()
409 //=================================================================================================
410 const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Revolution::lastShape()
415 //=================================================================================================
416 std::shared_ptr<GeomAPI_DataMapOfShapeShape> GeomAlgoAPI_Revolution::mapOfShapes() const
421 //=================================================================================================
422 std::shared_ptr<GeomAlgoAPI_MakeShape> GeomAlgoAPI_Revolution::makeShape() const