1 // Copyright (C) 2018-2019 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 "GeomAPI_Solid.h"
22 #include "GeomAPI_Box.h"
23 #include "GeomAPI_Cone.h"
24 #include "GeomAPI_Cylinder.h"
25 #include "GeomAPI_Dir.h"
26 #include "GeomAPI_Face.h"
27 #include "GeomAPI_Pln.h"
28 #include "GeomAPI_Pnt.h"
29 #include "GeomAPI_Shell.h"
30 #include "GeomAPI_Sphere.h"
31 #include "GeomAPI_Torus.h"
32 #include "GeomAPI_XYZ.h"
34 #include <BRep_Builder.hxx>
35 #include <BRepGProp.hxx>
36 #include <GProp_GProps.hxx>
37 #include <Precision.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TopoDS_Wire.hxx>
41 //==================================================================================================
42 GeomAPI_Solid::GeomAPI_Solid() : GeomAPI_Shape()
46 //==================================================================================================
47 GeomAPI_Solid::GeomAPI_Solid(const std::shared_ptr<GeomAPI_Shape>& theShape)
49 if (!theShape->isNull() && theShape->isSolid()) {
50 setImpl(new TopoDS_Shape(theShape->impl<TopoDS_Shape>()));
54 //==================================================================================================
55 std::shared_ptr<GeomAPI_Sphere> GeomAPI_Solid::getSphere() const
57 GeomSpherePtr aSphere;
58 ListOfShape aShells = subShapes(SHELL);
59 if (aShells.size() == 1)
60 aSphere = aShells.front()->shell()->getSphere();
64 //==================================================================================================
65 std::shared_ptr<GeomAPI_Cylinder> GeomAPI_Solid::getCylinder() const
67 bool isCylinder = false;
69 GeomPointPtr aLocation;
74 GeomPlanePtr aCaps[2];
76 for (TopExp_Explorer anExp(impl<TopoDS_Shape>(), TopAbs_FACE); anExp.More(); anExp.Next()) {
77 GeomFacePtr aFace(new GeomAPI_Face);
78 aFace->setImpl(new TopoDS_Shape(anExp.Current()));
80 GeomCylinderPtr aCurCyl = aFace->getCylinder();
82 if (isCylinder) { // at least one cylindrical face is found
84 if (Abs(aRadius - aCurCyl->radius()) >= Precision::Confusion() ||
85 // check directions are collinear
86 !anAxis->isParallel(aCurCyl->axis()) ||
87 // check current center is on the main axis
88 anAxis->xyz()->cross(aLocation->xyz()->decreased(aCurCyl->location()->xyz())
89 )->squareModulus() >= Precision::SquareConfusion()) {
94 else { // first cylinder is found
95 aLocation = aCurCyl->location();
97 // the plane is found => compare directions
98 if (!anAxis->isParallel(aCurCyl->axis()))
102 anAxis = aCurCyl->axis();
103 aRadius = aCurCyl->radius();
104 aHeight = aCurCyl->height();
109 // check the face is planar
110 bool isPlaneApplicable = false;
111 GeomPlanePtr aCurPln = aFace->getPlane();
113 // verify the plane is already exists
114 int aLastPlanIndex = 0;
115 while (aLastPlanIndex < 2) {
116 if (!aCaps[aLastPlanIndex]) {
118 aCaps[aLastPlanIndex] = aCurPln;
121 if (aCaps[aLastPlanIndex]->isCoincident(aCurPln))
126 isPlaneApplicable = aLastPlanIndex < 2;
129 if (isPlaneApplicable) {
130 if (!anAxis) // no cylinder is found, store the normal as further cylinder's axis
131 anAxis = aCurPln->direction();
140 isCylinder = isCylinder && aCaps[0] && aCaps[1] &&
141 aCaps[0]->direction()->isParallel(anAxis) &&
142 aCaps[1]->direction()->isParallel(anAxis);
144 GeomCylinderPtr aCylinder;
146 // intersect planes with cylinder's axis
147 std::shared_ptr<GeomAPI_XYZ> anAxisXYZ = anAxis->xyz();
148 std::shared_ptr<GeomAPI_XYZ> aLocationXYZ = aLocation->xyz();
149 double aParam0 = anAxisXYZ->dot( aCaps[0]->location()->xyz()->decreased(aLocationXYZ) );
150 double aParam1 = anAxisXYZ->dot( aCaps[1]->location()->xyz()->decreased(aLocationXYZ) );
151 if (aParam0 > aParam1 + Precision::Confusion()) {
152 double tmp = aParam0;
157 // update location of cylinder to be coincident with one of planes
158 aLocation->setX(aLocation->x() + aParam0 * anAxis->x());
159 aLocation->setY(aLocation->y() + aParam0 * anAxis->y());
160 aLocation->setZ(aLocation->z() + aParam0 * anAxis->z());
162 aHeight = aParam1 - aParam0;
164 aCylinder = GeomCylinderPtr(new GeomAPI_Cylinder(aLocation, anAxis, aRadius, aHeight));
169 //==================================================================================================
170 std::shared_ptr<GeomAPI_Cone> GeomAPI_Solid::getCone() const
179 GeomPlanePtr aCaps[2];
181 for (TopExp_Explorer anExp(impl<TopoDS_Shape>(), TopAbs_FACE); anExp.More(); anExp.Next()) {
182 GeomFacePtr aFace(new GeomAPI_Face);
183 aFace->setImpl(new TopoDS_Shape(anExp.Current()));
185 GeomConePtr aCurCone = aFace->getCone();
187 if (isCone) { // at least one conical face is found
188 // check equal apexes
189 if (anApex->distance(aCurCone->apex()) >= Precision::Confusion() ||
191 Abs(aSemiAngle - aCurCone->semiAngle() >= Precision::Confusion()) ||
192 // check axes are collinear
193 !anAxis->isParallel(aCurCone->axis())) {
198 else { // first cone is found
199 anApex = aCurCone->apex();
201 // the plane is found => compare directions
202 if (!anAxis->isParallel(aCurCone->axis()))
206 anAxis = aCurCone->axis();
207 aSemiAngle = aCurCone->semiAngle();
208 aHeight = aCurCone->height();
213 // check the face is planar
214 bool isPlaneApplicable = false;
215 GeomPlanePtr aCurPln = aFace->getPlane();
217 // verify the plane is already exists
218 int aLastPlanIndex = 0;
219 while (aLastPlanIndex < 2) {
220 if (!aCaps[aLastPlanIndex]) {
222 aCaps[aLastPlanIndex] = aCurPln;
225 if (aCaps[aLastPlanIndex]->isCoincident(aCurPln))
230 isPlaneApplicable = aLastPlanIndex < 2;
233 if (isPlaneApplicable) {
234 if (!anAxis) // no cone is found, store the normal as further cone's axis
235 anAxis = aCurPln->direction();
244 isCone = isCone && aCaps[0] && aCaps[0]->direction()->isParallel(anAxis);
245 if (isCone && aCaps[1]) // cone map have only one cap, if it is bounded by the apex
246 isCone = aCaps[1]->direction()->isParallel(anAxis);
250 // intersect planes with cone's axis
251 std::shared_ptr<GeomAPI_XYZ> anAxisXYZ = anAxis->xyz();
252 std::shared_ptr<GeomAPI_XYZ> anApexXYZ = anApex->xyz();
253 double aParam0 = anAxisXYZ->dot(aCaps[0]->location()->xyz()->decreased(anApexXYZ));
255 aCaps[1] ? anAxisXYZ->dot(aCaps[1]->location()->xyz()->decreased(anApexXYZ)) : 0.0;
256 if (aParam0 <= 0.0 && aParam1 <= 0.0) {
257 // reverse axis to make smaller cap be the first
262 if (aParam0 > aParam1 + Precision::Confusion()) {
263 double tmp = aParam0;
268 // calculate location of cone to be coincident with one of planes
269 GeomPointPtr aLocation(new GeomAPI_Pnt(
270 anApex->x() + aParam0 * anAxis->x(),
271 anApex->y() + aParam0 * anAxis->y(),
272 anApex->z() + aParam0 * anAxis->z()));
274 // calculate radii of caps
275 aParam0 *= Tan(aSemiAngle);
276 aParam1 *= Tan(aSemiAngle);
278 aCone = GeomConePtr(new GeomAPI_Cone(aLocation, anAxis, aSemiAngle, aParam0, aParam1));
283 //==================================================================================================
284 std::shared_ptr<GeomAPI_Torus> GeomAPI_Solid::getTorus() const
287 ListOfShape aShells = subShapes(SHELL);
288 if (aShells.size() == 1)
289 aTorus = aShells.front()->shell()->getTorus();
293 //==================================================================================================
294 std::shared_ptr<GeomAPI_Box> GeomAPI_Solid::getParallelepiped() const
297 ListOfShape aShells = subShapes(SHELL);
298 if (aShells.size() == 1)
299 aBox = aShells.front()->shell()->getParallelepiped();
303 //==================================================================================================
304 GeomPointPtr GeomAPI_Solid::middlePoint() const
306 GeomPointPtr anInnerPoint;
308 const TopoDS_Solid& aSolid = impl<TopoDS_Solid>();
313 BRepGProp::SurfaceProperties(aSolid, aProps, 1.e-4);
315 gp_Pnt aPnt = aProps.CentreOfMass();
316 anInnerPoint = GeomPointPtr(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z()));