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_Rotation.h>
11 #include <GeomAlgoAPI_ShapeProps.h>
13 #include <BRep_Builder.hxx>
14 #include <BRep_Tool.hxx>
15 #include <BRepAlgoAPI_Cut.hxx>
16 #include <BRepBuilderAPI_MakeFace.hxx>
17 #include <BRepBuilderAPI_Transform.hxx>
18 #include <BRepCheck_Analyzer.hxx>
19 #include <BRepPrimAPI_MakeRevol.hxx>
20 #include <BRepGProp.hxx>
21 #include <Geom_Plane.hxx>
22 #include <Geom_RectangularTrimmedSurface.hxx>
23 #include <GeomLib_IsPlanarSurface.hxx>
25 #include <GProp_GProps.hxx>
26 #include <TopExp_Explorer.hxx>
29 //=================================================================================================
30 GeomAlgoAPI_Revolution::GeomAlgoAPI_Revolution(std::shared_ptr<GeomAPI_Shape> theBasis,
31 std::shared_ptr<GeomAPI_Ax1> theAxis,
32 std::shared_ptr<GeomAPI_Shape> theFromShape,
34 std::shared_ptr<GeomAPI_Shape> theToShape,
37 myFromShape(theFromShape),
38 myFromAngle(theFromAngle),
39 myToShape(theToShape),
40 myToAngle(theToAngle),
42 myShape(new GeomAPI_Shape()),
43 myFirst(new GeomAPI_Shape()),myLast(new GeomAPI_Shape())
48 //=================================================================================================
49 TopoDS_Face GeomAlgoAPI_Revolution::makeFaceFromPlane(gp_Pln& thePlane, const gp_Pnt& thePoint)
51 gp_XYZ aVec = thePoint.XYZ() - thePlane.Location().XYZ();
52 double aSign = aVec * thePlane.Axis().Direction().XYZ();
53 if(aSign < 0) thePlane.SetAxis(thePlane.Axis().Reversed());
55 BRepBuilderAPI_MakeFace aMakeFace(thePlane);
56 TopoDS_Face aResultFace = TopoDS::Face(aMakeFace.Shape());
61 //=================================================================================================
62 TopoDS_Solid GeomAlgoAPI_Revolution::makeSolidFromFace(const TopoDS_Face& theFace)
67 BRep_Builder aBoundingBuilder;
68 aBoundingBuilder.MakeShell(aShell);
69 aBoundingBuilder.Add(aShell, theFace);
70 aBoundingBuilder.MakeSolid(aSolid);
71 aBoundingBuilder.Add(aSolid, aShell);
76 //=================================================================================================
77 TopoDS_Shape GeomAlgoAPI_Revolution::findClosest(const TopoDS_Shape& theShape, const gp_Pnt& thePoint)
79 TopoDS_Shape aResult = theShape;
81 if(theShape.ShapeType() == TopAbs_COMPOUND) {
82 double aMinDistance = Precision::Infinite();
87 for (TopoDS_Iterator anItr(theShape); anItr.More(); anItr.Next()) {
88 TopoDS_Shape aValue = anItr.Value();
89 BRepGProp::VolumeProperties(aValue, aGProps);
90 aCentr = aGProps.CentreOfMass();
91 aCurDistance = aCentr.Distance(thePoint);
93 if(aCurDistance < aMinDistance) {
94 aMinDistance = aCurDistance;
103 //=================================================================================================
104 void GeomAlgoAPI_Revolution::build(const std::shared_ptr<GeomAPI_Shape>& theBasis)
106 if(!theBasis || !myAxis ||
107 (((!myFromShape && !myToShape) || (myFromShape && myToShape && myFromShape->isEqual(myToShape)))
108 && (myFromAngle == 0.0 && myToAngle == 0.0))) {
112 TopoDS_Face aBasisFace = TopoDS::Face(theBasis->impl<TopoDS_Shape>());
113 GeomLib_IsPlanarSurface isBasisPlanar(BRep_Tool::Surface(aBasisFace));
114 if(!isBasisPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution
117 gp_Pln aBasisPln = isBasisPlanar.Plan();
118 gp_Ax1 anAxis = myAxis->impl<gp_Ax1>();
120 TopoDS_Shape aResult;
121 if(!myFromShape && !myToShape) { // Case 1: When only angles was set.
122 // Rotating base face with the negative value of "from angle".
123 GeomAlgoAPI_Rotation aRotation(theBasis, myAxis, -myFromAngle);
124 TopoDS_Shape aRotatedBaseShape = aRotation.shape()->impl<TopoDS_Shape>();
126 // Making revolution to the angle equal to the sum of "from angle" and "to angle".
127 double anAngle = myFromAngle + myToAngle;
128 BRepPrimAPI_MakeRevol aRevolBuilder(aRotatedBaseShape,
130 anAngle / 180 * M_PI,
132 aRevolBuilder.Build();
133 if(!aRevolBuilder.IsDone()) {
137 aResult = aRevolBuilder.Shape();
138 } else if(myFromShape && myToShape) { // Case 2: When both bounding planes were set.
139 // Getting bounding faces.
140 TopoDS_Face aFromFace = TopoDS::Face(myFromShape->impl<TopoDS_Shape>());
141 TopoDS_Face aToFace = TopoDS::Face(myToShape->impl<TopoDS_Shape>());
143 // Getting planes from bounding face.
144 GeomLib_IsPlanarSurface isFromPlanar(BRep_Tool::Surface(aFromFace));
145 GeomLib_IsPlanarSurface isToPlanar(BRep_Tool::Surface(aToFace));
146 if(!isFromPlanar.IsPlanar() || !isToPlanar.IsPlanar()) {// non-planar shapes is not supported for revolution bounding
149 gp_Pln aFromPln = isFromPlanar.Plan();
150 gp_Pln aToPln = isToPlanar.Plan();
152 // Orienting bounding planes properly so that the center of mass of the base face stays
153 // on the result shape after cut.
154 gp_Pnt aBasisCentr = GeomAlgoAPI_ShapeProps::centreOfMass(theBasis)->impl<gp_Pnt>();
155 aFromFace = makeFaceFromPlane(aFromPln, aBasisCentr);
156 aToFace = makeFaceFromPlane(aToPln, aBasisCentr);
158 // Making solids from bounding planes and putting them in compound.
159 TopoDS_Shape aFromSolid = makeSolidFromFace(aFromFace);
160 TopoDS_Shape aToSolid = makeSolidFromFace(aToFace);
162 // Rotating bounding planes to the specified angle.
165 double aFromRotAngle = ((aFromPln.Axis().Direction() * aBasisPln.Axis().Direction()) > 0) ? -myFromAngle : myFromAngle;
166 double aToRotAngle = ((aToPln.Axis().Direction() * aBasisPln.Axis().Direction()) > 0) ? -myToAngle : myToAngle;
167 aFromTrsf.SetRotation(anAxis,aFromRotAngle / 180.0 * M_PI);
168 aToTrsf.SetRotation(anAxis, aToRotAngle / 180.0 * M_PI);
169 BRepBuilderAPI_Transform aFromTransform(aFromSolid, aFromTrsf, true);
170 BRepBuilderAPI_Transform aToTransform(aToSolid, aToTrsf, true);
171 aFromSolid = aFromTransform.Shape();
172 aToSolid = aToTransform.Shape();
174 // Making revolution to the 360 angle.
175 BRepPrimAPI_MakeRevol aRevolBuilder(aBasisFace, anAxis, 2 * M_PI, Standard_True);
176 aRevolBuilder.Build();
177 TopoDS_Shape aRevolShape = aRevolBuilder.Shape();
179 // Cutting revolution with from plane.
180 BRepAlgoAPI_Cut aFromCutBuilder(aRevolShape, aFromSolid);
181 aFromCutBuilder.Build();
182 if(!aFromCutBuilder.IsDone()) {
185 aResult = aFromCutBuilder.Shape();
187 // Cutting revolution with to plane.
188 BRepAlgoAPI_Cut aToCutBuilder(aResult, aToSolid);
189 aToCutBuilder.Build();
190 if(!aToCutBuilder.IsDone()) {
193 aResult = aToCutBuilder.Shape();
195 // If after cut we got more than one solids then take closest to the center of mass of the base face.
196 aResult = findClosest(aResult, aBasisCentr);
198 } else { //Case 3: When only one bounding plane was set.
199 // Getting bounding face.
200 TopoDS_Face aBoundingFace;
201 bool isFromFaceSet = false;
203 aBoundingFace = TopoDS::Face(myFromShape->impl<TopoDS_Shape>());
204 isFromFaceSet = true;
205 } else if(myToShape) {
206 aBoundingFace = TopoDS::Face(myToShape->impl<TopoDS_Shape>());
209 // Getting plane from bounding face.
210 GeomLib_IsPlanarSurface isBoundingPlanar(BRep_Tool::Surface(aBoundingFace));
211 if(!isBoundingPlanar.IsPlanar()) { // non-planar shapes is not supported for revolution bounding
214 gp_Pln aBoundingPln = isBoundingPlanar.Plan();
216 // Orienting bounding plane properly so that the center of mass of the base face stays
217 // on the result shape after cut.
218 gp_Pnt aBasisCentr = GeomAlgoAPI_ShapeProps::centreOfMass(theBasis)->impl<gp_Pnt>();
219 aBoundingFace = makeFaceFromPlane(aBoundingPln, aBasisCentr);
221 // Making solid from bounding plane.
222 TopoDS_Shape aBoundingSolid = makeSolidFromFace(aBoundingFace);
224 // Rotating bounding plane to the specified angle.
225 double aBoundingRotAngle = isFromFaceSet ? myFromAngle : myToAngle;
226 if(aBoundingPln.Axis().IsParallel(aBasisPln.Axis(), Precision::Confusion())) {
227 if(isFromFaceSet) aBoundingRotAngle = -aBoundingRotAngle;
229 double aSign = (aBoundingPln.Axis().Direction() ^ aBasisPln.Axis().Direction()) *
231 if((aSign <= 0 && !isFromFaceSet) || (aSign > 0 && isFromFaceSet)) {
232 aBoundingRotAngle = -aBoundingRotAngle;
235 gp_Trsf aBoundingTrsf;
236 aBoundingTrsf.SetRotation(anAxis, aBoundingRotAngle / 180.0 * M_PI);
237 BRepBuilderAPI_Transform aBoundingTransform(aBoundingSolid, aBoundingTrsf, true);
238 aBoundingSolid = aBoundingTransform.Shape();
240 // Making revolution to the 360 angle.
241 BRepPrimAPI_MakeRevol aRevolBuilder(aBasisFace, anAxis, 2 * M_PI, Standard_True);
242 aRevolBuilder.Build();
243 TopoDS_Shape aRevolShape = aRevolBuilder.Shape();
245 // Cutting revolution with bounding plane.
246 BRepAlgoAPI_Cut aFromCutBuilder(aRevolShape, aBoundingSolid);
247 aFromCutBuilder.Build();
248 if(!aFromCutBuilder.IsDone()) {
252 // Try to cut with base face. If it can not be done then keep result of cut with bounding plane.
253 aResult = aFromCutBuilder.Shape();
255 aBasisFace.Orientation(TopAbs_REVERSED);
258 // Making solid from basis face.
259 TopoDS_Shape aBasisSolid = makeSolidFromFace(aBasisFace);
261 // Rotating basis face to the specified angle.
263 double aBasisRotAngle = isFromFaceSet ? myToAngle : -myFromAngle;
264 aBasisTrsf.SetRotation(anAxis, aBasisRotAngle / 180.0 * M_PI);
265 BRepBuilderAPI_Transform aBasisTransform(aBasisSolid, aBasisTrsf, true);
266 aBasisSolid = aBasisTransform.Shape();
268 // Cutting revolution with basis face.
269 BRepAlgoAPI_Cut aBasisCutBuilder(aResult, aBasisSolid);
270 aBasisCutBuilder.Build();
271 if(aBasisCutBuilder.IsDone()) {
272 TopoDS_Shape aCutResult = aBasisCutBuilder.Shape();
273 TopExp_Explorer anExp(aCutResult, TopAbs_SOLID);
275 aResult = aCutResult;
279 // If after cut we got more than one solids then take closest to the center of mass of the base face.
280 aResult = findClosest(aResult, aBasisCentr);
283 TopExp_Explorer anExp(aResult, TopAbs_SOLID);
288 // fill data map to keep correct orientation of sub-shapes
289 //for (TopExp_Explorer Exp(aResult,TopAbs_FACE); Exp.More(); Exp.Next()) {
290 // std::shared_ptr<GeomAPI_Shape> aCurrentShape(new GeomAPI_Shape());
291 // aCurrentShape->setImpl(new TopoDS_Shape(Exp.Current()));
292 // myMap.bind(aCurrentShape, aCurrentShape);
294 myShape->setImpl(new TopoDS_Shape(aResult));
295 //myFirst->setImpl(new TopoDS_Shape(aBuilder->Modified(aFromShape).First()));
296 //myLast->setImpl(new TopoDS_Shape(aBuilder->Modified(aToShape).First()));
297 //myMkShape = new GeomAlgoAPI_MakeShape (aBuilder);
302 //=================================================================================================
303 const bool GeomAlgoAPI_Revolution::isDone() const
308 //=================================================================================================
309 const bool GeomAlgoAPI_Revolution::isValid() const
311 BRepCheck_Analyzer aChecker(myShape->impl<TopoDS_Shape>());
312 return (aChecker.IsValid() == Standard_True);
315 //=================================================================================================
316 const bool GeomAlgoAPI_Revolution::hasVolume() const
318 bool hasVolume(false);
320 const TopoDS_Shape& aRShape = myShape->impl<TopoDS_Shape>();
322 BRepGProp::VolumeProperties(aRShape, aGProp);
323 if(aGProp.Mass() > Precision::Confusion())
329 //=================================================================================================
330 const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Revolution::shape () const
335 //=================================================================================================
336 const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Revolution::firstShape()
341 //=================================================================================================
342 const std::shared_ptr<GeomAPI_Shape>& GeomAlgoAPI_Revolution::lastShape()
347 //=================================================================================================
348 void GeomAlgoAPI_Revolution::mapOfShapes (GeomAPI_DataMapOfShapeShape& theMap) const
353 //=================================================================================================
354 GeomAlgoAPI_MakeShape* GeomAlgoAPI_Revolution::makeShape() const
359 //=================================================================================================
360 GeomAlgoAPI_Revolution::~GeomAlgoAPI_Revolution()