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