OpenMD 3.2
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
Quaternion.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48/**
49 * @file Quaternion.hpp
50 * @author Teng Lin
51 * @date 10/11/2004
52 * @version 1.0
53 */
54
55#ifndef MATH_QUATERNION_HPP
56#define MATH_QUATERNION_HPP
57
58#include <config.h>
59
60#include <cmath>
61
62#include "math/SquareMatrix.hpp"
63#include "math/Vector3.hpp"
64#include "utils/Constants.hpp"
65#define ISZERO(a, eps) ((a) > -(eps) && (a) < (eps))
66const RealType tiny = 1.0e-6;
67
68namespace OpenMD {
69
70 /**
71 * @class Quaternion Quaternion.hpp "math/Quaternion.hpp"
72 * Quaternion is a sort of a higher-level complex number.
73 * It is defined as \f$Q = w + x*i + y*j + z*k\f$,
74 * where w, x, y, and z are numbers of type T (e.g. RealType), and
75 * \f$i*i = -1\f$; \f$j*j = -1\f$; \f$k*k = -1\f$;
76 * \f$i*j = k\f$; \f$j*k = i\f$; \f$k*i = j\f$;
77 */
78 template<typename Real>
79 class Quaternion : public Vector<Real, 4> {
80 public:
81 Quaternion() : Vector<Real, 4>() {}
82
83 /** Constructs and initializes a Quaternion from w, x, y, z values */
84 Quaternion(Real w, Real x, Real y, Real z) {
85 this->data_[0] = w;
86 this->data_[1] = x;
87 this->data_[2] = y;
88 this->data_[3] = z;
89 }
90
91 /** Constructs and initializes a Quaternion from a Vector<Real,4> */
92 Quaternion(const Vector<Real, 4>& v) : Vector<Real, 4>(v) {}
93
94 /** copy assignment */
95 Quaternion& operator=(const Vector<Real, 4>& v) {
96 if (this == &v) return *this;
97
99
100 return *this;
101 }
102
103 /**
104 * Returns the value of the first element of this quaternion.
105 * @return the value of the first element of this quaternion
106 */
107 Real w() const { return this->data_[0]; }
108
109 /**
110 * Returns the reference of the first element of this quaternion.
111 * @return the reference of the first element of this quaternion
112 */
113 Real& w() { return this->data_[0]; }
114
115 /**
116 * Returns the value of the first element of this quaternion.
117 * @return the value of the first element of this quaternion
118 */
119 Real x() const { return this->data_[1]; }
120
121 /**
122 * Returns the reference of the second element of this quaternion.
123 * @return the reference of the second element of this quaternion
124 */
125 Real& x() { return this->data_[1]; }
126
127 /**
128 * Returns the value of the thirf element of this quaternion.
129 * @return the value of the third element of this quaternion
130 */
131 Real y() const { return this->data_[2]; }
132
133 /**
134 * Returns the reference of the third element of this quaternion.
135 * @return the reference of the third element of this quaternion
136 */
137 Real& y() { return this->data_[2]; }
138
139 /**
140 * Returns the value of the fourth element of this quaternion.
141 * @return the value of the fourth element of this quaternion
142 */
143 Real z() const { return this->data_[3]; }
144 /**
145 * Returns the reference of the fourth element of this quaternion.
146 * @return the reference of the fourth element of this quaternion
147 */
148 Real& z() { return this->data_[3]; }
149
150 /**
151 * Tests if this quaternion is equal to other quaternion
152 * @return true if equal, otherwise return false
153 * @param q quaternion to be compared
154 */
155 inline bool operator==(const Quaternion<Real>& q) {
156 for (unsigned int i = 0; i < 4; i++) {
157 if (!equal(this->data_[i], q[i])) { return false; }
158 }
159
160 return true;
161 }
162
163 /**
164 * Returns the inverse of this quaternion
165 * @return inverse
166 * @note since quaternion is a complex number, the inverse of quaternion
167 * q = w + xi + yj+ zk is inv_q = (w -xi - yj - zk)/(|q|^2)
168 */
169 Quaternion<Real> inverse() {
170 Quaternion<Real> q;
171 Real d = this->lengthSquare();
172
173 q.w() = w() / d;
174 q.x() = -x() / d;
175 q.y() = -y() / d;
176 q.z() = -z() / d;
177
178 return q;
179 }
180
181 /**
182 * Sets the value to the multiplication of itself and another quaternion
183 * @param q the other quaternion
184 */
185 void mul(const Quaternion<Real>& q) {
186 Quaternion<Real> tmp(*this);
187
188 this->data_[0] =
189 (tmp[0] * q[0]) - (tmp[1] * q[1]) - (tmp[2] * q[2]) - (tmp[3] * q[3]);
190 this->data_[1] =
191 (tmp[0] * q[1]) + (tmp[1] * q[0]) + (tmp[2] * q[3]) - (tmp[3] * q[2]);
192 this->data_[2] =
193 (tmp[0] * q[2]) + (tmp[2] * q[0]) + (tmp[3] * q[1]) - (tmp[1] * q[3]);
194 this->data_[3] =
195 (tmp[0] * q[3]) + (tmp[3] * q[0]) + (tmp[1] * q[2]) - (tmp[2] * q[1]);
196 }
197
198 void mul(const Real& s) {
199 this->data_[0] *= s;
200 this->data_[1] *= s;
201 this->data_[2] *= s;
202 this->data_[3] *= s;
203 }
204
205 /** Set the value of this quaternion to the division of itself by another
206 * quaternion */
207 void div(Quaternion<Real>& q) { mul(q.inverse()); }
208
209 void div(const Real& s) {
210 this->data_[0] /= s;
211 this->data_[1] /= s;
212 this->data_[2] /= s;
213 this->data_[3] /= s;
214 }
215
216 Quaternion<Real>& operator*=(const Quaternion<Real>& q) {
217 mul(q);
218 return *this;
219 }
220
221 Quaternion<Real>& operator*=(const Real& s) {
222 mul(s);
223 return *this;
224 }
225
226 Quaternion<Real>& operator/=(Quaternion<Real>& q) {
227 *this *= q.inverse();
228 return *this;
229 }
230
231 Quaternion<Real>& operator/=(const Real& s) {
232 div(s);
233 return *this;
234 }
235 /**
236 * Returns the conjugate quaternion of this quaternion
237 * @return the conjugate quaternion of this quaternion
238 */
239 Quaternion<Real> conjugate() const {
240 return Quaternion<Real>(w(), -x(), -y(), -z());
241 }
242
243 /**
244 return rotation angle from -PI to PI
245 */
246 inline Real get_rotation_angle() const {
247 if (w() < (Real)0.0)
248 return 2.0 * atan2(-sqrt(x() * x() + y() * y() + z() * z()), -w());
249 else
250 return 2.0 * atan2(sqrt(x() * x() + y() * y() + z() * z()), w());
251 }
252
253 /**
254 create a unit quaternion from axis angle representation
255 */
256 Quaternion<Real> fromAxisAngle(const Vector3<Real>& axis,
257 const Real& angle) {
258 Vector3<Real> v(axis);
259 v.normalize();
260 Real half_angle = angle * 0.5;
261 Real sin_a = sin(half_angle);
262 *this = Quaternion<Real>(cos(half_angle), v.x() * sin_a, v.y() * sin_a,
263 v.z() * sin_a);
264 return *this;
265 }
266
267 /**
268 convert a quaternion to axis angle representation,
269 preserve the axis direction and angle from -PI to +PI
270 */
271 void toAxisAngle(Vector3<Real>& axis, Real& angle) const {
272 Real vl = sqrt(x() * x() + y() * y() + z() * z());
273 if (vl > tiny) {
274 Real ivl = 1.0 / vl;
275 axis.x() = x() * ivl;
276 axis.y() = y() * ivl;
277 axis.z() = z() * ivl;
278
279 if (w() < 0)
280 angle = 2.0 * atan2(-vl, -w()); //-PI,0
281 else
282 angle = 2.0 * atan2(vl, w()); // 0,PI
283 } else {
284 axis = Vector3<Real>(0.0, 0.0, 0.0);
285 angle = 0.0;
286 }
287 }
288
289 /**
290 shortest arc quaternion rotate one vector to another by shortest path.
291 create rotation from -> to, for any length vectors.
292 */
293 Quaternion<Real> fromShortestArc(const Vector3d& from, const Vector3d& to) {
294 Vector3d c(cross(from, to));
295 *this = Quaternion<Real>(dot(from, to), c.x(), c.y(), c.z());
296
297 this->normalize(); // if "from" or "to" not unit, normalize quat
298 w() += 1.0f; // reducing angle to halfangle
299 if (w() <= 1e-6) { // angle close to PI
300 if ((from.z() * from.z()) > (from.x() * from.x())) {
301 this->data_[0] = w();
302 this->data_[1] = 0.0; // cross(from , Vector3d(1,0,0))
303 this->data_[2] = from.z();
304 this->data_[3] = -from.y();
305 } else {
306 this->data_[0] = w();
307 this->data_[1] = from.y(); // cross(from, Vector3d(0,0,1))
308 this->data_[2] = -from.x();
309 this->data_[3] = 0.0;
310 }
311 }
312 this->normalize();
313 }
314
315 Real ComputeTwist(const Quaternion& q) {
316 return (Real)2.0 * atan2(q.z(), q.w());
317 }
318
319 void RemoveTwist(Quaternion& q) {
320 Real t = ComputeTwist(q);
321 Quaternion rt = fromAxisAngle(V3Z, t);
322
323 q *= rt.inverse();
324 }
325
326 void getTwistSwingAxisAngle(Real& twistAngle, Real& swingAngle,
327 Vector3<Real>& swingAxis) {
328 twistAngle = (Real)2.0 * atan2(z(), w());
329 Quaternion rt, rs;
330 rt.fromAxisAngle(V3Z, twistAngle);
331 rs = *this * rt.inverse();
332
333 Real vl = sqrt(rs.x() * rs.x() + rs.y() * rs.y() + rs.z() * rs.z());
334 if (vl > tiny) {
335 Real ivl = 1.0 / vl;
336 swingAxis.x() = rs.x() * ivl;
337 swingAxis.y() = rs.y() * ivl;
338 swingAxis.z() = rs.z() * ivl;
339
340 if (rs.w() < 0.0)
341 swingAngle = 2.0 * atan2(-vl, -rs.w()); //-PI,0
342 else
343 swingAngle = 2.0 * atan2(vl, rs.w()); // 0,PI
344 } else {
345 swingAxis = Vector3<Real>(1.0, 0.0, 0.0);
346 swingAngle = 0.0;
347 }
348 }
349
350 Vector3<Real> rotate(const Vector3<Real>& v) {
351 Quaternion<Real> q(v.x() * w() + v.z() * y() - v.y() * z(),
352 v.y() * w() + v.x() * z() - v.z() * x(),
353 v.z() * w() + v.y() * x() - v.x() * y(),
354 v.x() * x() + v.y() * y() + v.z() * z());
355
356 return Vector3<Real>(
357 w() * q.x() + x() * q.w() + y() * q.z() - z() * q.y(),
358 w() * q.y() + y() * q.w() + z() * q.x() - x() * q.z(),
359 w() * q.z() + z() * q.w() + x() * q.y() - y() * q.x()) *
360 (1.0 / this->lengthSquare());
361 }
362
363 Quaternion<Real>& align(const Vector3<Real>& V1, const Vector3<Real>& V2) {
364 // If V1 and V2 are not parallel, the axis of rotation is the unit-length
365 // vector U = Cross(V1,V2)/Length(Cross(V1,V2)). The angle of rotation,
366 // A, is the angle between V1 and V2. The quaternion for the rotation is
367 // q = cos(A/2) + sin(A/2)*(ux*i+uy*j+uz*k) where U = (ux,uy,uz).
368 //
369 // (1) Rather than extract A = acos(Dot(V1,V2)), multiply by 1/2, then
370 // compute sin(A/2) and cos(A/2), we reduce the computational costs
371 // by computing the bisector B = (V1+V2)/Length(V1+V2), so cos(A/2) =
372 // Dot(V1,B).
373 //
374 // (2) The rotation axis is U = Cross(V1,B)/Length(Cross(V1,B)), but
375 // Length(Cross(V1,B)) = Length(V1)*Length(B)*sin(A/2) = sin(A/2), in
376 // which case sin(A/2)*(ux*i+uy*j+uz*k) = (cx*i+cy*j+cz*k) where
377 // C = Cross(V1,B).
378 //
379 // If V1 = V2, then B = V1, cos(A/2) = 1, and U = (0,0,0). If V1 = -V2,
380 // then B = 0. This can happen even if V1 is approximately -V2 using
381 // floating point arithmetic, since Vector3::Normalize checks for
382 // closeness to zero and returns the zero vector accordingly. The test
383 // for exactly zero is usually not recommend for floating point
384 // arithmetic, but the implementation of Vector3::Normalize guarantees
385 // the comparison is robust. In this case, the A = pi and any axis
386 // perpendicular to V1 may be used as the rotation axis.
387
388 Vector3<Real> Bisector = V1 + V2;
389 Bisector.normalize();
390
391 Real CosHalfAngle = dot(V1, Bisector);
392
393 this->data_[0] = CosHalfAngle;
394
395 if (CosHalfAngle != (Real)0.0) {
396 Vector3<Real> Cross = cross(V1, Bisector);
397 this->data_[1] = Cross.x();
398 this->data_[2] = Cross.y();
399 this->data_[3] = Cross.z();
400 } else {
401 Real InvLength;
402 if (fabs(V1[0]) >= fabs(V1[1])) {
403 // V1.x or V1.z is the largest magnitude component
404 InvLength = (Real)1.0 / sqrt(V1[0] * V1[0] + V1[2] * V1[2]);
405
406 this->data_[1] = -V1[2] * InvLength;
407 this->data_[2] = (Real)0.0;
408 this->data_[3] = +V1[0] * InvLength;
409 } else {
410 // V1.y or V1.z is the largest magnitude component
411 InvLength = (Real)1.0 / sqrt(V1[1] * V1[1] + V1[2] * V1[2]);
412
413 this->data_[1] = (Real)0.0;
414 this->data_[2] = +V1[2] * InvLength;
415 this->data_[3] = -V1[1] * InvLength;
416 }
417 }
418 return *this;
419 }
420
421 void toTwistSwing(Real& tw, Real& sx, Real& sy) {
422 // First test if the swing is in the singularity:
423
424 if (ISZERO(z(), tiny) && ISZERO(w(), tiny)) {
425 sx = sy = Constants::PI;
426 tw = 0;
427 return;
428 }
429
430 // Decompose into twist-swing by solving the equation:
431 //
432 // Qtwist(t*2) * Qswing(s*2) = q
433 //
434 // note: (x,y) is the normalized swing axis (x*x+y*y=1)
435 //
436 // ( Ct 0 0 St ) * ( Cs xSs ySs 0 ) = ( qw qx qy qz )
437 // ( CtCs xSsCt-yStSs xStSs+ySsCt StCs ) = ( qw qx qy qz ) (1)
438 // From (1): CtCs / StCs = qw/qz => Ct/St = qw/qz => tan(t) = qz/qw (2)
439 //
440 // The swing rotation/2 s comes from:
441 //
442 // From (1): (CtCs)^2 + (StCs)^2 = qw^2 + qz^2 =>
443 // Cs = sqrt ( qw^2 + qz^2 ) (3)
444 //
445 // From (1): (xSsCt-yStSs)^2 + (xStSs+ySsCt)^2 = qx^2 + qy^2 =>
446 // Ss = sqrt ( qx^2 + qy^2 ) (4)
447 // From (1): |SsCt -StSs| |x| = |qx|
448 // |StSs +SsCt| |y| |qy| (5)
449
450 Real qw, qx, qy, qz;
451
452 if (w() < 0) {
453 qw = -w();
454 qx = -x();
455 qy = -y();
456 qz = -z();
457 } else {
458 qw = w();
459 qx = x();
460 qy = y();
461 qz = z();
462 }
463
464 Real t = atan2(qz, qw); // from (2)
465 Real s =
466 atan2(sqrt(qx * qx + qy * qy), sqrt(qz * qz + qw * qw)); // from (3)
467 // and (4)
468
469 Real x = 0.0, y = 0.0, sins = sin(s);
470
471 if (!ISZERO(sins, tiny)) {
472 Real sint = sin(t);
473 Real cost = cos(t);
474
475 // by solving the linear system in (5):
476 y = (-qx * sint + qy * cost) / sins;
477 x = (qx * cost + qy * sint) / sins;
478 }
479
480 tw = (Real)2.0 * t;
481 sx = (Real)2.0 * x * s;
482 sy = (Real)2.0 * y * s;
483 }
484
485 void toSwingTwist(Real& sx, Real& sy, Real& tw) {
486 // Decompose q into swing-twist using a similar development as
487 // in function toTwistSwing
488
489 if (ISZERO(z(), tiny) && ISZERO(w(), tiny)) {
490 sx = sy = Constants::PI;
491 tw = 0;
492 }
493
494 Real qw, qx, qy, qz;
495 if (w() < 0) {
496 qw = -w();
497 qx = -x();
498 qy = -y();
499 qz = -z();
500 } else {
501 qw = w();
502 qx = x();
503 qy = y();
504 qz = z();
505 }
506
507 // Get the twist t:
508 Real t = 2.0 * atan2(qz, qw);
509
510 Real bet = atan2(sqrt(qx * qx + qy * qy), sqrt(qz * qz + qw * qw));
511 Real gam = t / 2.0;
512 Real sinc = ISZERO(bet, tiny) ? 1.0 : sin(bet) / bet;
513 Real singam = sin(gam);
514 Real cosgam = cos(gam);
515
516 sx = Real((2.0 / sinc) * (cosgam * qx - singam * qy));
517 sy = Real((2.0 / sinc) * (singam * qx + cosgam * qy));
518 tw = Real(t);
519 }
520
521 /**
522 * Returns the corresponding rotation matrix (3x3)
523 * @return a 3x3 rotation matrix
524 */
526 SquareMatrix<Real, 3> rotMat3;
527
528 Real w2;
529 Real x2;
530 Real y2;
531 Real z2;
532
533 if (!this->isNormalized()) this->normalize();
534
535 w2 = w() * w();
536 x2 = x() * x();
537 y2 = y() * y();
538 z2 = z() * z();
539
540 rotMat3(0, 0) = w2 + x2 - y2 - z2;
541 rotMat3(0, 1) = 2.0 * (x() * y() + w() * z());
542 rotMat3(0, 2) = 2.0 * (x() * z() - w() * y());
543
544 rotMat3(1, 0) = 2.0 * (x() * y() - w() * z());
545 rotMat3(1, 1) = w2 - x2 + y2 - z2;
546 rotMat3(1, 2) = 2.0 * (y() * z() + w() * x());
547
548 rotMat3(2, 0) = 2.0 * (x() * z() + w() * y());
549 rotMat3(2, 1) = 2.0 * (y() * z() - w() * x());
550 rotMat3(2, 2) = w2 - x2 - y2 + z2;
551
552 return rotMat3;
553 }
554
555 }; // end Quaternion
556
557 /**
558 * Returns the vaule of scalar multiplication of this quaterion q (q * s).
559 * @return the vaule of scalar multiplication of this vector
560 * @param q the source quaternion
561 * @param s the scalar value
562 */
563 template<typename Real, unsigned int Dim>
565 Quaternion<Real> result(q);
566 result.mul(s);
567 return result;
568 }
569
570 /**
571 * Returns the vaule of scalar multiplication of this quaterion q (q * s).
572 * @return the vaule of scalar multiplication of this vector
573 * @param s the scalar value
574 * @param q the source quaternion
575 */
576 template<typename Real, unsigned int Dim>
577 Quaternion<Real> operator*(const Real& s, const Quaternion<Real>& q) {
578 Quaternion<Real> result(q);
579 result.mul(s);
580 return result;
581 }
582
583 /**
584 * Returns the multiplication of two quaternion
585 * @return the multiplication of two quaternion
586 * @param q1 the first quaternion
587 * @param q2 the second quaternion
588 */
589 template<typename Real>
591 const Quaternion<Real>& q2) {
592 Quaternion<Real> result(q1);
593 result *= q2;
594 return result;
595 }
596
597 /**
598 * Returns the division of two quaternion
599 * @param q1 divisor
600 * @param q2 dividen
601 */
602
603 template<typename Real>
605 Quaternion<Real>& q2) {
606 return q1 * q2.inverse();
607 }
608
609 /**
610 * Returns the value of the division of a scalar by a quaternion
611 * @return the value of the division of a scalar by a quaternion
612 * @param s scalar
613 * @param q quaternion
614 * @note for a quaternion q, 1/q = q.inverse()
615 */
616 template<typename Real>
619 x = q.inverse();
620 x *= s;
621 return x;
622 }
623
624 template<class T>
625 inline bool operator==(const Quaternion<T>& lhs, const Quaternion<T>& rhs) {
626 return equal(lhs[0], rhs[0]) && equal(lhs[1], rhs[1]) &&
627 equal(lhs[2], rhs[2]) && equal(lhs[3], rhs[3]);
628 }
629
630 using Quat4d = Quaternion<RealType>;
631} // namespace OpenMD
632
633#endif // MATH_QUATERNION_HPP
Quaternion is a sort of a higher-level complex number.
Quaternion(const Vector< Real, 4 > &v)
Constructs and initializes a Quaternion from a Vector<Real,4>.
SquareMatrix< Real, 3 > toRotationMatrix3()
Returns the corresponding rotation matrix (3x3).
Real & z()
Returns the reference of the fourth element of this quaternion.
Quaternion< Real > fromAxisAngle(const Vector3< Real > &axis, const Real &angle)
create a unit quaternion from axis angle representation
void div(Quaternion< Real > &q)
Set the value of this quaternion to the division of itself by another quaternion.
Quaternion< Real > conjugate() const
Returns the conjugate quaternion of this quaternion.
Quaternion(Real w, Real x, Real y, Real z)
Constructs and initializes a Quaternion from w, x, y, z values.
bool operator==(const Quaternion< Real > &q)
Tests if this quaternion is equal to other quaternion.
void toAxisAngle(Vector3< Real > &axis, Real &angle) const
convert a quaternion to axis angle representation, preserve the axis direction and angle from -PI to ...
Real & y()
Returns the reference of the third element of this quaternion.
Real & w()
Returns the reference of the first element of this quaternion.
Quaternion< Real > fromShortestArc(const Vector3d &from, const Vector3d &to)
shortest arc quaternion rotate one vector to another by shortest path.
Quaternion & operator=(const Vector< Real, 4 > &v)
copy assignment
Real & x()
Returns the reference of the second element of this quaternion.
Quaternion< Real > inverse()
Returns the inverse of this quaternion.
Real get_rotation_angle() const
return rotation angle from -PI to PI
void mul(const Quaternion< Real > &q)
Sets the value to the multiplication of itself and another quaternion.
A square matrix class.
Real & z()
Returns reference of the third element of Vector3.
Definition Vector3.hpp:123
Real & x()
Returns reference of the first element of Vector3.
Definition Vector3.hpp:99
Real & y()
Returns reference of the second element of Vector3.
Definition Vector3.hpp:111
Vector< Real, Dim > & operator=(const Vector< Real, Dim > &v)
copy assignment operator
Definition Vector.hpp:96
void normalize()
Normalizes this vector in place.
Definition Vector.hpp:406
Real lengthSquare() const
Definition Vector.hpp:403
bool isNormalized() const
Definition Vector.hpp:418
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.
bool equal(const Polynomial< Real > &p1, const Polynomial< Real > &p2)
Tests if two polynomial have the same exponents.
Vector3< Real > cross(const Vector3< Real > &v1, const Vector3< Real > &v2)
Returns the cross product of two Vectors.
Definition Vector3.hpp:139
Real dot(const DynamicVector< Real > &v1, const DynamicVector< Real > &v2)
Returns the dot product of two DynamicVectors.
DynamicRectMatrix< Real > operator*(const DynamicRectMatrix< Real > &m, Real s)
Return the multiplication of scalar and matrix (m * s).
DynamicRectMatrix< Real > operator/(const DynamicRectMatrix< Real > &m, Real s)
Return the scalar division of matrix (m / s).