Salome HOME
Add copyright header according to request of CEA from 06.06.2017
[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       if (myAngle < -360.) {
72         myError = "Rotation builder :: angle smaller than -360 degrees.";
73         return false;
74       }
75       if (myAngle > 360.) {
76         myError = "Rotation builder :: angle greater than 360 degrees.";
77         return false;
78       }
79       return true;
80     }
81     case BY_POINTS: {
82       if (!myCenterPoint) {
83         myError = "Rotation builder :: center point is not valid.";
84         return false;
85       }
86       if (!myStartPoint) {
87         myError = "Rotation builder :: start point is not valid.";
88         return false;
89       }
90       if (!myEndPoint) {
91         myError = "Rotation builder :: end point is not valid.";
92         return false;
93       }
94       if (!mySourceShape) {
95         myError = "Rotation builder :: source shape is not valid.";
96         return false;
97       }
98       if(myCenterPoint->distance(myStartPoint) < Precision::Confusion()) {
99         myError = "Rotation builder :: center point and start point coincide.";
100         return false;
101       }
102       if(myCenterPoint->distance(myEndPoint) < Precision::Confusion()) {
103         myError = "Rotation builder :: center point and end point coincide.";
104         return false;
105       }
106       if(myStartPoint->distance(myEndPoint) < Precision::Confusion()) {
107         myError = "Rotation builder :: start point and end point coincide.";
108         return false;
109       }
110       std::shared_ptr<GeomAPI_XYZ> aCenterPointXYZ = myCenterPoint->xyz();
111       std::shared_ptr<GeomAPI_XYZ> aStartPointXYZ = myStartPoint->xyz();
112       std::shared_ptr<GeomAPI_XYZ> aEndPointXYZ = myEndPoint->xyz();
113       std::shared_ptr<GeomAPI_XYZ> vectCenterPointStartPoint =
114         aStartPointXYZ->decreased(aCenterPointXYZ);
115       std::shared_ptr<GeomAPI_XYZ> vectCenterPointEndPoint =
116         aEndPointXYZ->decreased(aCenterPointXYZ);
117       std::shared_ptr<GeomAPI_XYZ> crossProduct =
118         vectCenterPointStartPoint->cross(vectCenterPointEndPoint);
119       std::shared_ptr<GeomAPI_Pnt> aOriginPnt =
120         std::shared_ptr<GeomAPI_Pnt>(new GeomAPI_Pnt(0.,0.,0.));
121       std::shared_ptr<GeomAPI_XYZ> aOriginXYZ = aOriginPnt->xyz();
122
123       if (crossProduct->distance(aOriginXYZ) < Precision::Confusion()) {
124         myError = "Rotation builder :: center point, start point and end point are on a line.";
125         return false;
126       }
127       return true;
128     }
129     default: {
130       myError = "Rotation builder :: method not implemented.";
131       return false;
132     }
133   }
134 }
135
136 //=================================================================================================
137 void GeomAlgoAPI_Rotation::build()
138 {
139   gp_Trsf* aTrsf = new gp_Trsf();
140
141   switch (myMethodType) {
142     case BY_ANGLE: {
143       const gp_Ax1& anAxis = myAxis->impl<gp_Ax1>();
144       aTrsf->SetRotation(anAxis, myAngle/180.0*M_PI);
145       break;
146     }
147     case BY_POINTS: {
148       const gp_Pnt& aCenterPoint = myCenterPoint->impl<gp_Pnt>();
149       const gp_Pnt& aStartPoint = myStartPoint->impl<gp_Pnt>();
150       const gp_Pnt& aEndPoint = myEndPoint->impl<gp_Pnt>();
151       gp_Vec aVec1(aCenterPoint, aStartPoint);
152       gp_Vec aVec2(aCenterPoint, aEndPoint);
153       gp_Dir aDir(aVec1^aVec2);
154       gp_Ax1 anAxis(aCenterPoint, aDir);
155       double anAngle = aVec1.Angle(aVec2);
156       if (fabs(anAngle) < Precision::Angular()) anAngle += 2.*M_PI;
157       aTrsf->SetRotation(anAxis, anAngle);
158       break;
159     }
160     default: {
161       myError = "Rotation builder :: method not supported";
162       return;
163     }
164   }
165
166   const TopoDS_Shape& aSourceShape = mySourceShape->impl<TopoDS_Shape>();
167
168   if(aSourceShape.IsNull()) {
169     myError = "Rotation builder :: source shape does not contain any actual shape.";
170     return;
171   }
172
173   // Transform the shape while copying it.
174   BRepBuilderAPI_Transform* aBuilder = new BRepBuilderAPI_Transform(aSourceShape, *aTrsf, true);
175   if(!aBuilder) {
176     myError = "Rotation builder :: transform initialization failed.";
177     return;
178   }
179
180   setImpl(aBuilder);
181   setBuilderType(OCCT_BRepBuilderAPI_MakeShape);
182
183   if(!aBuilder->IsDone()) {
184     myError = "Rotation builder :: algorithm failed.";
185     return;
186   }
187
188   TopoDS_Shape aResult = aBuilder->Shape();
189
190   std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
191   aShape->setImpl(new TopoDS_Shape(aResult));
192   setShape(aShape);
193   setDone(true);
194 }