xc
ASDMath.h
1 // -*-c++-*-
2 //----------------------------------------------------------------------------
3 // XC program; finite element analysis code
4 // for structural analysis and design.
5 //
6 // Copyright (C) Luis C. Pérez Tato
7 //
8 // This program derives from OpenSees <http://opensees.berkeley.edu>
9 // developed by the «Pacific earthquake engineering research center».
10 //
11 // Except for the restrictions that may arise from the copyright
12 // of the original program (see copyright_opensees.txt)
13 // XC is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // This software is distributed in the hope that it will be useful, but
19 // WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 //
24 // You should have received a copy of the GNU General Public License
25 // along with this program.
26 // If not, see <http://www.gnu.org/licenses/>.
27 //----------------------------------------------------------------------------
28 /* ****************************************************************** **
29 ** OpenSees - Open System for Earthquake Engineering Simulation **
30 ** Pacific Earthquake Engineering Research Center **
31 ** **
32 ** **
33 ** (C) Copyright 1999, The Regents of the University of California **
34 ** All Rights Reserved. **
35 ** **
36 ** Commercial use of this program without express permission of the **
37 ** University of California, Berkeley, is strictly prohibited. See **
38 ** file 'COPYRIGHT' in main directory for information on usage and **
39 ** redistribution, and for a DISCLAIMER OF ALL WARRANTIES. **
40 ** **
41 ** Developed by: **
42 ** Frank McKenna (fmckenna@ce.berkeley.edu) **
43 ** Gregory L. Fenves (fenves@ce.berkeley.edu) **
44 ** Filip C. Filippou (filippou@ce.berkeley.edu) **
45 ** **
46 ** ****************************************************************** */
47 
48 // $Revision: 1.10 $
49 // $Date: 2020/05/18 22:51:21 $
50 
51 // Original implementation: Massimo Petracca (ASDEA)
52 //
53 // Implementation of a Quaternion for compact and robust representation
54 // of spatial rotations
55 //
56 
57 #ifndef ASDMath_h
58 #define ASDMath_h
59 
60 #include <stdint.h>
61 #include <math.h>
62 #include <cmath>
63 #include <limits>
64 #include "utility/matrix/Vector.h"
65 #include "utility/matrix/Matrix.h"
66 
67 namespace XC {
68 
71 template<class T>
73  {
74  private:
75  T mData[3];
76  public:
77 
82  {
83  mData[0] = mData[1] = mData[2] = 0.0;
84  }
85 
92  ASDVector3(T x, T y, T z)
93  {
94  mData[0] = x;
95  mData[1] = y;
96  mData[2] = z;
97  }
98 
105  ASDVector3(const Vector& v, size_t index = 0)
106  {
107  mData[0] = v(0 + index);
108  mData[1] = v(1 + index);
109  mData[2] = v(2 + index);
110  }
111 
116  ASDVector3(const ASDVector3& other)
117  {
118  mData[0] = other.mData[0];
119  mData[1] = other.mData[1];
120  mData[2] = other.mData[2];
121  }
122 
123 public:
124 
130  {
131  if (this != &other) {
132  mData[0] = other.mData[0];
133  mData[1] = other.mData[1];
134  mData[2] = other.mData[2];
135  }
136  return *this;
137  }
138 
139 public:
140 
145  inline const T x()const { return mData[0]; }
146 
151  inline const T y()const { return mData[1]; }
152 
157  inline const T z()const { return mData[2]; }
158 
163  inline T operator()(size_t i) const { return mData[i]; }
164 
169  inline T& operator()(size_t i) { return mData[i]; }
170 
175  inline T operator[](size_t i) const { return mData[i]; }
176 
181  inline T& operator[](size_t i) { return mData[i]; }
182 
183 public:
184 
189  inline T squaredNorm() const
190  {
191  return
192  mData[0] * mData[0] +
193  mData[1] * mData[1] +
194  mData[2] * mData[2];
195  }
196 
201  inline T norm() const
202  {
203  return std::sqrt(squaredNorm());
204  }
205 
210  inline T normalize()
211  {
212  T n = norm();
213  if (n > 0.0) {
214  mData[0] /= n;
215  mData[1] /= n;
216  mData[2] /= n;
217  }
218  return n;
219  }
220 
226  inline T dot(const ASDVector3& b) const
227  {
228  return
229  mData[0] * b.mData[0] +
230  mData[1] * b.mData[1] +
231  mData[2] * b.mData[2];
232  }
233 
239  inline ASDVector3 cross(const ASDVector3& b) const
240  {
241  ASDVector3 c;
242  c.mData[0] = mData[1] * b.mData[2] - mData[2] * b.mData[1];
243  c.mData[1] = mData[2] * b.mData[0] - mData[0] * b.mData[2];
244  c.mData[2] = mData[0] * b.mData[1] - mData[1] * b.mData[0];
245  return c;
246  }
247 
248 public:
249 
250  inline void operator += (const ASDVector3& b)
251  {
252  mData[0] += b.mData[0];
253  mData[1] += b.mData[1];
254  mData[2] += b.mData[2];
255  }
256 
257  inline ASDVector3 operator + (const ASDVector3& b) const
258  {
259  ASDVector3 a(*this);
260  a += b;
261  return a;
262  }
263 
264  inline void operator -= (const ASDVector3& b)
265  {
266  mData[0] -= b.mData[0];
267  mData[1] -= b.mData[1];
268  mData[2] -= b.mData[2];
269  }
270 
271  inline ASDVector3 operator - (const ASDVector3& b) const
272  {
273  ASDVector3 a(*this);
274  a -= b;
275  return a;
276  }
277 
278  inline void operator *= (T b)
279  {
280  mData[0] *= b;
281  mData[1] *= b;
282  mData[2] *= b;
283  }
284 
285  inline ASDVector3 operator * (T b) const
286  {
287  ASDVector3 a(*this);
288  a *= b;
289  return a;
290  }
291 
292  inline void operator /= (T b)
293  {
294  mData[0] /= b;
295  mData[1] /= b;
296  mData[2] /= b;
297  }
298 
299  inline ASDVector3 operator / (T b) const
300  {
301  ASDVector3 a(*this);
302  a /= b;
303  return a;
304  }
305 
306  };
307 
308 template<class T>
309 inline ASDVector3<T> operator * (T a, const ASDVector3<T>& b)
310  { return b * a; }
311 
318 template<class TStream, class T>
319 inline TStream& operator << (TStream& s, const ASDVector3<T>& v)
320 {
321  return (s << "(" << v.x() << ", " << v.y() << ", " << v.z() << ")");
322 }
323 
327 template<class T>
329 {
330 
331 public:
332 
337  : mX(0.0)
338  , mY(0.0)
339  , mZ(0.0)
340  , mW(0.0)
341  {
342  }
343 
351  ASDQuaternion(T w, T x, T y, T z)
352  : mX(x)
353  , mY(y)
354  , mZ(z)
355  , mW(w)
356  {
357  }
358 
364  : mX(other.mX)
365  , mY(other.mY)
366  , mZ(other.mZ)
367  , mW(other.mW)
368  {
369  }
370 
371 public:
372 
378  {
379  if (this != &other) {
380  mX = other.mX;
381  mY = other.mY;
382  mZ = other.mZ;
383  mW = other.mW;
384  }
385  return *this;
386  }
387 
388 public:
389 
394  inline const T x()const { return mX; }
395 
400  inline const T y()const { return mY; }
401 
406  inline const T z()const { return mZ; }
407 
412  inline const T w()const { return mW; }
413 
414 public:
415 
421  inline const T squaredNorm()const
422  {
423  return mX * mX + mY * mY + mZ * mZ + mW * mW;
424  }
425 
431  inline const T norm()const
432  {
433  return std::sqrt(squaredNorm());
434  }
435 
440  inline void normalize()
441  {
442  T n = squaredNorm();
443  if (n > 0.0 && n != 1.0) {
444  n = std::sqrt(n);
445  mX /= n;
446  mY /= n;
447  mZ /= n;
448  mW /= n;
449  }
450  }
451 
456  inline ASDQuaternion conjugate()const
457  {
458  return ASDQuaternion(mW, -mX, -mY, -mZ);
459  }
460 
473  template<class TMatrix3x3>
474  inline void toRotationMatrix(TMatrix3x3& R)const
475  {
476  R(0, 0) = 2.0 * (mW * mW + mX * mX - 0.5);
477  R(0, 1) = 2.0 * (mX * mY - mW * mZ);
478  R(0, 2) = 2.0 * (mX * mZ + mW * mY);
479 
480  R(1, 0) = 2.0 * (mY * mX + mW * mZ);
481  R(1, 1) = 2.0 * (mW * mW + mY * mY - 0.5);
482  R(1, 2) = 2.0 * (mY * mZ - mX * mW);
483 
484  R(2, 0) = 2.0 * (mZ * mX - mW * mY);
485  R(2, 1) = 2.0 * (mZ * mY + mW * mX);
486  R(2, 2) = 2.0 * (mW * mW + mZ * mZ - 0.5);
487  }
488 
495  inline void toRotationVector(T& rx, T& ry, T& rz)const
496  {
497  T xx, yy, zz, ww;
498 
499  if (mW < 0.0) {
500  xx = -mX;
501  yy = -mY;
502  zz = -mZ;
503  ww = -mW;
504  }
505  else {
506  xx = mX;
507  yy = mY;
508  zz = mZ;
509  ww = mW;
510  }
511 
512  T vNorm = xx * xx + yy * yy + zz * zz;
513  if (vNorm == 0.0) {
514  rx = 0.0;
515  ry = 0.0;
516  rz = 0.0;
517  return;
518  }
519 
520  if (vNorm != 1.0)
521  vNorm = std::sqrt(vNorm);
522 
523  T mult = (vNorm < ww) ? (2.0 / vNorm * std::asin(vNorm)) : (2.0 / vNorm * std::acos(ww));
524 
525  rx = xx * mult;
526  ry = yy * mult;
527  rz = zz * mult;
528  }
529 
538  template<class TVector3>
539  inline void toRotationVector(TVector3& v)const
540  {
541  toRotationVector(v(0), v(1), v(2));
542  }
543 
555  template<class TVector3_A, class TVector3_B>
556  inline void rotateVector(const TVector3_A& a, TVector3_B& b)const
557  {
558  // b = 2.0 * cross( this->VectorialPart, a )
559  b(0) = 2.0 * (mY * a(2) - mZ * a(1));
560  b(1) = 2.0 * (mZ * a(0) - mX * a(2));
561  b(2) = 2.0 * (mX * a(1) - mY * a(0));
562 
563  // c = cross( this->VectorialPart, b )
564  T c0 = mY * b(2) - mZ * b(1);
565  T c1 = mZ * b(0) - mX * b(2);
566  T c2 = mX * b(1) - mY * b(0);
567 
568  // set results
569  b(0) = a(0) + b(0) * mW + c0;
570  b(1) = a(1) + b(1) * mW + c1;
571  b(2) = a(2) + b(2) * mW + c2;
572  }
573 
584  template<class TVector3>
585  inline void rotateVector(TVector3& a)const
586  {
587  // b = 2.0 * cross( this->VectorialPart, a )
588  T b0 = 2.0 * (mY * a(2) - mZ * a(1));
589  T b1 = 2.0 * (mZ * a(0) - mX * a(2));
590  T b2 = 2.0 * (mX * a(1) - mY * a(0));
591 
592  // c = cross( this->VectorialPart, b )
593  T c0 = mY * b2 - mZ * b1;
594  T c1 = mZ * b0 - mX * b2;
595  T c2 = mX * b1 - mY * b0;
596 
597  // set results
598  a(0) += b0 * mW + c0;
599  a(1) += b1 * mW + c1;
600  a(2) += b2 * mW + c2;
601  }
602 
603 public:
604 
609  static inline ASDQuaternion Identity()
610  {
611  return ASDQuaternion(1.0, 0.0, 0.0, 0.0);
612  }
613 
622  static inline ASDQuaternion FromAxisAngle(T x, T y, T z, T radians)
623  {
624  T sqnorm = x * x + y * y + z * z;
625  if (sqnorm == 0.0)
626  return ASDQuaternion::Identity();
627 
628  if (sqnorm > 0.0 && sqnorm != 1.0) {
629  T norm = std::sqrt(sqnorm);
630  x /= norm;
631  y /= norm;
632  z /= norm;
633  }
634 
635  T halfAngle = radians * 0.5;
636 
637  T s = std::sin(halfAngle);
638  T q0 = std::cos(halfAngle);
639 
640  ASDQuaternion result(q0, s * x, s * y, s * z);
641  result.normalize();
642 
643  return result;
644  }
645 
653  static inline ASDQuaternion FromRotationVector(T rx, T ry, T rz)
654  {
655  T rModulus = rx * rx + ry * ry + rz * rz;
656  if (rModulus == 0.0)
657  return ASDQuaternion::Identity();
658 
659  if (rModulus != 1.0) {
660  rModulus = std::sqrt(rModulus);
661  rx /= rModulus;
662  ry /= rModulus;
663  rz /= rModulus;
664  }
665 
666  T halfAngle = rModulus * 0.5;
667 
668  T q0 = std::cos(halfAngle);
669  T s = std::sin(halfAngle);
670 
671  ASDQuaternion result(q0, rx * s, ry * s, rz * s);
672  result.normalize();
673 
674  return result;
675  }
676 
686  template<class TVector3>
687  static inline ASDQuaternion FromRotationVector(const TVector3& v)
688  {
689  return ASDQuaternion::FromRotationVector(v(0), v(1), v(2));
690  }
691 
703  template<class TMatrix3x3>
704  static inline ASDQuaternion FromRotationMatrix(const TMatrix3x3& m)
705  {
706  T xx = m(0, 0);
707  T yy = m(1, 1);
708  T zz = m(2, 2);
709  T tr = xx + yy + zz;
710  ASDQuaternion Q;
711  if ((tr > xx) && (tr > yy) && (tr > zz))
712  {
713  T S = std::sqrt(tr + 1.0) * 2.0;
714  Q = ASDQuaternion(
715  0.25 * S,
716  (m(2, 1) - m(1, 2)) / S,
717  (m(0, 2) - m(2, 0)) / S,
718  (m(1, 0) - m(0, 1)) / S
719  );
720  }
721  else if ((xx > yy) && (xx > zz))
722  {
723  T S = std::sqrt(1.0 + xx - yy - zz) * 2.0;
724  Q = ASDQuaternion(
725  (m(2, 1) - m(1, 2)) / S,
726  0.25 * S,
727  (m(0, 1) + m(1, 0)) / S,
728  (m(0, 2) + m(2, 0)) / S
729  );
730  }
731  else if (yy > zz)
732  {
733  T S = std::sqrt(1.0 + yy - xx - zz) * 2.0;
734  Q = ASDQuaternion(
735  (m(0, 2) - m(2, 0)) / S,
736  (m(0, 1) + m(1, 0)) / S,
737  0.25 * S,
738  (m(1, 2) + m(2, 1)) / S
739  );
740  }
741  else
742  {
743  T S = std::sqrt(1.0 + zz - xx - yy) * 2.0;
744  Q = ASDQuaternion(
745  (m(1, 0) - m(0, 1)) / S,
746  (m(0, 2) + m(2, 0)) / S,
747  (m(1, 2) + m(2, 1)) / S,
748  0.25 * S
749  );
750  }
751 
752 
753  Q.normalize();
754  return Q;
755  }
756 
757 private:
758  T mX;
759  T mY;
760  T mZ;
761  T mW;
762 
763 };
764 
772 template<class T>
773 inline ASDQuaternion<T> operator* (const ASDQuaternion<T>& a, const ASDQuaternion<T>& b)
774 {
775  return ASDQuaternion<T>(
776  a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
777  a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
778  a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
779  a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
780  );
781 }
782 
789 template<class TStream, class T>
790 inline TStream& operator << (TStream& s, const ASDQuaternion<T>& q)
791  {
792  return (s << "[(" << q.x() << ", " << q.y() << ", " << q.z() << "), " << q.w() << "]");
793  }
794 } // end of XC namespace
795 
796 #endif // !ASDMath_h
797 
798 
Float vector abstraction.
Definition: Vector.h:94
ASDVector3(const Vector &v, size_t index=0)
Creates a ASDVector3 from a Vector starting from index.
Definition: ASDMath.h:105
T squaredNorm() const
Returns the squared norm this vector.
Definition: ASDMath.h:189
ASDVector3(T x, T y, T z)
Creates a ASDVector3 from its coefficients.
Definition: ASDMath.h:92
T & operator[](size_t i)
Returns the i-th coefficient of this vector.
Definition: ASDMath.h:181
ASDQuaternion(const ASDQuaternion &other)
Creates a ASDQuaternion from another ASDQuaternion.
Definition: ASDMath.h:363
ASDQuaternion(T w, T x, T y, T z)
Creates a ASDQuaternion from its coefficients.
Definition: ASDMath.h:351
void toRotationMatrix(TMatrix3x3 &R) const
Constructs a Rotation Matrix from this ASDQuaternion.
Definition: ASDMath.h:474
ASDVector3()
Creates a Zero ASDVector3.
Definition: ASDMath.h:81
const T z() const
Returns the Z coefficient of this quaternion.
Definition: ASDMath.h:406
void toRotationVector(T &rx, T &ry, T &rz) const
Extracts the Rotation Vector from this ASDQuaternion.
Definition: ASDMath.h:495
const T y() const
Returns the Y coefficient of this quaternion.
Definition: ASDMath.h:400
const T z() const
Returns the Z coefficient of this vector.
Definition: ASDMath.h:157
T operator[](size_t i) const
Returns the i-th coefficient of this vector.
Definition: ASDMath.h:175
ASDQuaternion conjugate() const
Returns the Conjugate of this ASDQuaternion, which represents the opposite rotation.
Definition: ASDMath.h:456
void toRotationVector(TVector3 &v) const
Extracts the Rotation Vector from this ASDQuaternion The vector type is the template parameter...
Definition: ASDMath.h:539
const T norm() const
Returns the norm of this quaternion.
Definition: ASDMath.h:431
static ASDQuaternion FromRotationVector(const TVector3 &v)
Returns a ASDQuaternion from a rotation vector.
Definition: ASDMath.h:687
void rotateVector(const TVector3_A &a, TVector3_B &b) const
Rotates a vector using this quaternion.
Definition: ASDMath.h:556
static ASDQuaternion FromRotationVector(T rx, T ry, T rz)
Returns a ASDQuaternion from a rotation vector.
Definition: ASDMath.h:653
T normalize()
makes this vector a unit vector.
Definition: ASDMath.h:210
T dot(const ASDVector3 &b) const
Returns the dot product this vector with another vector.
Definition: ASDMath.h:226
T & operator()(size_t i)
Returns the i-th coefficient of this vector.
Definition: ASDMath.h:169
ASDVector3 cross(const ASDVector3 &b) const
Returns the cross product this vector with another vector.
Definition: ASDMath.h:239
T norm() const
Returns the norm this vector.
Definition: ASDMath.h:201
void normalize()
Makes this ASDQuaternion a Unit ASDQuaternion.
Definition: ASDMath.h:440
ASDVector3(const ASDVector3 &other)
Creates a ASDVector3 from another ASDVector3.
Definition: ASDMath.h:116
const T x() const
Returns the X coefficient of this vector.
Definition: ASDMath.h:145
static ASDQuaternion FromAxisAngle(T x, T y, T z, T radians)
Returns a ASDQuaternion that represents a rotation of an angle &#39;radians&#39; around the axis (x...
Definition: ASDMath.h:622
Open source finite element program for structural analysis.
Definition: ContinuaReprComponent.h:35
ASDVector3 & operator=(const ASDVector3 &other)
Copies a ASDVector3.
Definition: ASDMath.h:129
const T squaredNorm() const
Returns the squared norm of this quaternion.
Definition: ASDMath.h:421
ASDQuaternion()
Creates a Zero ASDQuaternion.
Definition: ASDMath.h:336
const T x() const
Returns the X coefficient of this quaternion.
Definition: ASDMath.h:394
static ASDQuaternion FromRotationMatrix(const TMatrix3x3 &m)
Returns a ASDQuaternion from a Rotation Matrix.
Definition: ASDMath.h:704
T operator()(size_t i) const
Returns the i-th coefficient of this vector.
Definition: ASDMath.h:163
static ASDQuaternion Identity()
Returns the Identity ASDQuaternion (i.e.
Definition: ASDMath.h:609
ASDQuaternion A simple fixed size 3D vector.
Definition: ASDMath.h:72
const T y() const
Returns the Y coefficient of this vector.
Definition: ASDMath.h:151
void rotateVector(TVector3 &a) const
Rotates a vector using this quaternion.
Definition: ASDMath.h:585
ASDQuaternion A simple class that implements the main features of quaternion algebra.
Definition: ASDMath.h:328
const T w() const
Returns the W coefficient of this quaternion.
Definition: ASDMath.h:412