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