SPIDAR API Library  0x16033101
Space Interface Device for Artificial Reality
Quaternion.hpp
Go to the documentation of this file.
1 
5 #ifndef SPIDAR_QUATERNION_HPP
6 #define SPIDAR_QUATERNION_HPP
7 
8 #include <cmath>
9 
10 #include "Vector.hpp"
11 
12 namespace Spidar
13 {
14 namespace Math
15  {
23 template <class T>
24 struct Quaternion
25 {
26  typedef T ValueType;
28 
29  ValueType x, y, z, w;
30 
31  // コンストラクタ
32  Quaternion(void)
33  {
34  x = y = z = 0;
35  w = 1;
36  }
37 
38  Quaternion(const Quaternion& other)
39  {
40  x = other.x;
41  y = other.y;
42  z = other.z;
43  w = other.w;
44  }
45 
46  explicit Quaternion(const VectorType& v)
47  {
48  w = 0;
49  x = v[0];
50  y = v[1];
51  z = v[2];
52  }
53 
54  template <class T>
55  explicit Quaternion(T x, T y, T z, T w)
56  {
57  this->x = static_cast<ValueType>(x);
58  this->y = static_cast<ValueType>(y);
59  this->z = static_cast<ValueType>(z);
60  this->w = static_cast<ValueType>(w);
61  }
62 
63  Quaternion(ValueType angle, const VectorType &axis)
64  {
65  w = static_cast<ValueType>(cos(0.5*angle));
66 
67  ValueType s = static_cast<ValueType>(sin(0.5*angle) / axis.norm());
68 
69  x = axis[0] * s;
70  y = axis[1] * s;
71  z = axis[2] * s;
72  }
73 
74  template <class OtherType>
75  explicit Quaternion(const OtherType &other)
76  {
77  x = static_cast<ValueType>(other.x);
78  y = static_cast<ValueType>(other.y);
79  z = static_cast<ValueType>(other.z);
80  w = static_cast<ValueType>(other.w);
81  }
82 
83  Quaternion& operator=(const Quaternion &other)
84  {
85  x = other.x;
86  y = other.y;
87  z = other.z;
88  w = other.w;
89 
90  return *this;
91  }
92 
93  template <class OtherType>
94  Quaternion& operator=(const OtherType &other)
95  {
96  x = static_cast<ValueType>(other.x);
97  y = static_cast<ValueType>(other.y);
98  z = static_cast<ValueType>(other.z);
99  w = static_cast<ValueType>(other.w);
100 
101  return *this;
102  }
103 
104  Quaternion& operator+=(const Quaternion &other)
105  {
106  x += static_cast<ValueType>(other.x);
107  y += static_cast<ValueType>(other.y);
108  z += static_cast<ValueType>(other.z);
109  w += static_cast<ValueType>(other.w);
110 
111  return *this;
112  }
113 
114  Quaternion& operator-=(const Quaternion &other)
115  {
116  x -= static_cast<ValueType>(other.x);
117  y -= static_cast<ValueType>(other.y);
118  z -= static_cast<ValueType>(other.z);
119  w -= static_cast<ValueType>(other.w);
120 
121  return *this;
122  }
123 
124  Quaternion& operator*=(double value)
125  {
126  x = static_cast<ValueType>(value * x);
127  y = static_cast<ValueType>(value * y);
128  z = static_cast<ValueType>(value * z);
129  w = static_cast<ValueType>(value * w);
130 
131  return *this;
132  }
133 
134  Quaternion& operator*=(const Quaternion &other)
135  {
136  Quaternion temp;
137 
138  temp.x = w * other.x + x * other.w + y * other.z - z * other.y;
139  temp.y = w * other.y + y * other.w + z * other.x - x * other.z;
140  temp.z = w * other.z + z * other.w + x * other.y - y * other.x;
141  temp.w = w * other.w - x * other.x - y * other.y - z * other.z;
142 
143  *this = temp;
144 
145  return *this;
146  }
147 
148  Quaternion& operator/=(double value)
149  {
150  x = static_cast<ValueType>(x / value);
151  y = static_cast<ValueType>(y / value);
152  z = static_cast<ValueType>(z / value);
153  w = static_cast<ValueType>(w / value);
154 
155  return *this;
156  }
157 
158  //
159  ValueType angle(void) const
160  {
161  double temp = w;
162  double check = 1;
163  temp = std::min(temp, check);
164  check = -1;
165  temp = std::max(temp, check);
166  return static_cast<ValueType>(2.0 * std::acos(temp));
167  }
168 
169  //
170  VectorType axis(void) const
171  {
172  VectorType &r = static_cast<VectorType>(*this);
173  ValueType norm = r.norm();
174 
175  if (norm > 0) return r / norm;
176  else return VectorType(1, 0, 0);
177  }
178 
179  //
180  const ValueType dot(const Quaternion &other) const
181  {
182  return x * other.x + y * other.y + z * other.z + w * other.w;
183  }
184 
185  //
186  const ValueType norm(void) const
187  {
188  return static_cast<ValueType>(std::sqrt(static_cast<double>(dot(*this))));
189  }
190 
191  //
192  const Quaternion unit(void) const
193  {
194  double norm = std::sqrt(static_cast<double>(dot(*this)));
195 
196  if (norm>0) return *this / norm;
197  else return *this;
198  }
199 
200  //
201  Quaternion conjugated(void) const
202  {
203  Quaternion q(*this);
204  q.x = -q.x;
205  q.y = -q.y;
206  q.z = -q.z;
207  return q;
208  }
209 
210  //
211  Quaternion inv(void) const
212  {
213  Quaternion q(conjugated());
214 
215  ValueType temp = dot(*this);
216 
217  q.x /= temp;
218  q.y /= temp;
219  q.z /= temp;
220  q.w /= temp;
221 
222  return q;
223  }
224 
225  //
226  const Quaternion derivative(const VectorType &avel) const
227  {
228  return 0.5 * Quaternion(avel) * (*this);
229  }
230 
231  //
232  const VectorType angularVelocity(const Quaternion &qd) const
233  {
234  return *reinterpret_cast<const VectorType*>(&(qd * conjugated())) * 2.0;
235  }
236 
237  //
238  const VectorType rotate(const VectorType &v) const
239  {
240  return *reinterpret_cast<const VectorType*>(&(*this * Quaternion(v) * conjugated()));
241  }
242 
243 }; // end of struct Quaternion.
244 
245 //
246 template <class T>
247 std::ostream& operator<<(std::ostream &os, const Quaternion<T> &q)
248 {
249  os << "(" << q.w << " " << q.x << " " << q.y << " " << q.z << ")";
250 
251  return os;
252 }
253 
254 //
255 template <class T>
256 const Quaternion<T> operator+(Quaternion<T> lhs, const Quaternion<T> &rhs)
257 {
258  return lhs += rhs;
259 }
260 
261 //
262 template <class T>
263 const Quaternion<T> operator-(Quaternion<T> lhs, const Quaternion<T> &rhs)
264 {
265  return lhs -= rhs;
266 }
267 
268 //
269 template <class T>
270 const Quaternion<T> operator*(Quaternion<T> lhs, double rhs)
271 {
272  return lhs *= rhs;
273 }
274 
275 //
276 template <class T>
277 const Quaternion<T> operator*(double lhs, Quaternion<T> rhs)
278 {
279  return rhs *= lhs;
280 }
281 
282 //
283 template <class T>
284 const Quaternion<T> operator*(Quaternion<T> lhs, const Quaternion<T> &rhs)
285 {
286  return lhs *= rhs;
287 }
288 
289 //
290 template <class T>
291 const Quaternion<T> operator/(Quaternion<T> lhs, double rhs)
292 {
293  return lhs /= rhs;
294 }
295 
296 //
297 template <class T>
298 const Quaternion<T> slerp(const Quaternion<T> &from, const Quaternion<T> &to, double t)
299 {
300  typedef Quaternion<T> QuaternionType;
301  typedef typename QuaternionType::ValueType ValueType;
302 
303  QuaternionType q;
304 
305  double dot = from.dot(to);
306 
307  if (dot < 0)
308  {
309  dot = -dot;
310  q = Quaternion<T>(-to.x, -to.y, -to.z, -to.w);
311  }
312  else q = to;
313 
314  if (dot > 1) dot = 1;
315  if (dot < -1) dot = -1;
316 
317  double angle = static_cast<ValueType>(std::acos(dot));
318  ValueType sina = static_cast<ValueType>(std::sin(angle));
319  ValueType sinat = static_cast<ValueType>(std::sin(angle * t));
320  ValueType sinaomt = static_cast<ValueType>(std::sin(angle * (1.0-t)));
321 
322  if (sina)
323  {
324  return QuaternionType((from.x * sinaomt + q.x * sinat) / sina,
325  (from.y * sinaomt + q.y * sinat) / sina,
326  (from.z * sinaomt + q.z * sinat) / sina,
327  (from.w * sinaomt + q.w * sinat) / sina);
328  }
329  else
330  {
331  return from;
332  }
333 }
334 
335 } // end of namespace Math.
336 } // end of namespace Spidar.
337 
338 #endif // SPIDAR_QUATERNION_HPP
339 
340 // end of file.
ValueType w
四元数の要素
Definition: Quaternion.hpp:29
SPIDARライブラリのルート名前空間です.
ベクトルクラスです.
Definition: Vector.hpp:24
Vector< T, 3 > VectorType
ベクトルの型
Definition: Quaternion.hpp:27
T ValueType
要素の型
Definition: Quaternion.hpp:26
四元数クラスです.
Definition: Quaternion.hpp:24