From 9e6d3de54aeb5717a7ab3ac85519d4bc85cd2142 Mon Sep 17 00:00:00 2001
From: Oliver Sander <sander@igpm.rwth-aachen.de>
Date: Mon, 2 Feb 2009 10:08:28 +0000
Subject: [PATCH] A new class which embodies rotations in Euclidean spaces

[[Imported from SVN: r3487]]
---
 src/rotation.hh | 98 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)
 create mode 100644 src/rotation.hh

diff --git a/src/rotation.hh b/src/rotation.hh
new file mode 100644
index 00000000..b9293cd9
--- /dev/null
+++ b/src/rotation.hh
@@ -0,0 +1,98 @@
+#ifndef ROTATION_HH
+#define ROTATION_HH
+
+/** \file
+    \brief Define rotations in Euclidean spaces
+*/
+
+#include <dune/common/fvector.hh>
+#include <dune/common/fixedarray.hh>
+#include <dune/common/fmatrix.hh>
+#include <dune/common/exceptions.hh>
+
+#include "quaternion.hh"
+
+
+template <int dim, class T>
+class Rotation
+{
+
+};
+
+/** \brief Specialization for dim==3 
+
+Uses unit quaternion coordinates.
+*/
+template <class T>
+class Rotation<3,T> : public Quaternion<T>
+{
+
+    /** \brief Computes sin(x/2) / x without getting unstable for small x */
+    static T sincHalf(const T& x) {
+        return (x < 1e-4) ? 0.5 + (x*x/48) : std::sin(x/2)/x;
+    }
+
+public:
+
+    /** \brief Default constructor creates the identity element */
+    Rotation()
+        : Quaternion<T>(0,0,0,1)
+    {}
+
+    Rotation<3,T>(Dune::FieldVector<T,3> axis, T angle) 
+        : Quaternion<T>(axis, angle)
+    {}
+
+    /** \brief Assignment from a quaternion
+        \deprecated Using this is bad design.
+    */
+    Rotation& operator=(const Quaternion<T>& other) {
+        (*this)[0] = other[0];
+        (*this)[1] = other[1];
+        (*this)[2] = other[2];
+        (*this)[3] = other[3];
+        return *this;
+    }
+
+    /** \brief Return the identity element */
+    static Rotation<3,T> identity() {
+        // Default constructor creates an identity
+        Rotation<3,T> id;
+        return id;
+    }
+
+    /** \brief Right multiplication */
+    Rotation<3,T> mult(const Rotation<3,T>& other) const {
+        Rotation<3,T> q;
+        q[0] =   (*this)[3]*other[0] - (*this)[2]*other[1] + (*this)[1]*other[2] + (*this)[0]*other[3];
+        q[1] =   (*this)[2]*other[0] + (*this)[3]*other[1] - (*this)[0]*other[2] + (*this)[1]*other[3];
+        q[2] = - (*this)[1]*other[0] + (*this)[0]*other[1] + (*this)[3]*other[2] + (*this)[2]*other[3];
+        q[3] = - (*this)[0]*other[0] - (*this)[1]*other[1] - (*this)[2]*other[2] + (*this)[3]*other[3];
+
+        return q;
+    }
+
+    /** \brief The exponential map from \f$ \mathfrak{so}(3) \f$ to \f$ SO(3) \f$
+     */
+    static Rotation<3,T> exp(const T& v0, const T& v1, const T& v2) {
+        Rotation<3,T> q;
+
+        T normV = std::sqrt(v0*v0 + v1*v1 + v2*v2);
+
+        // Stabilization for small |v| due to Grassia
+        T sin = sincHalf(normV);
+
+        // if normV == 0 then q = (0,0,0,1)
+        assert(!isnan(sin));
+            
+        q[0] = sin * v0;
+        q[1] = sin * v1;
+        q[2] = sin * v2;
+        q[3] = std::cos(normV/2);
+
+        return q;
+    }
+    
+};
+
+#endif
-- 
GitLab