1 // Copyright (C) 2017-2022 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 // File: GeomAlgoAPI_Sphere.h
21 // Created: 16 Mar 2017
22 // Author: Clarisse Genrault (CEA)
24 #include <GeomAlgoAPI_Sphere.h>
26 #include <gp_Circ.hxx>
28 #include <BRepBuilderAPI_MakeEdge.hxx>
29 #include <BRepBuilderAPI_MakeFace.hxx>
30 #include <BRepBuilderAPI_MakeWire.hxx>
32 #include <BRepPrimAPI_MakeRevol.hxx>
33 #include <BRepPrimAPI_MakeSphere.hxx>
35 //=================================================================================================
36 GeomAlgoAPI_Sphere::GeomAlgoAPI_Sphere(std::shared_ptr<GeomAPI_Pnt> theCenterPoint,
37 const double theRadius)
40 myCenterPoint = theCenterPoint;
44 //=================================================================================================
45 GeomAlgoAPI_Sphere::GeomAlgoAPI_Sphere(const double theRMin, const double theRMax,
46 const double thePhiMin, const double thePhiMax,
47 const double theThetaMin, const double theThetaMax)
54 myThetaMin = theThetaMin;
55 myThetaMax = theThetaMax;
58 //=================================================================================================
59 bool GeomAlgoAPI_Sphere::check()
62 if ((myRMin-myRMax) > Precision::Confusion()) {
63 myError = "Sphere builder :: RMin is larger than RMax.";
68 myError = "Sphere builder :: center is not valid.";
71 if (myRadius < Precision::Confusion()) {
72 myError = "Sphere builder :: radius is negative or null.";
79 //=================================================================================================
80 void GeomAlgoAPI_Sphere::build()
82 myCreatedFaces.clear();
86 const gp_Pnt& aCenterPoint = myCenterPoint->impl<gp_Pnt>();
88 // Construct the sphere
89 BRepPrimAPI_MakeSphere *aSphereMaker = new BRepPrimAPI_MakeSphere(aCenterPoint, myRadius);
91 aSphereMaker->Build();
93 if (!aSphereMaker->IsDone()) {
97 TopoDS_Shape aResult = aSphereMaker->Shape();
98 std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
99 aShape->setImpl(new TopoDS_Shape(aResult));
102 // Test on the shapes
103 if (!aShape.get() || aShape->isNull()) {
104 myError = "Sphere builder :: resulting shape is null.";
108 setImpl(aSphereMaker);
114 //=================================================================================================
115 void GeomAlgoAPI_Sphere::buildRootSphere()
117 myCreatedFaces.clear();
119 const double aStartPhiRad = myPhiMin * M_PI / 180.;
120 BRepBuilderAPI_MakeWire aWireBuilder;
122 gp_Pnt anOrigin(0., 0., 0.);
123 gp_Dir aNormal(-sin(aStartPhiRad), cos(aStartPhiRad), 0.);
126 // The section is defined by 4 points and up to 4 wires. In the rmin = 0 case, two of the points
127 // will actually be the origin
128 double aX = myRMax*sin(myThetaMin * M_PI/180.);
129 double aZ = myRMax*cos(myThetaMin * M_PI/180.);
130 gp_Pnt aTopOuterStart(aX*cos(aStartPhiRad), aX*sin(aStartPhiRad), aZ);
132 aX = myRMax*sin((myThetaMin+myThetaMax) * M_PI/180.);
133 aZ = myRMax*cos((myThetaMin+myThetaMax) * M_PI/180.);
134 gp_Pnt aBaseOuterEnd(aX*cos(aStartPhiRad), aX*sin(aStartPhiRad), aZ);
136 aX = myRMin*sin(myThetaMin * M_PI/180.);
137 aZ = myRMin*cos(myThetaMin * M_PI/180.);
138 gp_Pnt aTopInnerStart(aX*cos(aStartPhiRad), aX*sin(aStartPhiRad), aZ);
140 aX = myRMin*sin((myThetaMin+myThetaMax) * M_PI/180.);
141 aZ = myRMin*cos((myThetaMin+myThetaMax) * M_PI/180.);
142 gp_Pnt aBaseInnerEnd(aX*cos(aStartPhiRad), aX*sin(aStartPhiRad), aZ);
144 // There will always be the rmax arc since rmax can't be zero
145 gp_Circ anOuterCircle(gp_Ax2(anOrigin, aNormal), myRMax);
146 BRepBuilderAPI_MakeEdge anArcOuterBuilder;
147 if (aTopOuterStart.IsEqual(aBaseOuterEnd, Precision::Confusion()))
148 anArcOuterBuilder = BRepBuilderAPI_MakeEdge(anOuterCircle);
150 anArcOuterBuilder = BRepBuilderAPI_MakeEdge(anOuterCircle, aTopOuterStart, aBaseOuterEnd);
151 anArcOuterBuilder.Build();
153 // Two cases : either we need four edges (one being an arc with curvature radius rmin) or we
154 // need three (if rmin=0).
155 // In the later case the top and bottom edges intersect at the origin
156 // Add the edges to the wire in consecutive order (very important for the face to make sense
158 if(myRMin >= Precision::Confusion()){
159 gp_Circ anInnerCircle(gp_Ax2(anOrigin, aNormal), myRMin);
160 BRepBuilderAPI_MakeEdge anArcInnerBuilder;
161 if (aTopInnerStart.IsEqual(aBaseInnerEnd, Precision::Confusion()))
162 anArcInnerBuilder = BRepBuilderAPI_MakeEdge(anInnerCircle);
164 anArcInnerBuilder = BRepBuilderAPI_MakeEdge(anInnerCircle, aTopInnerStart, aBaseInnerEnd);
165 anArcInnerBuilder.Build();
167 BRepBuilderAPI_MakeEdge anEdgeStartBuilder(aTopInnerStart, aTopOuterStart);
168 anEdgeStartBuilder.Build();
169 BRepBuilderAPI_MakeEdge anEdgeEndBuilder(aBaseInnerEnd, aBaseOuterEnd);
170 anEdgeEndBuilder.Build();
172 aWireBuilder.Add(anEdgeStartBuilder.Edge());
173 aWireBuilder.Add(anArcOuterBuilder.Edge());
174 aWireBuilder.Add(anEdgeEndBuilder.Edge());
175 aWireBuilder.Add(anArcInnerBuilder.Edge());
178 BRepBuilderAPI_MakeEdge anEdgeStartBuilder(anOrigin, aTopOuterStart);
179 anEdgeStartBuilder.Build();
180 BRepBuilderAPI_MakeEdge anEdgeEndBuilder(anOrigin, aBaseOuterEnd);
181 anEdgeEndBuilder.Build();
183 aWireBuilder.Add(anArcOuterBuilder.Edge());
184 aWireBuilder.Add(anEdgeStartBuilder.Edge());
185 aWireBuilder.Add(anEdgeEndBuilder.Edge());
188 // Make a face from the wire
189 aWireBuilder.Build();
190 BRepBuilderAPI_MakeFace aFaceBuilder(aWireBuilder.Wire());
191 aFaceBuilder.Build();
193 if (!aFaceBuilder.IsDone()){
194 myError = "GDML sphere builder :: section is not valid";
198 // Mathematical tool objects needed by the revolution builder
199 gp_Dir aZDir(0., 0., 1.);
200 gp_Ax1 aZAxis(anOrigin, aZDir);
202 // Build the solid using the section face we've created and a revolution builder
203 BRepPrimAPI_MakeRevol* aRevolBuilder =
204 new BRepPrimAPI_MakeRevol(aFaceBuilder.Face(), aZAxis, myPhiMax * M_PI / 180., Standard_True);
207 myError = "GDML Sphere builder :: section revolution did not succeed";
209 if(!aRevolBuilder->IsDone()) {
210 myError = "GDML Sphere builder :: section revolution did not succeed";
214 // Get the shape, verify it, build a GeomAPI_Shape.
215 std::shared_ptr<GeomAPI_Shape> aResultShape =
216 std::shared_ptr<GeomAPI_Shape>(new GeomAPI_Shape());
217 aResultShape->setImpl(new TopoDS_Shape(aRevolBuilder->Shape()));
218 setShape(aResultShape);
220 // Test on the shapes
221 if (!(aResultShape).get() || aResultShape->isNull()) {
222 myError = "GDML Sphere builder :: resulting shape is null.";
226 setImpl(aRevolBuilder);
227 setBuilderType(OCCT_BRepBuilderAPI_MakeShape);