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 <BRepGProp.hxx>
37 #include <GProp_GProps.hxx>
38 #include <Precision.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopoDS_Wire.hxx>
42 //==================================================================================================
43 GeomAPI_Solid::GeomAPI_Solid() : GeomAPI_Shape()
47 //==================================================================================================
48 GeomAPI_Solid::GeomAPI_Solid(const std::shared_ptr<GeomAPI_Shape>& theShape)
50 if (!theShape->isNull() && theShape->isSolid()) {
51 setImpl(new TopoDS_Shape(theShape->impl<TopoDS_Shape>()));
55 //==================================================================================================
56 std::shared_ptr<GeomAPI_Sphere> GeomAPI_Solid::getSphere() const
58 GeomSpherePtr aSphere;
59 ListOfShape aShells = subShapes(SHELL);
60 if (aShells.size() == 1)
61 aSphere = aShells.front()->shell()->getSphere();
65 //==================================================================================================
66 std::shared_ptr<GeomAPI_Cylinder> GeomAPI_Solid::getCylinder() const
68 bool isCylinder = false;
70 GeomPointPtr aLocation;
75 GeomPlanePtr aCaps[2];
77 for (TopExp_Explorer anExp(impl<TopoDS_Shape>(), TopAbs_FACE); anExp.More(); anExp.Next()) {
78 GeomFacePtr aFace(new GeomAPI_Face);
79 aFace->setImpl(new TopoDS_Shape(anExp.Current()));
81 GeomCylinderPtr aCurCyl = aFace->getCylinder();
83 if (isCylinder) { // at least one cylindrical face is found
85 if (Abs(aRadius - aCurCyl->radius()) >= Precision::Confusion() ||
86 // check directions are collinear
87 !anAxis->isParallel(aCurCyl->axis()) ||
88 // check current center is on the main axis
89 anAxis->xyz()->cross(aLocation->xyz()->decreased(aCurCyl->location()->xyz())
90 )->squareModulus() >= Precision::SquareConfusion()) {
95 else { // first cylinder is found
96 aLocation = aCurCyl->location();
98 // the plane is found => compare directions
99 if (!anAxis->isParallel(aCurCyl->axis()))
103 anAxis = aCurCyl->axis();
104 aRadius = aCurCyl->radius();
105 aHeight = aCurCyl->height();
110 // check the face is planar
111 bool isPlaneApplicable = false;
112 GeomPlanePtr aCurPln = aFace->getPlane();
114 // verify the plane is already exists
115 int aLastPlanIndex = 0;
116 while (aLastPlanIndex < 2) {
117 if (!aCaps[aLastPlanIndex]) {
119 aCaps[aLastPlanIndex] = aCurPln;
122 if (aCaps[aLastPlanIndex]->isCoincident(aCurPln))
127 isPlaneApplicable = aLastPlanIndex < 2;
130 if (isPlaneApplicable) {
131 if (!anAxis) // no cylinder is found, store the normal as further cylinder's axis
132 anAxis = aCurPln->direction();
141 isCylinder = isCylinder && aCaps[0] && aCaps[1] &&
142 aCaps[0]->direction()->isParallel(anAxis) &&
143 aCaps[1]->direction()->isParallel(anAxis);
145 GeomCylinderPtr aCylinder;
147 // intersect planes with cylinder's axis
148 std::shared_ptr<GeomAPI_XYZ> anAxisXYZ = anAxis->xyz();
149 std::shared_ptr<GeomAPI_XYZ> aLocationXYZ = aLocation->xyz();
150 double aParam0 = anAxisXYZ->dot( aCaps[0]->location()->xyz()->decreased(aLocationXYZ) );
151 double aParam1 = anAxisXYZ->dot( aCaps[1]->location()->xyz()->decreased(aLocationXYZ) );
152 if (aParam0 > aParam1 + Precision::Confusion()) {
153 double tmp = aParam0;
158 // update location of cylinder to be coincident with one of planes
159 aLocation->setX(aLocation->x() + aParam0 * anAxis->x());
160 aLocation->setY(aLocation->y() + aParam0 * anAxis->y());
161 aLocation->setZ(aLocation->z() + aParam0 * anAxis->z());
163 aHeight = aParam1 - aParam0;
165 aCylinder = GeomCylinderPtr(new GeomAPI_Cylinder(aLocation, anAxis, aRadius, aHeight));
170 //==================================================================================================
171 std::shared_ptr<GeomAPI_Cone> GeomAPI_Solid::getCone() const
180 GeomPlanePtr aCaps[2];
182 for (TopExp_Explorer anExp(impl<TopoDS_Shape>(), TopAbs_FACE); anExp.More(); anExp.Next()) {
183 GeomFacePtr aFace(new GeomAPI_Face);
184 aFace->setImpl(new TopoDS_Shape(anExp.Current()));
186 GeomConePtr aCurCone = aFace->getCone();
188 if (isCone) { // at least one conical face is found
189 // check equal apexes
190 if (anApex->distance(aCurCone->apex()) >= Precision::Confusion() ||
192 Abs(aSemiAngle - aCurCone->semiAngle() >= Precision::Confusion()) ||
193 // check axes are collinear
194 !anAxis->isParallel(aCurCone->axis())) {
199 else { // first cone is found
200 anApex = aCurCone->apex();
202 // the plane is found => compare directions
203 if (!anAxis->isParallel(aCurCone->axis()))
207 anAxis = aCurCone->axis();
208 aSemiAngle = aCurCone->semiAngle();
209 aHeight = aCurCone->height();
214 // check the face is planar
215 bool isPlaneApplicable = false;
216 GeomPlanePtr aCurPln = aFace->getPlane();
218 // verify the plane is already exists
219 int aLastPlanIndex = 0;
220 while (aLastPlanIndex < 2) {
221 if (!aCaps[aLastPlanIndex]) {
223 aCaps[aLastPlanIndex] = aCurPln;
226 if (aCaps[aLastPlanIndex]->isCoincident(aCurPln))
231 isPlaneApplicable = aLastPlanIndex < 2;
234 if (isPlaneApplicable) {
235 if (!anAxis) // no cone is found, store the normal as further cone's axis
236 anAxis = aCurPln->direction();
245 isCone = isCone && aCaps[0] && aCaps[0]->direction()->isParallel(anAxis);
246 if (isCone && aCaps[1]) // cone map have only one cap, if it is bounded by the apex
247 isCone = aCaps[1]->direction()->isParallel(anAxis);
251 // intersect planes with cone's axis
252 std::shared_ptr<GeomAPI_XYZ> anAxisXYZ = anAxis->xyz();
253 std::shared_ptr<GeomAPI_XYZ> anApexXYZ = anApex->xyz();
254 double aParam0 = anAxisXYZ->dot(aCaps[0]->location()->xyz()->decreased(anApexXYZ));
256 aCaps[1] ? anAxisXYZ->dot(aCaps[1]->location()->xyz()->decreased(anApexXYZ)) : 0.0;
257 if (aParam0 <= 0.0 && aParam1 <= 0.0) {
258 // reverse axis to make smaller cap be the first
263 if (aParam0 > aParam1 + Precision::Confusion()) {
264 double tmp = aParam0;
269 // calculate location of cone to be coincident with one of planes
270 GeomPointPtr aLocation(new GeomAPI_Pnt(
271 anApex->x() + aParam0 * anAxis->x(),
272 anApex->y() + aParam0 * anAxis->y(),
273 anApex->z() + aParam0 * anAxis->z()));
275 // calculate radii of caps
276 aParam0 *= Tan(aSemiAngle);
277 aParam1 *= Tan(aSemiAngle);
279 aCone = GeomConePtr(new GeomAPI_Cone(aLocation, anAxis, aSemiAngle, aParam0, aParam1));
284 //==================================================================================================
285 std::shared_ptr<GeomAPI_Torus> GeomAPI_Solid::getTorus() const
288 ListOfShape aShells = subShapes(SHELL);
289 if (aShells.size() == 1)
290 aTorus = aShells.front()->shell()->getTorus();
294 //==================================================================================================
295 std::shared_ptr<GeomAPI_Box> GeomAPI_Solid::getParallelepiped() const
298 ListOfShape aShells = subShapes(SHELL);
299 if (aShells.size() == 1)
300 aBox = aShells.front()->shell()->getParallelepiped();
304 //==================================================================================================
305 GeomPointPtr GeomAPI_Solid::middlePoint() const
307 GeomPointPtr anInnerPoint;
309 const TopoDS_Solid& aSolid = impl<TopoDS_Solid>();
314 BRepGProp::SurfaceProperties(aSolid, aProps, 1.e-4);
316 gp_Pnt aPnt = aProps.CentreOfMass();
317 anInnerPoint = GeomPointPtr(new GeomAPI_Pnt(aPnt.X(), aPnt.Y(), aPnt.Z()));