1 // Copyright (C) 2014-2020 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include <GeomAlgoAPI_Ellipsoid.h>
23 #include <gp_Elips.hxx>
24 #include <gp_GTrsf.hxx>
25 #include <BRepBuilderAPI_GTransform.hxx>
26 #include <BRepBuilderAPI_MakeEdge.hxx>
27 #include <BRepOffsetAPI_Sewing.hxx>
28 #include <BRepBuilderAPI_MakeFace.hxx>
29 #include <BRepBuilderAPI_MakeSolid.hxx>
30 #include <BRepBuilderAPI_MakeWire.hxx>
31 #include <BRepPrimAPI_MakeRevol.hxx>
34 #include <TopoDS_Edge.hxx>
36 //=================================================================================================
38 GeomAlgoAPI_Ellipsoid::GeomAlgoAPI_Ellipsoid(const double theAx,
41 const double theZCut1,
42 const double theZCut2)
51 //=================================================================================================
52 bool GeomAlgoAPI_Ellipsoid::check()
54 if (myAx < Precision::Confusion()) {
55 myError = "Ellipsoid builder :: ax is negative or null.";
57 } else if (myBy < Precision::Confusion()) {
58 myError = "Ellipsoid builder :: by is negative or null.";
60 } else if (myCz < Precision::Confusion()) {
61 myError = "Ellipsoid builder :: cz is negative or null.";
63 } else if (myZCut1 < 0.) {
64 myError = "Ellipsoid builder :: zcut1 is negative.";
66 } else if (myZCut2 < 0.) {
67 myError = "Ellipsoid builder :: zcut2 is negative.";
69 } else if (myZCut1 < Precision::Confusion() && myZCut2 < Precision::Confusion()) {
70 myError = "Ellipsoid builder :: zcut1 and zcut2 are null.";
77 //=================================================================================================
78 void GeomAlgoAPI_Ellipsoid::build()
80 myCreatedFaces.clear();
82 BRepOffsetAPI_Sewing aSewer;
86 gp_Pnt anOrigin(0., 0., 0.);
87 gp_Dir aDirX(1., 0., 0.);
88 gp_Dir aDirY(0., 1., 0.);
89 gp_Dir aDirZ(0., 0., 1.);
90 gp_Ax1 aZAxis(anOrigin, aDirZ);
92 // Calculate the parameters needed to make the edges and the faces
93 // gp_Elips needs the second parameter to be greater than the third (major axis)
95 aRefAx2 = gp_Ax2(anOrigin, aDirY, aDirX);
96 anElips = gp_Elips(aRefAx2, myAx / 2., myCz / 2.);
98 aRefAx2 = gp_Ax2(anOrigin, aDirY, aDirZ);
99 anElips = gp_Elips(aRefAx2, myCz / 2., myAx / 2.);
102 double aLowPositionFactor = sqrt(1. - (myZCut1 * myZCut1 * 4. / (myCz * myCz))) / 2.;
103 double aHighPositionFactor = sqrt(1. - (myZCut2 * myZCut2 * 4. / (myCz * myCz))) / 2.;
105 double aXEndTop = myAx * aHighPositionFactor;
106 double aXEndBottom = myAx * aLowPositionFactor;
108 // Build the XZ ellipse
109 gp_Pnt anEndPoint1(aXEndTop, 0., myZCut2);
110 gp_Pnt anEndPoint2(aXEndBottom, 0., -myZCut1);
111 BRepBuilderAPI_MakeEdge anElipsBuilder(anElips, anEndPoint1, anEndPoint2);
112 anElipsBuilder.Build();
113 TopoDS_Edge anOuterEdge = anElipsBuilder.Edge();
115 // Perform a revolution based on the section to build a simple version of the outer face
117 BRepPrimAPI_MakeRevol aRevolBuilder(anOuterEdge, aZAxis, 2. * M_PI, Standard_True);
118 if (!aRevolBuilder.IsDone()) {
119 myError = "Ellipsoid builder :: section revolution did not succeed";
124 gp_Mat rot (1., 0., 0.,
128 aGTrsf.SetVectorialPart(rot);
130 BRepBuilderAPI_GTransform aScaleBuilder(aRevolBuilder.Shape(), aGTrsf, true);
131 if (!aScaleBuilder.IsDone()) {
132 myError = "Ellipsoid builder :: scale did not succeed";
136 TopoDS_Face anOuterFace = TopoDS::Face(aScaleBuilder.Shape());
137 aSewer.Add(TopoDS::Face(anOuterFace.Reversed()));
139 // Build the high and low ellipse if needed
145 if ((myCz / 2. - myZCut1) > Precision::Confusion()) {
146 aLowAx2 = gp_Ax2(gp_Pnt(0., 0., -myZCut1), aDirZ, aDirX);
147 aLowElips = gp_Elips(aLowAx2, aLowPositionFactor * myAx, aLowPositionFactor * myBy);
149 if ((myCz / 2. - myZCut2) > Precision::Confusion()) {
150 aHighAx2 = gp_Ax2(gp_Pnt(0., 0., myZCut2), aDirZ, aDirX);
151 aHighElips = gp_Elips(aHighAx2, aHighPositionFactor * myAx, aHighPositionFactor * myBy);
154 if ((myCz / 2. - myZCut1) > Precision::Confusion()) {
155 aLowAx2 = gp_Ax2(gp_Pnt(0., 0., -myZCut1), aDirZ, aDirY);
156 aLowElips = gp_Elips(aLowAx2, aLowPositionFactor * myBy, aLowPositionFactor * myAx);
158 if ((myCz / 2. - myZCut2) > Precision::Confusion()) {
159 aHighAx2 = gp_Ax2(gp_Pnt(0., 0., myZCut2), aDirZ, aDirY);
160 aHighElips = gp_Elips(aHighAx2, aHighPositionFactor * myBy, aHighPositionFactor * myAx);
164 // Make higher and lower elliptical faces if needed
165 if ((myCz / 2. - myZCut1) > Precision::Confusion()) {
166 TopoDS_Face aBottomFace;
167 BRepBuilderAPI_MakeEdge aBottomEdgeMk(aLowElips);
168 aBottomEdgeMk.Build();
169 BRepBuilderAPI_MakeWire aBottomWireMk;
170 aBottomWireMk.Add(aBottomEdgeMk.Edge());
171 BRepBuilderAPI_MakeFace aBottomFaceMk(aBottomWireMk.Wire());
172 aBottomFace = aBottomFaceMk.Face();
173 aSewer.Add(TopoDS::Face(aBottomFace.Reversed()));
175 if ((myCz / 2. - myZCut2) > Precision::Confusion()) {
176 TopoDS_Face aTopFace;
177 BRepBuilderAPI_MakeEdge aTopEdgeMk(aHighElips);
179 BRepBuilderAPI_MakeWire aTopWireMk;
180 aTopWireMk.Add(aTopEdgeMk.Edge());
181 BRepBuilderAPI_MakeFace aTopFaceMk(aTopWireMk.Wire());
182 aTopFace = aTopFaceMk.Face();
183 aSewer.Add(TopoDS::Face(aTopFace.Reversed()));
188 if ((myCz / 2. - myZCut2) > Precision::Confusion() ||
189 (myCz / 2. - myZCut1) > Precision::Confusion()) {
190 aShell = TopoDS::Shell(aSewer.SewedShape());
192 TopoDS_Builder aBuilder;
193 aBuilder.MakeShell(aShell);
194 aBuilder.Add(aShell, aSewer.SewedShape());
197 BRepBuilderAPI_MakeSolid *anEllipsoidMk = new BRepBuilderAPI_MakeSolid(aShell);
198 anEllipsoidMk->Build();
200 // Store and publish the results
201 std::shared_ptr<GeomAPI_Shape> aResultShape =
202 std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
203 aResultShape->setImpl(new TopoDS_Shape(anEllipsoidMk->Solid()));
204 setShape(aResultShape);
206 // Test on the shapes
207 if (!(aResultShape).get() || aResultShape->isNull()) {
208 myError = "Ellipsoid builder :: resulting shape is null.";
212 setImpl(anEllipsoidMk);
213 setBuilderType(OCCT_BRepBuilderAPI_MakeShape);