1 // Copyright (C) 2018-20xx 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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "GeomAPI_Solid.h"
23 #include "GeomAPI_Box.h"
24 #include "GeomAPI_Cone.h"
25 #include "GeomAPI_Cylinder.h"
26 #include "GeomAPI_Dir.h"
27 #include "GeomAPI_Face.h"
28 #include "GeomAPI_Pln.h"
29 #include "GeomAPI_Pnt.h"
30 #include "GeomAPI_Shell.h"
31 #include "GeomAPI_Sphere.h"
32 #include "GeomAPI_Torus.h"
33 #include "GeomAPI_XYZ.h"
35 #include <BRep_Builder.hxx>
36 #include <Precision.hxx>
37 #include <TopExp_Explorer.hxx>
38 #include <TopoDS_Wire.hxx>
40 //==================================================================================================
41 GeomAPI_Solid::GeomAPI_Solid() : GeomAPI_Shape()
45 //==================================================================================================
46 GeomAPI_Solid::GeomAPI_Solid(const std::shared_ptr<GeomAPI_Shape>& theShape)
48 if (!theShape->isNull() && theShape->isSolid()) {
49 setImpl(new TopoDS_Shape(theShape->impl<TopoDS_Shape>()));
53 //==================================================================================================
54 std::shared_ptr<GeomAPI_Sphere> GeomAPI_Solid::getSphere() const
56 GeomSpherePtr aSphere;
57 ListOfShape aShells = subShapes(SHELL);
58 if (aShells.size() == 1)
59 aSphere = aShells.front()->shell()->getSphere();
63 //==================================================================================================
64 std::shared_ptr<GeomAPI_Cylinder> GeomAPI_Solid::getCylinder() const
66 bool isCylinder = false;
68 GeomPointPtr aLocation;
73 GeomPlanePtr aCaps[2];
75 for (TopExp_Explorer anExp(impl<TopoDS_Shape>(), TopAbs_FACE); anExp.More(); anExp.Next()) {
76 GeomFacePtr aFace(new GeomAPI_Face);
77 aFace->setImpl(new TopoDS_Shape(anExp.Current()));
79 GeomCylinderPtr aCurCyl = aFace->getCylinder();
81 if (isCylinder) { // at least one cylindrical face is found
83 if (Abs(aRadius - aCurCyl->radius()) >= Precision::Confusion() ||
84 // check directions are collinear
85 !anAxis->isParallel(aCurCyl->axis()) ||
86 // check current center is on the main axis
87 anAxis->xyz()->cross(aLocation->xyz()->decreased(aCurCyl->location()->xyz())
88 )->squareModulus() >= Precision::SquareConfusion()) {
93 else { // first cylinder is found
94 aLocation = aCurCyl->location();
96 // the plane is found => compare directions
97 if (!anAxis->isParallel(aCurCyl->axis()))
101 anAxis = aCurCyl->axis();
102 aRadius = aCurCyl->radius();
103 aHeight = aCurCyl->height();
108 // check the face is planar
109 bool isPlaneApplicable = false;
110 GeomPlanePtr aCurPln = aFace->getPlane();
112 // verify the plane is already exists
113 int aLastPlanIndex = 0;
114 while (aLastPlanIndex < 2) {
115 if (!aCaps[aLastPlanIndex]) {
117 aCaps[aLastPlanIndex] = aCurPln;
120 if (aCaps[aLastPlanIndex]->isCoincident(aCurPln))
125 isPlaneApplicable = aLastPlanIndex < 2;
128 if (isPlaneApplicable) {
129 if (!anAxis) // no cylinder is found, store the normal as further cylinder's axis
130 anAxis = aCurPln->direction();
139 isCylinder = isCylinder && aCaps[0] && aCaps[1] &&
140 aCaps[0]->direction()->isParallel(anAxis) &&
141 aCaps[1]->direction()->isParallel(anAxis);
143 GeomCylinderPtr aCylinder;
145 // intersect planes with cylinder's axis
146 std::shared_ptr<GeomAPI_XYZ> anAxisXYZ = anAxis->xyz();
147 std::shared_ptr<GeomAPI_XYZ> aLocationXYZ = aLocation->xyz();
148 double aParam0 = anAxisXYZ->dot( aCaps[0]->location()->xyz()->decreased(aLocationXYZ) );
149 double aParam1 = anAxisXYZ->dot( aCaps[1]->location()->xyz()->decreased(aLocationXYZ) );
150 if (aParam0 > aParam1 + Precision::Confusion()) {
151 double tmp = aParam0;
156 // update location of cylinder to be coincident with one of planes
157 aLocation->setX(aLocation->x() + aParam0 * anAxis->x());
158 aLocation->setY(aLocation->y() + aParam0 * anAxis->y());
159 aLocation->setZ(aLocation->z() + aParam0 * anAxis->z());
161 aHeight = aParam1 - aParam0;
163 aCylinder = GeomCylinderPtr(new GeomAPI_Cylinder(aLocation, anAxis, aRadius, aHeight));
168 //==================================================================================================
169 std::shared_ptr<GeomAPI_Cone> GeomAPI_Solid::getCone() const
178 GeomPlanePtr aCaps[2];
180 for (TopExp_Explorer anExp(impl<TopoDS_Shape>(), TopAbs_FACE); anExp.More(); anExp.Next()) {
181 GeomFacePtr aFace(new GeomAPI_Face);
182 aFace->setImpl(new TopoDS_Shape(anExp.Current()));
184 GeomConePtr aCurCone = aFace->getCone();
186 if (isCone) { // at least one conical face is found
187 // check equal apexes
188 if (anApex->distance(aCurCone->apex()) >= Precision::Confusion() ||
190 Abs(aSemiAngle - aCurCone->semiAngle() >= Precision::Confusion()) ||
191 // check axes are collinear
192 !anAxis->isParallel(aCurCone->axis())) {
197 else { // first cone is found
198 anApex = aCurCone->apex();
200 // the plane is found => compare directions
201 if (!anAxis->isParallel(aCurCone->axis()))
205 anAxis = aCurCone->axis();
206 aSemiAngle = aCurCone->semiAngle();
207 aHeight = aCurCone->height();
212 // check the face is planar
213 bool isPlaneApplicable = false;
214 GeomPlanePtr aCurPln = aFace->getPlane();
216 // verify the plane is already exists
217 int aLastPlanIndex = 0;
218 while (aLastPlanIndex < 2) {
219 if (!aCaps[aLastPlanIndex]) {
221 aCaps[aLastPlanIndex] = aCurPln;
224 if (aCaps[aLastPlanIndex]->isCoincident(aCurPln))
229 isPlaneApplicable = aLastPlanIndex < 2;
232 if (isPlaneApplicable) {
233 if (!anAxis) // no cone is found, store the normal as further cone's axis
234 anAxis = aCurPln->direction();
243 isCone = isCone && aCaps[0] && aCaps[0]->direction()->isParallel(anAxis);
244 if (isCone && aCaps[1]) // cone map have only one cap, if it is bounded by the apex
245 isCone = aCaps[1]->direction()->isParallel(anAxis);
249 // intersect planes with cone's axis
250 std::shared_ptr<GeomAPI_XYZ> anAxisXYZ = anAxis->xyz();
251 std::shared_ptr<GeomAPI_XYZ> anApexXYZ = anApex->xyz();
252 double aParam0 = anAxisXYZ->dot(aCaps[0]->location()->xyz()->decreased(anApexXYZ));
254 aCaps[1] ? anAxisXYZ->dot(aCaps[1]->location()->xyz()->decreased(anApexXYZ)) : 0.0;
255 if (aParam0 <= 0.0 && aParam1 <= 0.0) {
256 // reverse axis to make smaller cap be the first
261 if (aParam0 > aParam1 + Precision::Confusion()) {
262 double tmp = aParam0;
267 // calculate location of cone to be coincident with one of planes
268 GeomPointPtr aLocation(new GeomAPI_Pnt(
269 anApex->x() + aParam0 * anAxis->x(),
270 anApex->y() + aParam0 * anAxis->y(),
271 anApex->z() + aParam0 * anAxis->z()));
273 // calculate radii of caps
274 aParam0 /= Cos(aSemiAngle);
275 aParam1 /= Cos(aSemiAngle);
277 aCone = GeomConePtr(new GeomAPI_Cone(aLocation, anAxis, aSemiAngle, aParam0, aParam1));
282 //==================================================================================================
283 std::shared_ptr<GeomAPI_Torus> GeomAPI_Solid::getTorus() const
286 ListOfShape aShells = subShapes(SHELL);
287 if (aShells.size() == 1)
288 aTorus = aShells.front()->shell()->getTorus();
292 //==================================================================================================
293 std::shared_ptr<GeomAPI_Box> GeomAPI_Solid::getParallelepiped() const
296 ListOfShape aShells = subShapes(SHELL);
297 if (aShells.size() == 1)
298 aBox = aShells.front()->shell()->getParallelepiped();