Salome HOME
Merge branch 'Dev_2.8.0'
[modules/shaper.git] / src / GeomAlgoAPI / GeomAlgoAPI_Rotation.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_Rotation.h"
22
23 #include <GeomAPI_XYZ.h>
24
25 #include <BRepBuilderAPI_Transform.hxx>
26
27 #include <gp_Ax1.hxx>
28 #include <gp_Dir.hxx>
29 #include <gp_Vec.hxx>
30
31 #include <Precision.hxx>
32
33 //=================================================================================================
34 GeomAlgoAPI_Rotation::GeomAlgoAPI_Rotation(std::shared_ptr<GeomAPI_Shape> theSourceShape,
35                                            std::shared_ptr<GeomAPI_Ax1>   theAxis,
36                                            double                         theAngle)
37 {
38   myMethodType = BY_ANGLE;
39   mySourceShape = theSourceShape;
40   myAxis = theAxis;
41   myAngle = theAngle;
42 }
43
44
45 //=================================================================================================
46 GeomAlgoAPI_Rotation::GeomAlgoAPI_Rotation(std::shared_ptr<GeomAPI_Shape> theSourceShape,
47                                            std::shared_ptr<GeomAPI_Pnt>   theCenterPoint,
48                                            std::shared_ptr<GeomAPI_Pnt>   theStartPoint,
49                                            std::shared_ptr<GeomAPI_Pnt>   theEndPoint)
50 {
51   myMethodType = BY_POINTS;
52   mySourceShape = theSourceShape;
53   myCenterPoint = theCenterPoint;
54   myStartPoint = theStartPoint;
55   myEndPoint = theEndPoint;
56 }
57
58 //=================================================================================================
59 bool GeomAlgoAPI_Rotation::check()
60 {
61   switch (myMethodType) {
62     case BY_ANGLE: {
63       if (!myAxis) {
64         myError = "Rotation builder :: axis is not valid.";
65         return false;
66       }
67       if (!mySourceShape) {
68         myError = "Rotation builder :: source shape is not valid.";
69         return false;
70       }
71       return true;
72     }
73     case BY_POINTS: {
74       if (!myCenterPoint) {
75         myError = "Rotation builder :: center point is not valid.";
76         return false;
77       }
78       if (!myStartPoint) {
79         myError = "Rotation builder :: start point is not valid.";
80         return false;
81       }
82       if (!myEndPoint) {
83         myError = "Rotation builder :: end point is not valid.";
84         return false;
85       }
86       if (!mySourceShape) {
87         myError = "Rotation builder :: source shape is not valid.";
88         return false;
89       }
90       if(myCenterPoint->distance(myStartPoint) < Precision::Confusion()) {
91         myError = "Rotation builder :: center point and start point coincide.";
92         return false;
93       }
94       if(myCenterPoint->distance(myEndPoint) < Precision::Confusion()) {
95         myError = "Rotation builder :: center point and end point coincide.";
96         return false;
97       }
98       if(myStartPoint->distance(myEndPoint) < Precision::Confusion()) {
99         myError = "Rotation builder :: start point and end point coincide.";
100         return false;
101       }
102       std::shared_ptr<GeomAPI_XYZ> aCenterPointXYZ = myCenterPoint->xyz();
103       std::shared_ptr<GeomAPI_XYZ> aStartPointXYZ = myStartPoint->xyz();
104       std::shared_ptr<GeomAPI_XYZ> aEndPointXYZ = myEndPoint->xyz();
105       std::shared_ptr<GeomAPI_XYZ> vectCenterPointStartPoint =
106         aStartPointXYZ->decreased(aCenterPointXYZ);
107       std::shared_ptr<GeomAPI_XYZ> vectCenterPointEndPoint =
108         aEndPointXYZ->decreased(aCenterPointXYZ);
109       std::shared_ptr<GeomAPI_XYZ> crossProduct =
110         vectCenterPointStartPoint->cross(vectCenterPointEndPoint);
111       std::shared_ptr<GeomAPI_Pnt> aOriginPnt =
112         std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(0.,0.,0.));
113       std::shared_ptr<GeomAPI_XYZ> aOriginXYZ = aOriginPnt->xyz();
114
115       if (crossProduct->distance(aOriginXYZ) < Precision::Confusion()) {
116         myError = "Rotation builder :: center point, start point and end point are on a line.";
117         return false;
118       }
119       return true;
120     }
121     default: {
122       myError = "Rotation builder :: method not implemented.";
123       return false;
124     }
125   }
126 }
127
128 //=================================================================================================
129 void GeomAlgoAPI_Rotation::build()
130 {
131   gp_Trsf* aTrsf = new gp_Trsf();
132
133   switch (myMethodType) {
134     case BY_ANGLE: {
135       const gp_Ax1& anAxis = myAxis->impl<gp_Ax1>();
136       aTrsf->SetRotation(anAxis, myAngle/180.0*M_PI);
137       break;
138     }
139     case BY_POINTS: {
140       const gp_Pnt& aCenterPoint = myCenterPoint->impl<gp_Pnt>();
141       const gp_Pnt& aStartPoint = myStartPoint->impl<gp_Pnt>();
142       const gp_Pnt& aEndPoint = myEndPoint->impl<gp_Pnt>();
143       gp_Vec aVec1(aCenterPoint, aStartPoint);
144       gp_Vec aVec2(aCenterPoint, aEndPoint);
145       gp_Dir aDir(aVec1^aVec2);
146       gp_Ax1 anAxis(aCenterPoint, aDir);
147       double anAngle = aVec1.Angle(aVec2);
148       if (fabs(anAngle) < Precision::Angular()) anAngle += 2.*M_PI;
149       aTrsf->SetRotation(anAxis, anAngle);
150       break;
151     }
152     default: {
153       myError = "Rotation builder :: method not supported";
154       return;
155     }
156   }
157
158   const TopoDS_Shape& aSourceShape = mySourceShape->impl<TopoDS_Shape>();
159
160   if(aSourceShape.IsNull()) {
161     myError = "Rotation builder :: source shape does not contain any actual shape.";
162     return;
163   }
164
165   // Transform the shape while copying it.
166   BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aSourceShape, *aTrsf, true);
167   if(!aBuilder) {
168     myError = "Rotation builder :: transform initialization failed.";
169     return;
170   }
171
172   setImpl(aBuilder);
173   setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
174
175   if(!aBuilder->IsDone()) {
176     myError = "Rotation builder :: algorithm failed.";
177     return;
178   }
179
180   TopoDS_Shape aResult = aBuilder->Shape();
181
182   std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
183   aShape->setImpl(new TopoDS_Shape(aResult));
184   setShape(aShape);
185   setDone(true);
186 }