OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
Rotation3D.cpp
Go to the documentation of this file.
1// ------------------------------------------------------------------------
2// $RCSfile: Rotation3D.cpp,v $
3// ------------------------------------------------------------------------
4// $Revision: 1.2 $
5// ------------------------------------------------------------------------
6// Copyright: see Copyright.readme
7// ------------------------------------------------------------------------
8//
9// Class: Rotation3D
10// Represents a rotation in 3-dimensional space.
11//
12// There are two possible external representations:
13//
14// - Matrix3D R.
15// The matrix R is an element of SO(3). Its column vectors define the
16// unit vectors of the rotated coordinate system, expressed in the
17// original system. This representation is used internally and can only
18// be read from a Rotation3D object. To build such an object, use the
19// other representation.
20//
21// - Vector3D V.
22// The direction of V defines the axis of rotation, and its length the
23// rotation angle. A zero vector represents the identity.
24//
25// ------------------------------------------------------------------------
26// Class category: BeamlineGeometry
27// ------------------------------------------------------------------------
28//
29// $Date: 2001/08/24 19:32:00 $
30// $Author: jsberg $
31//
32// ------------------------------------------------------------------------
33
35#include <algorithm>
36#include <cmath>
37
38
39// Class Rotation3D
40// ------------------------------------------------------------------------
41
42Rotation3D::Rotation3D(double vx, double vy, double vz):
43 R() {
44 double phi = std::sqrt(vx * vx + vy * vy + vz * vz);
45
46 if(phi != 0.0) {
47 double factor = std::sin(phi / 2.0) / phi;
48 double S0 = std::cos(phi / 2.0);
49 double S1 = factor * vx;
50 double S2 = factor * vy;
51 double S3 = factor * vz;
52
53 R(0, 0) = 2.0 * (S1 * S1 + S0 * S0) - 1.0;
54 R(0, 1) = 2.0 * (S1 * S2 - S0 * S3);
55 R(0, 2) = 2.0 * (S1 * S3 + S0 * S2);
56
57 R(1, 0) = 2.0 * (S2 * S1 + S0 * S3);
58 R(1, 1) = 2.0 * (S2 * S2 + S0 * S0) - 1.0;
59 R(1, 2) = 2.0 * (S2 * S3 - S0 * S1);
60
61 R(2, 0) = 2.0 * (S3 * S1 - S0 * S2);
62 R(2, 1) = 2.0 * (S3 * S2 + S0 * S1);
63 R(2, 2) = 2.0 * (S3 * S3 + S0 * S0) - 1.0;
64 }
65}
66
67
68void Rotation3D::getAxis(double &vx, double &vy, double &vz) const {
69 vx = (R(2, 1) - R(1, 2)) / 2.0;
70 vy = (R(0, 2) - R(2, 0)) / 2.0;
71 vz = (R(1, 0) - R(0, 1)) / 2.0;
72 double c = (R(0, 0) + R(1, 1) + R(2, 2) - 1.0) / 2.0;
73 double s = std::sqrt(vx * vx + vy * vy + vz * vz);
74 double phi = std::atan2(s, c);
75
76 if(c < 0.0) {
77 // NOTE: We must avoid negative arguments to sqrt(),
78 // which may occur due to rounding errors.
79 vx = (vx > 0.0 ? phi : (-phi)) * std::sqrt(std::max(R(0, 0) - c, 0.0) / (1.0 - c));
80 vy = (vy > 0.0 ? phi : (-phi)) * std::sqrt(std::max(R(1, 1) - c, 0.0) / (1.0 - c));
81 vz = (vz > 0.0 ? phi : (-phi)) * std::sqrt(std::max(R(2, 2) - c, 0.0) / (1.0 - c));
82 } else if(std::abs(s) > 1.0e-10) {
83 double factor = phi / s;
84 vx *= factor;
85 vy *= factor;
86 vz *= factor;
87 }
88}
89
90
92 double vx, vy, vz;
93 getAxis(vx, vy, vz);
94 return Vector3D(vx, vy, vz);
95}
96
97
99 Rotation3D inv;
100
101 for(int i = 0; i < 3; i++) {
102 for(int j = 0; j < 3; j++) {
103 inv.R(i, j) = R(j, i);
104 }
105 }
106
107 return inv;
108}
109
110
112 return (R(0, 1) == 0.0) && (R(1, 0) == 0.0) && (R(0, 2) == 0.0) && (R(2, 0) == 0.0);
113}
114
115
117 return (R(1, 2) == 0.0) && (R(2, 1) == 0.0) && (R(1, 0) == 0.0) && (R(0, 1) == 0.0);
118}
119
120
122 return (R(2, 0) == 0.0) && (R(0, 2) == 0.0) && (R(2, 1) == 0.0) && (R(1, 2) == 0.0);
123}
124
125
127 return Rotation3D();
128}
129
130
132 Rotation3D result;
133 result.R(1, 1) = result.R(2, 2) = std::cos(angle);
134 result.R(1, 2) = - (result.R(2, 1) = std::sin(angle));
135 return result;
136}
137
138
140 Rotation3D result;
141 result.R(2, 2) = result.R(0, 0) = std::cos(angle);
142 result.R(2, 0) = - (result.R(0, 2) = std::sin(angle));
143 return result;
144}
145
146
148 Rotation3D result;
149 result.R(0, 0) = result.R(1, 1) = std::cos(angle);
150 result.R(0, 1) = - (result.R(1, 0) = std::sin(angle));
151 return result;
152}
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
Rotation in 3-dimensional space.
Definition: Rotation3D.h:46
static Rotation3D Identity()
Make identity.
Definition: Rotation3D.cpp:126
Matrix3D R
Definition: Rotation3D.h:119
static Rotation3D ZRotation(double angle)
Make rotation.
Definition: Rotation3D.cpp:147
static Rotation3D YRotation(double angle)
Make rotation.
Definition: Rotation3D.cpp:139
Rotation3D inverse() const
Inversion.
Definition: Rotation3D.cpp:98
bool isPureXRotation() const
Test for rotation.
Definition: Rotation3D.cpp:111
Vector3D getAxis() const
Get axis vector.
Definition: Rotation3D.cpp:91
bool isPureZRotation() const
Test for rotation.
Definition: Rotation3D.cpp:121
static Rotation3D XRotation(double angle)
Make rotation.
Definition: Rotation3D.cpp:131
bool isPureYRotation() const
Test for rotation.
Definition: Rotation3D.cpp:116
Rotation3D()
Default constructor.
Definition: Rotation3D.h:126
A 3-dimension vector.
Definition: Vector3D.h:31