• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • lib
  • marble
Quaternion.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2006-2007 Torsten Rahn <tackat@kde.org>
9 // Copyright 2007 Inge Wallin <ingwa@kde.org>
10 // Copyright 2011 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
11 //
12 
13 #include "Quaternion.h"
14 
15 #include <cmath>
16 using namespace std;
17 
18 #include <QString>
19 #include <QDebug>
20 
21 
22 using namespace Marble;
23 
24 Quaternion::Quaternion()
25 {
26 // like in libeigen we keep the quaternion uninitialized
27 // set( 1.0, 0.0, 0.0, 0.0 );
28 }
29 
30 Quaternion::Quaternion(qreal w, qreal x, qreal y, qreal z)
31 {
32  v[Q_W] = w;
33  v[Q_X] = x;
34  v[Q_Y] = y;
35  v[Q_Z] = z;
36 }
37 
38 Quaternion Quaternion::fromSpherical(qreal lon, qreal lat)
39 {
40  const qreal w = 0.0;
41  const qreal x = cos(lat) * sin(lon);
42  const qreal y = sin(lat);
43  const qreal z = cos(lat) * cos(lon);
44 
45  return Quaternion( w, x, y, z );
46 }
47 
48 void Quaternion::getSpherical(qreal &lon, qreal &lat) const
49 {
50  qreal y = v[Q_Y];
51  if ( y > 1.0 )
52  y = 1.0;
53  else if ( y < -1.0 )
54  y = -1.0;
55 
56  lat = asin( y );
57 
58  if(v[Q_X] * v[Q_X] + v[Q_Z] * v[Q_Z] > 0.00005)
59  lon = atan2(v[Q_X], v[Q_Z]);
60  else
61  lon = 0.0;
62 }
63 
64 void Quaternion::normalize()
65 {
66  (*this) *= 1.0 / length();
67 }
68 
69 qreal Quaternion::length() const
70 {
71  return sqrt(v[Q_W] * v[Q_W] + v[Q_X] * v[Q_X] + v[Q_Y] * v[Q_Y] + v[Q_Z] * v[Q_Z]);
72 }
73 
74 Quaternion& Quaternion::operator*=(qreal mult)
75 {
76  (*this) = (*this) * mult;
77 
78  return *this;
79 }
80 
81 Quaternion Quaternion::inverse() const
82 {
83  Quaternion inverse( v[Q_W], -v[Q_X], -v[Q_Y], -v[Q_Z] );
84  inverse.normalize();
85 
86  return inverse;
87 }
88 
89 Quaternion Quaternion::log() const
90 {
91  double const qlen = length();
92  double const vlen = sqrt(v[Q_X]*v[Q_X] + v[Q_Y]*v[Q_Y] + v[Q_Z]*v[Q_Z]);
93  double const a = acos(v[Q_W]/qlen) / vlen;
94  return Quaternion(std::log(qlen), v[Q_X] * a, v[Q_Y] * a, v[Q_Z] * a);
95 }
96 
97 Quaternion Quaternion::exp() const
98 {
99  double const vlen = sqrt(v[Q_X]*v[Q_X] + v[Q_Y]*v[Q_Y] + v[Q_Z]*v[Q_Z]);
100  double const s = std::exp(v[Q_W]);
101  double const a = s * sin(vlen) / vlen;
102  return Quaternion(s * cos(vlen), v[Q_X] * a, v[Q_Y] * a, v[Q_Z] * a);
103 }
104 
105 Quaternion Quaternion::fromEuler(qreal pitch, qreal yaw, qreal roll)
106 {
107  const qreal cPhi = cos(0.5 * pitch); // also: "heading"
108  const qreal cThe = cos(0.5 * yaw); // also: "attitude"
109  const qreal cPsi = cos(0.5 * roll); // also: "bank"
110 
111  const qreal sPhi = sin(0.5 * pitch);
112  const qreal sThe = sin(0.5 * yaw);
113  const qreal sPsi = sin(0.5 * roll);
114 
115  const qreal w = cPhi * cThe * cPsi + sPhi * sThe * sPsi;
116  const qreal x = sPhi * cThe * cPsi - cPhi * sThe * sPsi;
117  const qreal y = cPhi * sThe * cPsi + sPhi * cThe * sPsi;
118  const qreal z = cPhi * cThe * sPsi - sPhi * sThe * cPsi;
119 
120  return Quaternion( w, x, y, z );
121 }
122 
123 qreal Quaternion::pitch() const // "heading", phi
124 {
125  return atan2( 2.0*(v[Q_X]*v[Q_W]-v[Q_Y]*v[Q_Z]),
126  ( 1.0 - 2.0*(v[Q_X]*v[Q_X]+v[Q_Z]*v[Q_Z]) ) );
127 }
128 
129 qreal Quaternion::yaw() const // "attitude", theta
130 {
131  return atan2( 2.0*(v[Q_Y]*v[Q_W]-v[Q_X]*v[Q_Z]),
132  ( 1.0 - 2.0*(v[Q_Y]*v[Q_Y]+v[Q_Z]*v[Q_Z]) ) );
133 }
134 
135 qreal Quaternion::roll() const // "bank", psi
136 {
137  return asin(2.0*(v[Q_X]*v[Q_Y]+v[Q_Z]*v[Q_W]));
138 }
139 
140 #ifndef QT_NO_DEBUG_STREAM
141 QDebug operator<<(QDebug debug, const Quaternion &q)
142 {
143  QString quatdisplay = QString("Quaternion: w= %1, x= %2, y= %3, z= %4, |q|= %5" )
144  .arg(q.v[Q_W]).arg(q.v[Q_X]).arg(q.v[Q_Y]).arg(q.v[Q_Z]).arg(q.length());
145 
146  debug << quatdisplay;
147 
148  return debug;
149 }
150 #endif
151 
152 Quaternion& Quaternion::operator*=(const Quaternion &q)
153 {
154  (*this) = (*this) * q;
155 
156  return *this;
157 }
158 
159 bool Quaternion::operator==(const Quaternion &q) const
160 {
161 
162  return ( v[Q_W] == q.v[Q_W]
163  && v[Q_X] == q.v[Q_X]
164  && v[Q_Y] == q.v[Q_Y]
165  && v[Q_Z] == q.v[Q_Z] );
166 }
167 
168 Quaternion Quaternion::operator*(const Quaternion &q) const
169 {
170  const qreal w = v[Q_W] * q.v[Q_W] - v[Q_X] * q.v[Q_X] - v[Q_Y] * q.v[Q_Y] - v[Q_Z] * q.v[Q_Z];
171  const qreal x = v[Q_W] * q.v[Q_X] + v[Q_X] * q.v[Q_W] + v[Q_Y] * q.v[Q_Z] - v[Q_Z] * q.v[Q_Y];
172  const qreal y = v[Q_W] * q.v[Q_Y] - v[Q_X] * q.v[Q_Z] + v[Q_Y] * q.v[Q_W] + v[Q_Z] * q.v[Q_X];
173  const qreal z = v[Q_W] * q.v[Q_Z] + v[Q_X] * q.v[Q_Y] - v[Q_Y] * q.v[Q_X] + v[Q_Z] * q.v[Q_W];
174 
175  return Quaternion( w, x, y, z );
176 }
177 
178 Quaternion Quaternion::operator+(const Quaternion &q) const
179 {
180  return Quaternion(v[Q_W] + q.v[Q_W],
181  v[Q_X] + q.v[Q_X],
182  v[Q_Y] + q.v[Q_Y],
183  v[Q_Z] + q.v[Q_Z]);
184 }
185 
186 Quaternion Quaternion::operator*(qreal factor) const
187 {
188  return Quaternion( v[Q_W] * factor, v[Q_X] * factor, v[Q_Y] * factor, v[Q_Z] * factor );
189 }
190 
191 void Quaternion::rotateAroundAxis(const Quaternion &q)
192 {
193  const qreal w = + v[Q_X] * q.v[Q_X] + v[Q_Y] * q.v[Q_Y] + v[Q_Z] * q.v[Q_Z];
194  const qreal x = + v[Q_X] * q.v[Q_W] - v[Q_Y] * q.v[Q_Z] + v[Q_Z] * q.v[Q_Y];
195  const qreal y = + v[Q_X] * q.v[Q_Z] + v[Q_Y] * q.v[Q_W] - v[Q_Z] * q.v[Q_X];
196  const qreal z = - v[Q_X] * q.v[Q_Y] + v[Q_Y] * q.v[Q_X] + v[Q_Z] * q.v[Q_W];
197 
198  (*this) = q * Quaternion( w, x, y, z );
199 }
200 
201 Quaternion Quaternion::slerp(const Quaternion &q1, const Quaternion &q2, qreal t)
202 {
203  qreal p1;
204  qreal p2;
205 
206  // Let alpha be the angle between the two quaternions.
207  qreal cosAlpha = ( q1.v[Q_X] * q2.v[Q_X]
208  + q1.v[Q_Y] * q2.v[Q_Y]
209  + q1.v[Q_Z] * q2.v[Q_Z]
210  + q1.v[Q_W] * q2.v[Q_W] );
211  qreal alpha = acos( cosAlpha );
212  qreal sinAlpha = sin( alpha );
213 
214  if ( sinAlpha > 0.0 ) {
215  p1 = sin( ( 1.0 - t ) * alpha ) / sinAlpha;
216  p2 = sin( t * alpha ) / sinAlpha;
217  } else {
218  // both Quaternions are equal
219  p1 = 1.0;
220  p2 = 0.0;
221  }
222 
223  const qreal w = p1 * q1.v[Q_W] + p2 * q2.v[Q_W];
224  const qreal x = p1 * q1.v[Q_X] + p2 * q2.v[Q_X];
225  const qreal y = p1 * q1.v[Q_Y] + p2 * q2.v[Q_Y];
226  const qreal z = p1 * q1.v[Q_Z] + p2 * q2.v[Q_Z];
227 
228  return Quaternion( w, x, y, z );
229 }
230 
231 Quaternion Quaternion::nlerp(const Quaternion &q1, const Quaternion &q2, qreal t)
232 {
233  const qreal p1 = 1.0 - t;
234 
235  const qreal w = p1 * q1.v[Q_W] + t * q2.v[Q_W];
236  const qreal x = p1 * q1.v[Q_X] + t * q2.v[Q_X];
237  const qreal y = p1 * q1.v[Q_Y] + t * q2.v[Q_Y];
238  const qreal z = p1 * q1.v[Q_Z] + t * q2.v[Q_Z];
239 
240  Quaternion result( w, x, y, z );
241  result.normalize();
242 
243  return result;
244 }
245 
246 void Quaternion::toMatrix(matrix &m) const
247 {
248 
249  const qreal xy = v[Q_X] * v[Q_Y], xz = v[Q_X] * v[Q_Z];
250  const qreal yy = v[Q_Y] * v[Q_Y], yw = v[Q_Y] * v[Q_W];
251  const qreal zw = v[Q_Z] * v[Q_W], zz = v[Q_Z] * v[Q_Z];
252 
253  m[0][0] = 1.0 - 2.0 * (yy + zz);
254  m[0][1] = 2.0 * (xy + zw);
255  m[0][2] = 2.0 * (xz - yw);
256  m[0][3] = 0.0;
257 
258  const qreal xx = v[Q_X] * v[Q_X];
259  const qreal xw = v[Q_X] * v[Q_W];
260  const qreal yz = v[Q_Y] * v[Q_Z];
261 
262  m[1][0] = 2.0 * (xy - zw);
263  m[1][1] = 1.0 - 2.0 * (xx + zz);
264  m[1][2] = 2.0 * (yz + xw);
265  m[1][3] = 0.0;
266 
267  m[2][0] = 2.0 * (xz + yw);
268  m[2][1] = 2.0 * (yz - xw);
269  m[2][2] = 1.0 - 2.0 * (xx + yy);
270  m[2][3] = 0.0;
271 }
272 
273 void Quaternion::rotateAroundAxis(const matrix &m)
274 {
275  const qreal x = m[0][0] * v[Q_X] + m[1][0] * v[Q_Y] + m[2][0] * v[Q_Z];
276  const qreal y = m[0][1] * v[Q_X] + m[1][1] * v[Q_Y] + m[2][1] * v[Q_Z];
277  const qreal z = m[0][2] * v[Q_X] + m[1][2] * v[Q_Y] + m[2][2] * v[Q_Z];
278 
279  v[Q_W] = 1.0;
280  v[Q_X] = x;
281  v[Q_Y] = y;
282  v[Q_Z] = z;
283 }
Quaternion.h
Marble::matrix
xmmfloat matrix[3]
Definition: Quaternion.h:38
operator<<
QDebug operator<<(QDebug debug, const Quaternion &q)
Definition: Quaternion.cpp:141
Marble::Q_W
Definition: Quaternion.h:33
Marble::operator==
bool operator==(const DownloadPolicyKey &lhs, const DownloadPolicyKey &rhs)
Definition: DownloadPolicy.h:49
operator+
Vec3 operator+(const Vec3 &c1, const Vec3 &c2)
Definition: attlib.cpp:116
normalize
void normalize(const QString &output)
Definition: tools/speaker-files/main.cpp:135
Marble::Q_Z
Definition: Quaternion.h:32
QString
Marble::Q_Y
Definition: Quaternion.h:31
Marble::Q_X
Definition: Quaternion.h:30
QDebug
Marble::Quaternion::length
qreal length() const
Definition: Quaternion.cpp:69
operator*
Vec3 operator*(double r, const Vec3 &c1)
Definition: attlib.cpp:133
Marble::Quaternion
Definition: Quaternion.h:41
Marble::Quaternion::v
xmmfloat v
Definition: Quaternion.h:87
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
Marble::Quaternion::normalize
void normalize()
Definition: Quaternion.cpp:64
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:41 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal