1 #ifndef VTESTBED_GEOMETRY_QUATERNION_HH 2 #define VTESTBED_GEOMETRY_QUATERNION_HH 6 #include <vtestbed/base/bstream.hh> 7 #include <vtestbed/geometry/math.hh> 8 #include <vtestbed/geometry/types.hh> 18 using vec4 = Vertex<T,4>;
19 using vec3 = Vertex<T,3>;
26 inline Quaternion(T s, T x, T y, T z): _data{s,x,y,z} {}
27 inline Quaternion(
const vec4& q): _data{q(0),q(1),q(2),q(3)} {}
28 inline Quaternion(T re,
const vec3& im): _data{re,im(0),im(1),im(2)} {}
29 inline T w()
const {
return this->_data[0]; }
30 inline T x()
const {
return this->_data[1]; }
31 inline T y()
const {
return this->_data[2]; }
32 inline T z()
const {
return this->_data[3]; }
34 inline T real()
const {
return w(); }
35 inline vec3 imag()
const {
return {x(),y(),z()}; }
36 inline T operator()(
int i)
const {
return this->_data[i]; }
37 inline T operator[](
int i)
const {
return this->_data[i]; }
38 inline const vec4& data()
const {
return this->_data; }
60 template <
class T>
inline T real(
const Quaternion<T>& q) {
return q.real(); }
61 template <
class T>
inline Vertex<T,3> imag(
const Quaternion<T>& q) {
return q.imag(); }
66 operator*(
const Quaternion<T>& a,
const Quaternion<T>& b);
70 operator*=(Quaternion<T>& a,
const Quaternion<T>& b) {
77 operator*(
const Quaternion<T>& a, T b) {
78 return {a(0)*b, a(1)*b, a(2)*b, a(3)*b};
83 operator*(T a,
const Quaternion<T>& b) {
84 return {a*b(0), a*b(1), a*b(2), a*b(3)};
89 operator/(
const Quaternion<T>& a, T b) {
90 return {a(0)/b, a(1)/b, a(2)/b, a(3)/b};
95 operator+(Quaternion<T>& a,
const Quaternion<T>& b) {
96 return Quaternion<T>{a(0)+b(0),a(1)+b(1),a(2)+b(2),a(3)+b(3)};
101 operator+=(Quaternion<T>& a,
const Quaternion<T>& b) {
108 unit(
const Quaternion<T>& q) {
109 return ::vtb::geometry::unit(q.data());
114 length(
const Quaternion<T>& q) {
131 from_euler_angles(
const Vertex<T,3>& angles);
135 rotation_matrix(
const Quaternion<T>& q);
139 from_vector(
const Quaternion<T>& q) {
142 return Quaternion<T>{
143 sqrt(1 - pow2(q(1)) - pow2(q(2)) - pow2(q(3))),
152 to_vector(
const Quaternion<T>& q) {
153 return Quaternion<T>{0, q(1), q(2), q(3)};
158 conj(
const Quaternion<T>& q) {
159 return Quaternion<T>{q(0), -q(1), -q(2), -q(3)};
164 rotate(
const Vertex<T,3>& v,
const Quaternion<T>& q) {
165 return (q*Quaternion<T>(T{},v)*conj(q)).imag();
171 using scalar_type = T;
172 using vertex_type = Vertex<T,3>;
177 vertex_type _origin{T{}};
186 const vertex_type& origin):
187 _quaternion(q), _quaternion_conj(q_conj), _origin(origin) {}
193 inline const quaternion_type& quaternion()
const {
return this->_quaternion; }
194 inline const quaternion_type& quaternion_conj()
const {
return this->_quaternion_conj; }
198 this->_quaternion = rhs, this->_quaternion_conj = conj(rhs);
201 inline const vertex_type& origin()
const {
return this->_origin; }
202 inline void origin(
const vertex_type& rhs) { this->_origin = rhs; }
204 inline void clear() {
205 this->_quaternion.clear(), this->_quaternion_conj.clear(),
213 make_coordinate_system(
const Quaternion<T>& q,
const Vertex<T,3>& origin) {
218 inline Quaternion_coordinate_system<T>
219 make_coordinate_system(
const Quaternion<T>& q,
220 const Quaternion<T>& q_conj,
221 const Vertex<T,3>& origin) {
222 return Quaternion_coordinate_system<T>(q, q_conj, origin);
227 to(
const Quaternion_coordinate_system<T>& cs,
const Vertex<T,3>& v) {
228 Vertex<T,3> x = v-cs.origin();
229 return rotate(x, cs.quaternion());
234 from(
const Quaternion_coordinate_system<T>& cs,
const Vertex<T,3>& v) {
235 return rotate(v, cs.quaternion_conj()) + cs.origin();
240 vector_to(
const Quaternion_coordinate_system<T>& cs,
const Vertex<T,3>& v) {
241 return rotate(v, cs.quaternion());
246 vector_from(
const Quaternion_coordinate_system<T>& cs,
const Vertex<T,3>& v) {
247 return rotate(v, cs.quaternion_conj());
254 #endif // vim:filetype=cpp
T length(const blitz::TinyVector< T, N > &x)
Computes vector length without overflow.
Vertex< T, 3 > to_euler_angles(const Quaternion< T > &q)
Convert quaternion to Euler angles.