EMAN2
quaternion.cpp
Go to the documentation of this file.
1/*
2 * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.edu)
3 * Copyright (c) 2000-2006 Baylor College of Medicine
4 *
5 * This software is issued under a joint BSD/GNU license. You may use the
6 * source code in this file under either license. However, note that the
7 * complete EMAN2 and SPARX software packages have some GPL dependencies,
8 * so you are responsible for compliance with the licenses of these packages
9 * if you opt to use BSD licensing. The warranty disclaimer below holds
10 * in either instance.
11 *
12 * This complete copyright notice must be included in any revised version of the
13 * source code. Additional authorship citations may be added, but existing
14 * author citations must be preserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * */
31
32#include "quaternion.h"
33
34using namespace EMAN;
35
36Quaternion::Quaternion()
37: e0(0), e1(0), e2(0), e3(0)
38{
39}
40
41Quaternion::Quaternion(float radians, const Vec3f &axis)
42{
43 Vec3f q = axis;
44 //normalize();
45
46 q *= sin(radians / 2.0f);
47 e0 = cos(radians / 2.0f);
48
49 e1 = q[0];
50 e2 = q[1];
51 e3 = q[2];
52}
53
54Quaternion::Quaternion(const Vec3f &axis, float radians)
55{
56 Vec3f q = axis;
57 //normalize();
58
59 q *= sin(radians / 2.0f);
60 e0 = cos(radians / 2.0f);
61
62 e1 = q[0];
63 e2 = q[1];
64 e3 = q[2];
65}
66
67Quaternion::Quaternion(float ee0, float ee1, float ee2, float ee3)
68:e0(ee0), e1(ee1), e2(ee2), e3(ee3)
69{
70 //normalize();
71}
72
73Quaternion::Quaternion(const vector<float> & m)
74{
75 int i = 0;
76
77 if (m[0] > m[4]) {
78 if (m[0] > m[8]) {
79 i = 0;
80 }
81 else {
82 i = 2;
83 }
84 }
85 else {
86 if (m[4] > m[8]) {
87 i = 1;
88 }
89 else {
90 i = 2;
91 }
92 }
93
94 if (m[0] + m[4] + m[8] > m[i*3+i]) {
95 e0 = (float) (sqrt(m[0] + m[4] + m[8] + 1) / 2.0);
96 e1 = (float) ((m[5] - m[7]) / (4 * e0));
97 e2 = (float) ((m[6] - m[2]) / (4 * e0));
98 e3 = (float) ((m[1] - m[3]) / (4 * e0));
99 }
100 else {
101 float quat[3];
102 int j = (i + 1) % 3;
103 int k = (i + 2) % 3;
104
105 quat[i] = (float) (sqrt(m[i*3+i] - m[j*3+j] - m[k*3+k] + 1) / 2.0);
106 quat[j] = (float) ((m[i*3+j] + m[j*3+i]) / (4 * quat[i]));
107 quat[k] = (float) ((m[i*3+k] + m[k*3+i]) / (4 * quat[i]));
108
109 e0 = (float) ((m[j*3+k] - m[k*3+j]) / (4 * quat[i]));
110 e1 = quat[0];
111 e2 = quat[1];
112 e3 = quat[2];
113 }
114
115 //normalize();
116}
117
118
120{
121 float dist = 1.0f / sqrt(norm());
122 e0 *= dist;
123 e1 *= dist;
124 e2 *= dist;
125 e3 *= dist;
126}
127
129{
130 float f = 1.0f / norm();
131 e0 *= f;
132 e1 *= -f;
133 e2 *= -f;
134 e3 *= -f;
135 return (*this);
136}
137
139{
140 Quaternion q = *this;
141 return q.inverse();
142}
143
144
146{
147 Vec3f i(e1, e2, e3);
148 Vec3f v1 = i.cross(v) * (2 * e0);
149 Vec3f v2 = v1.cross(i) * (float) 2;
150 Vec3f rotated = v + v1 - v2;
151
152 return rotated;
153}
154
155
157{
158 Vec3f q(e1, e2, e3);
159 float len = q.length();
160 float radians = 0;
161
162 if (len > 0.00001f) {
163 radians = 2.0f * acos(e0);
164 }
165 else {
166 radians = 0;
167 }
168 return radians;
169}
170
172{
173 Vec3f q(e1, e2, e3);
174 float len = q.length();
175 Vec3f axis;
176
177 if (len > 0.00001f) {
178 axis = q * ((float) (1.0f / len));
179 }
180 else {
181 axis.set_value(0.0f, 0.0f, 1.0f);
182 }
183 return axis;
184}
185
186
187vector<float> Quaternion::to_matrix3() const
188{
189 vector < float >m(9);
190
191 m[0] = e0 * e0 + e1 * e1 - e2 * e2 - e3 * e3;
192 m[1] = 2.0f * (e1 * e2 + e0 * e3);
193 m[2] = 2.0f * (e1 * e3 - e0 * e2);
194
195 m[3] = 2.0f * (e1 * e2 - e0 * e3);
196 m[4] = e0 * e0 + e1 * e1 + e2 * e2 - e3 * e3;
197 m[5] = 2.0f * (e2 * e3 + e0 * e1);
198
199 m[6] = 2.0f * (e1 * e3 + e0 * e2);
200 m[7] = 2.0f * (e2 * e3 - e0 * e1);
201 m[8] = e0 * e0 - e1 * e1 - e2 * e2 + e3 * e3;
202
203 return m;
204}
205
206
207
208float Quaternion::real() const
209{
210 return e0;
211}
212
214{
215 return Vec3f(e1, e2, e3);
216}
217
218vector < float >Quaternion::as_list() const
219{
220 vector < float >v(4);
221 v[0] = e0;
222 v[1] = e1;
223 v[2] = e2;
224 v[3] = e3;
225
226 return v;
227}
228
230{
231 e0 += q.e0;
232 e1 += q.e1;
233 e2 += q.e2;
234 e3 += q.e3;
235 return *this;
236}
237
239{
240 e0 -= q.e0;
241 e1 -= q.e1;
242 e2 -= q.e2;
243 e3 -= q.e3;
244 return *this;
245}
246
248{
249 float a = e0 * q.e0 - e1 * q.e1 - e2 * q.e2 - e3 * q.e3;
250 float b = e0 * q.e1 + e1 * q.e0 + e2 * q.e3 - e3 * q.e2;
251 float c = e0 * q.e2 - e1 * q.e3 + e2 * q.e0 + e3 * q.e1;
252 float d = e0 * q.e3 + e1 * q.e2 - e2 * q.e1 + e3 * q.e0;
253
254 e0 = a;
255 e1 = b;
256 e2 = c;
257 e3 = d;
258
259
260 // normalize();
261
262 return (*this);
263}
264
266{
267 e0 *= s;
268 e1 *= s;
269 e2 *= s;
270 e3 *= s;
271 return (*this);
272}
273
275{
276 float qn = q.norm();
277
278 float a = (+e0 * q.e0 + e1 * q.e1 + e2 * q.e2 + e3 * q.e3) / qn;
279 float b = (-e0 * q.e1 + e1 * q.e0 - e2 * q.e3 + e3 * q.e2) / qn;
280 float c = (-e0 * q.e2 + e1 * q.e3 + e2 * q.e0 - e3 * q.e1) / qn;
281 float d = (-e0 * q.e3 - e1 * q.e2 + e2 * q.e1 + e3 * q.e0) / qn;
282
283 e0 = a;
284 e1 = b;
285 e2 = c;
286 e3 = d;
287
288 return (*this);
289}
290
292{
293 if (s != 0) {
294 e0 /= s;
295 e1 /= s;
296 e2 /= s;
297 e3 /= s;
298 }
299
300 return (*this);
301}
302
303
305{
306 Quaternion q = q1;
307 q += q2;
308 return q;
309}
310
312{
313 Quaternion q = q1;
314 q -= q2;
315 return q;
316}
317
318
320{
321 Quaternion q = q1;
322 q *= q2;
323 return q;
324}
325
327{
328 Quaternion q1 = q;
329 q1 *= s;
330 return q1;
331}
332
334{
335 Quaternion q1 = q;
336 q1 *= s;
337 return q1;
338}
339
341{
342 Quaternion q = q1;
343 q /= q2;
344 return q;
345}
346
347
348bool EMAN::operator==(const Quaternion & q1, const Quaternion & q2)
349{
350 bool result = true;
351 const float err_limit = 0.00001f;
352
353 vector < float >v1 = q1.as_list();
354 vector < float >v2 = q2.as_list();
355
356 for (size_t i = 0; i < v1.size(); i++) {
357 if (fabs(v1[i] - v2[i]) > err_limit) {
358 result = false;
359 break;
360 }
361 }
362
363 return result;
364}
365
366bool EMAN::operator!=(const Quaternion & q1, const Quaternion & q2)
367{
368 return (!(q1 == q2));
369}
370
371
373 const Quaternion & to, float t)
374{
375 const double epsilon = 0.00001;
376 double cosom = from.e1 * to.e1 + from.e2 * to.e2 + from.e3 * to.e3 + from.e0 * to.e0;
377
378 Quaternion q;
379 if (cosom < 0) {
380 cosom = -cosom;
381 q = q - to;
382 }
383 else {
384 q = to;
385 }
386
387 double scale0 = 1 - t;
388 double scale1 = t;
389
390 if ((1 - cosom) > epsilon) {
391 double omega = acos(cosom);
392 double sinom = sin(omega);
393 scale0 = sin((1 - t) * omega) / sinom;
394 scale1 = sin(t * omega) / sinom;
395 }
396
397 float scale0f = (float) scale0;
398 float scale1f = (float) scale1;
399
400 return (scale0f * from + scale1f * q);
401}
Quaternion is used in Rotation and Transformation to replace Euler angles.
Definition: quaternion.h:62
vector< float > to_matrix3() const
Definition: quaternion.cpp:187
static Quaternion interpolate(const Quaternion &from, const Quaternion &to, float percent)
Definition: quaternion.cpp:372
Vec3f unreal() const
Definition: quaternion.cpp:213
Vec3f rotate(const Vec3f &v) const
Definition: quaternion.cpp:145
float norm() const
Definition: quaternion.h:74
Quaternion & operator*=(const Quaternion &q)
Definition: quaternion.cpp:247
Quaternion & inverse()
Definition: quaternion.cpp:128
vector< float > as_list() const
Definition: quaternion.cpp:218
Quaternion create_inverse() const
Definition: quaternion.cpp:138
Quaternion & operator/=(const Quaternion &q)
Definition: quaternion.cpp:274
Quaternion & operator+=(const Quaternion &q)
Definition: quaternion.cpp:229
Vec3f to_axis() const
Definition: quaternion.cpp:171
float to_angle() const
Definition: quaternion.cpp:156
Quaternion & operator-=(const Quaternion &q)
Definition: quaternion.cpp:238
float real() const
Definition: quaternion.cpp:208
Vec3< Type > cross(const Vec3< Type2 > &v) const
Calculate the cross product of 'this' vector with a second vector.
Definition: vec3.h:384
void set_value(const vector< Type2 > &v)
Set new values using a std::vector object.
Definition: vec3.h:408
float length() const
Calculate its length.
Definition: vec3.h:352
EMData * sqrt() const
return square root of current image
E2Exception class.
Definition: aligner.h:40
EMData * operator+(const EMData &em, float n)
Definition: emdata.cpp:3187
Vec3< float > Vec3f
Definition: vec3.h:693
bool operator!=(const EMObject &e1, const EMObject &e2)
Definition: emobject.cpp:873
EMData * operator-(const EMData &em, float n)
Definition: emdata.cpp:3194
EMData * operator/(const EMData &em, float n)
Definition: emdata.cpp:3208
EMData * operator*(const EMData &em, float n)
Definition: emdata.cpp:3201
bool operator==(const EMObject &e1, const EMObject &e2)
Definition: emobject.cpp:770