Salome HOME
Merge branch 'master' into cgt/devCEA
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_Ellipsoid.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <GeomAlgoAPI_Ellipsoid.h>
22
23 #include <gp_Ax2.hxx>
24 #include <gp_Elips.hxx>
25 #include <gp_GTrsf.hxx>
26 #include <BRepBuilderAPI_GTransform.hxx>
27 #include <BRepBuilderAPI_MakeEdge.hxx>
28 #include <BRepOffsetAPI_Sewing.hxx>
29 #include <BRepBuilderAPI_MakeFace.hxx>
30 #include <BRepBuilderAPI_MakeSolid.hxx>
31 #include <BRepBuilderAPI_MakeWire.hxx>
32 #include <BRepPrimAPI_MakeRevol.hxx>
33
34 #include <TopoDS.hxx>
35 #include <TopoDS_Edge.hxx>
36
37 //=================================================================================================
38 GeomAlgoAPI_Ellipsoid::GeomAlgoAPI_Ellipsoid()
39 {
40 }
41
42 //=================================================================================================
43
44 GeomAlgoAPI_Ellipsoid::GeomAlgoAPI_Ellipsoid(const double theAx,
45                                              const double theBy,
46                                              const double theCz,
47                                              const double theZCut1,
48                                              const double theZCut2)
49 {
50   myAx = theAx;
51   myBy = theBy;
52   myCz = theCz;
53   myZCut1 = theZCut1;
54   myZCut2 = theZCut2;
55 }
56
57 //=================================================================================================
58 bool GeomAlgoAPI_Ellipsoid::check()
59 {
60   if (myAx < Precision::Confusion()) {
61     myError = "Ellipsoid builder :: ax is negative or null.";
62     return false;
63   } else if (myBy < Precision::Confusion()) {
64     myError = "Ellipsoid builder :: by is negative or null.";
65     return false;
66   } else if (myCz < Precision::Confusion()) {
67     myError = "Ellipsoid builder :: cz is negative or null.";
68     return false;
69   } else if (myZCut1 < 0.) {
70     myError = "Ellipsoid builder :: zcut1 is negative.";
71     return false;
72   } else if (myZCut2 < 0.) {
73     myError = "Ellipsoid builder :: zcut2 is negative.";
74     return false;
75   } else if (myZCut1 < Precision::Confusion() && myZCut2 < Precision::Confusion()) {
76     myError = "Ellipsoid builder :: zcut1 and zcut2 are null.";
77     return false;
78   }
79
80   return true;
81 }
82
83 //=================================================================================================
84 void GeomAlgoAPI_Ellipsoid::build()
85 {
86   myCreatedFaces.clear();
87
88   BRepOffsetAPI_Sewing aSewer;
89   gp_Ax2 aRefAx2;
90   gp_Elips anElips;
91
92   gp_Pnt anOrigin(0., 0., 0.);
93   gp_Dir aDirX(1., 0., 0.);
94   gp_Dir aDirY(0., 1., 0.);
95   gp_Dir aDirZ(0., 0., 1.);
96   gp_Ax1 aZAxis(anOrigin, aDirZ);
97
98   // Calculate the parameters needed to make the edges and the faces
99   // gp_Elips needs the second parameter to be greater than the third (major axis)
100   if (myCz < myAx) {
101     aRefAx2 = gp_Ax2(anOrigin, aDirY, aDirX);
102     anElips = gp_Elips(aRefAx2, myAx / 2., myCz / 2.);
103   } else {
104     aRefAx2 = gp_Ax2(anOrigin, aDirY, aDirZ);
105     anElips = gp_Elips(aRefAx2, myCz / 2., myAx / 2.);
106   }
107
108   double aLowPositionFactor = sqrt(1. - (myZCut1 * myZCut1 * 4. / (myCz * myCz))) / 2.;
109   double aHighPositionFactor = sqrt(1. - (myZCut2 * myZCut2 * 4. / (myCz * myCz))) / 2.;
110
111   double aXEndTop = myAx * aHighPositionFactor;
112   double aXEndBottom = myAx *  aLowPositionFactor;
113
114   // Build the XZ ellipse
115   gp_Pnt anEndPoint1(aXEndTop, 0., myZCut2);
116   gp_Pnt anEndPoint2(aXEndBottom, 0., -myZCut1);
117   BRepBuilderAPI_MakeEdge anElipsBuilder(anElips, anEndPoint1, anEndPoint2);
118   anElipsBuilder.Build();
119   TopoDS_Edge anOuterEdge = anElipsBuilder.Edge();
120
121   // Perform a revolution based on the section to build a simple version of the outer face
122   // (isotropic in XY)
123   BRepPrimAPI_MakeRevol aRevolBuilder(anOuterEdge, aZAxis, 2. * M_PI, Standard_True);
124   if (!aRevolBuilder.IsDone()) {
125     myError = "Ellipsoid builder :: section revolution did not succeed";
126     return;
127   }
128
129   gp_GTrsf aGTrsf;
130   gp_Mat rot (1.,          0., 0.,
131               0., myBy / myAx, 0.,
132               0.,          0., 1.);
133
134   aGTrsf.SetVectorialPart(rot);
135
136   BRepBuilderAPI_GTransform aScaleBuilder(aRevolBuilder.Shape(), aGTrsf, true);
137   if (!aScaleBuilder.IsDone()) {
138     myError = "Ellipsoid builder :: scale did not succeed";
139     return;
140   }
141
142   TopoDS_Face anOuterFace = TopoDS::Face(aScaleBuilder.Shape());
143   aSewer.Add(TopoDS::Face(anOuterFace.Reversed()));
144
145   // Build the high and low ellipse if needed
146   gp_Ax2 aLowAx2;
147   gp_Ax2 aHighAx2;
148   gp_Elips aLowElips;
149   gp_Elips aHighElips;
150   if (myBy < myAx) {
151     if ((myCz / 2. - myZCut1) > Precision::Confusion()) {
152       aLowAx2 = gp_Ax2(gp_Pnt(0., 0., -myZCut1), aDirZ, aDirX);
153       aLowElips = gp_Elips(aLowAx2, aLowPositionFactor * myAx, aLowPositionFactor * myBy);
154     }
155     if ((myCz / 2. - myZCut2) > Precision::Confusion()) {
156       aHighAx2 = gp_Ax2(gp_Pnt(0., 0., myZCut2), aDirZ, aDirX);
157       aHighElips = gp_Elips(aHighAx2, aHighPositionFactor * myAx, aHighPositionFactor * myBy);
158     }
159   } else {
160     if ((myCz / 2. - myZCut1) > Precision::Confusion()) {
161       aLowAx2 = gp_Ax2(gp_Pnt(0., 0., -myZCut1), aDirZ, aDirY);
162       aLowElips = gp_Elips(aLowAx2, aLowPositionFactor * myBy, aLowPositionFactor * myAx);
163     }
164     if ((myCz / 2. - myZCut2) > Precision::Confusion()) {
165       aHighAx2 = gp_Ax2(gp_Pnt(0., 0., myZCut2), aDirZ, aDirY);
166       aHighElips = gp_Elips(aHighAx2, aHighPositionFactor * myBy, aHighPositionFactor * myAx);
167     }
168   }
169
170   // Make higher and lower elliptical faces if needed
171   if ((myCz / 2. - myZCut1) > Precision::Confusion()) {
172     TopoDS_Face aBottomFace;
173     BRepBuilderAPI_MakeEdge aBottomEdgeMk(aLowElips);
174     aBottomEdgeMk.Build();
175     BRepBuilderAPI_MakeWire aBottomWireMk;
176     aBottomWireMk.Add(aBottomEdgeMk.Edge());
177     BRepBuilderAPI_MakeFace aBottomFaceMk(aBottomWireMk.Wire());
178     aBottomFace = aBottomFaceMk.Face();
179     aSewer.Add(TopoDS::Face(aBottomFace.Reversed()));
180   }
181   if ((myCz / 2. - myZCut2) > Precision::Confusion()) {
182     TopoDS_Face aTopFace;
183     BRepBuilderAPI_MakeEdge aTopEdgeMk(aHighElips);
184     aTopEdgeMk.Build();
185     BRepBuilderAPI_MakeWire aTopWireMk;
186     aTopWireMk.Add(aTopEdgeMk.Edge());
187     BRepBuilderAPI_MakeFace aTopFaceMk(aTopWireMk.Wire());
188     aTopFace = aTopFaceMk.Face();
189     aSewer.Add(TopoDS::Face(aTopFace.Reversed()));
190   }
191
192   TopoDS_Shell aShell;
193   aSewer.Perform();
194   if ((myCz / 2. - myZCut2) > Precision::Confusion() ||
195       (myCz / 2. - myZCut1) > Precision::Confusion()) {
196     aShell = TopoDS::Shell(aSewer.SewedShape());
197   } else {
198     TopoDS_Builder aBuilder;
199     aBuilder.MakeShell(aShell);
200     aBuilder.Add(aShell, aSewer.SewedShape());
201   }
202
203   BRepBuilderAPI_MakeSolid *anEllipsoidMk = new BRepBuilderAPI_MakeSolid(aShell);
204   anEllipsoidMk->Build();
205
206   // Store and publish the results
207   std::shared_ptr<GeomAPI_Shape> aResultShape =
208     std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
209   aResultShape->setImpl(new TopoDS_Shape(anEllipsoidMk->Solid()));
210   setShape(aResultShape);
211
212   // Test on the shapes
213   if (!(aResultShape).get() || aResultShape->isNull()) {
214     myError = "Ellipsoid builder  :: resulting shape is null.";
215     return;
216   }
217
218   setImpl(anEllipsoidMk);
219   setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
220
221   setDone(true);
222 }