OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
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
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}
static Rotation3D Identity()
Make identity.
Matrix3D R
Definition Rotation3D.h:119
static Rotation3D ZRotation(double angle)
Make rotation.
static Rotation3D YRotation(double angle)
Make rotation.
Rotation3D inverse() const
Inversion.
bool isPureXRotation() const
Test for rotation.
Vector3D getAxis() const
Get axis vector.
bool isPureZRotation() const
Test for rotation.
static Rotation3D XRotation(double angle)
Make rotation.
bool isPureYRotation() const
Test for rotation.
Rotation3D()
Default constructor.
Definition Rotation3D.h:126
A 3-dimension vector.
Definition Vector3D.h:31