URL:
https://svn.lrde.epita.fr/svn/oln/trunk/milena
ChangeLog:
2007-09-21 Simon Nivault <simon.nivault(a)lrde.epita.fr>
Add quaternion based on vector 4d
* mln/metal/vec.hh: Add sprod, vprod and normalize.
* mln/norm/l2.hh: New, Works on C-tabs and on metal::vec.
* mln/value/quat.hh: New.
* tests/norm_l2.cc: New.
* tests/value_quat.cc: New.
---
mln/metal/vec.hh | 117 +++++++++++++++++
mln/norm/l2.hh | 111 ++++++++++++++++
mln/value/quat.hh | 343 ++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/norm_l2.cc | 54 ++++++++
tests/value_quat.cc | 72 ++++++++++
5 files changed, 694 insertions(+), 3 deletions(-)
Index: trunk/milena/tests/value_quat.cc
===================================================================
--- trunk/milena/tests/value_quat.cc (revision 0)
+++ trunk/milena/tests/value_quat.cc (revision 1151)
@@ -0,0 +1,72 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/*! \file tests/value_int_u8.cc
+ *
+ * \brief Tests on mln::value::int_u8.
+ */
+
+#include <iostream>
+
+#include <mln/value/quat.hh>
+
+
+int main()
+{
+ using namespace mln;
+
+ value::quat q1(3.f, 4.f, 1.6f, 0.5f);
+ value::quat q2(1.2, make::vec(3, 6, 4));
+ value::quat q3(make::vec(1.3, 3., -6., 4.));
+
+ std::cout << q1 << std::endl;
+ std::cout << q2 << std::endl;
+ std::cout << q3 << std::endl;
+
+ std::cout << q1.scal() << std::endl;
+
+ q1.set_scal(2.6);
+ std::cout << q1 << std::endl;
+
+ std::cout << q1.vect() << std::endl;
+
+ q2.set_vect(make::vec(1.4, 5.9, 3.1));
+ std::cout << q2 << std::endl;
+
+ std::cout << q2 * q3 << std::endl;
+
+ mln_assertion(!q3.is_unit());
+ q3.set_unit();
+ std::cout << q3 << std::endl;
+ mln_assertion(q3.is_unit());
+
+ std::cout << q2.conj() << std::endl;
+ std::cout << q2.inv() << std::endl;
+ std::cout << norm::l2(q2) << ' ' << norm::l2(q2.inv())
<< std::endl;
+ std::cout << q2.inv().inv() << std::endl;
+
+}
Index: trunk/milena/tests/norm_l2.cc
===================================================================
--- trunk/milena/tests/norm_l2.cc (revision 0)
+++ trunk/milena/tests/norm_l2.cc (revision 1151)
@@ -0,0 +1,54 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/*! \file tests/norm_l2.cc
+ *
+ * \brief Tests on mln::norm::l2.
+ */
+
+#include <iostream>
+
+#include <mln/norm/l2.hh>
+
+#include <mln/metal/vec.hh>
+
+int main()
+{
+ using namespace mln;
+
+ int t1[] = {2, 6, -1, 2};
+
+ std::cout << norm::l2(t1) << std::endl;
+
+ int t2[] = {2, -6, -1, 2};
+
+ std::cout << norm::l2_distance(t1, t2) << std::endl;
+
+ metal::vec<4,float> v = make::vec(2, 6, -1, 2);
+
+ std::cout << norm::l2(v);
+}
Index: trunk/milena/mln/metal/vec.hh
===================================================================
--- trunk/milena/mln/metal/vec.hh (revision 1150)
+++ trunk/milena/mln/metal/vec.hh (revision 1151)
@@ -29,6 +29,7 @@
# define MLN_METAL_VEC_HH
# include <iostream>
+# include <cmath>
# include <mln/core/contract.hh>
# include <mln/metal/binary_arith_trait.hh>
@@ -140,10 +141,84 @@
void set_all(const T& val);
+ T sprod(const vec<n, T>& rhs) const;
+
unsigned size() const;
+ const vec<n, T>& normalize();
};
+ // eq
+
+ template <unsigned n, typename T, typename U>
+ bool operator==(const vec<n,T>& lhs, const vec<n,U>& rhs);
+
+ template <unsigned n, typename T, typename U>
+ bool operator!=(const vec<n,T>& lhs, const vec<n,U>& rhs);
+
+ // +
+
+ template <unsigned n, typename T, typename U>
+ vec<n,T>&
+ operator+=(vec<n,T>& lhs, const vec<n,U>& rhs);
+
+ template <unsigned n, typename T, typename U>
+ vec<n, typename binary_arith_trait<T,U>::ret >
+ operator+(const vec<n,T>& lhs, const vec<n,U>& rhs);
+
+ // -
+
+ template <unsigned n, typename T, typename U>
+ vec<n,T>&
+ operator-=(vec<n,T>& lhs, const vec<n,U>& rhs);
+
+ template <unsigned n, typename T, typename U>
+ vec<n, typename binary_arith_trait<T,U>::ret>
+ operator-(const vec<n,T>& lhs, const vec<n,U>& rhs);
+
+ template <unsigned n, typename T>
+ vec<n, T>
+ operator-(const vec<n,T>& lhs);
+
+ // *
+
+ template <unsigned n, typename T, typename S>
+ vec<n,T>&
+ operator*=(vec<n,T>& lhs, const S& scalar);
+
+ template <unsigned n, typename T, typename S>
+ vec<n, typename binary_arith_trait<T,S>::ret>
+ operator*(const S& scalar, const vec<n,T>& lhs);
+
+ // /
+
+ template <unsigned n, typename T, typename S>
+ vec<n,T>&
+ operator/=(vec<n,T>& lhs, const S& scalar);
+
+ template <unsigned n, typename T, typename S>
+ vec<n, typename binary_arith_trait<T,S>::ret>
+ operator/(const vec<n,T>& lhs, const S& scalar);
+
+ // <<
+
+ template <unsigned n, typename T>
+ std::ostream&
+ operator<<(std::ostream& ostr, const vec<n,T>& v);
+
+ template <unsigned n>
+ std::ostream&
+ operator<<(std::ostream& ostr, const vec<n,unsigned char>& v);
+
+ template <unsigned n>
+ std::ostream&
+ operator<<(std::ostream& ostr, const vec<n,signed char>& v);
+
+ // vprod
+
+ template <typename T, typename U>
+ vec<3, typename binary_arith_trait<T, U>::ret>
+ vprod(const vec<3, T>& lhs, const vec<3, U>& rhs);
# ifndef MLN_INCLUDE_ONLY
@@ -193,11 +268,33 @@
}
template <unsigned n, typename T>
+ T vec<n,T>::sprod(const vec<n, T>& rhs) const
+ {
+ T tmp = 0;
+
+ for (unsigned i = 0; i < n; ++i)
+ tmp += data_[i] * rhs.data_[i];
+ return tmp;
+ }
+
+ template <unsigned n, typename T>
unsigned vec<n,T>::size() const
{
return n;
}
+ template <unsigned n, typename T>
+ const vec<n, T>& vec<n, T>::normalize()
+ {
+ float n_l2 = 0;
+ for (unsigned i = 0; i < n; ++i)
+ n_l2 += data_[i] * data_[i];
+ n_l2 = sqrt(n_l2);
+ for (unsigned i = 0; i < n; ++i)
+ data_[i] = T(data_[i] / n_l2);
+ return *this;
+ }
+
// eq
@@ -284,7 +381,7 @@
template <unsigned n, typename T, typename S>
vec<n, typename binary_arith_trait<T,S>::ret>
- operator*(const vec<n,T>& lhs, const S& scalar)
+ operator*(const S& scalar, const vec<n,T>& lhs)
{
vec<n, typename binary_arith_trait<T,S>::ret> tmp;
for (unsigned i = 0; i < n; ++i)
@@ -299,7 +396,7 @@
vec<n,T>&
operator/=(vec<n,T>& lhs, const S& scalar)
{
- precondition(scalar != 0);
+ mln_precondition(scalar != 0);
for (unsigned i = 0; i < n; ++i)
lhs[i] /= scalar;
return lhs;
@@ -309,7 +406,7 @@
vec<n, typename binary_arith_trait<T,S>::ret>
operator/(const vec<n,T>& lhs, const S& scalar)
{
- precondition(scalar != 0);
+ mln_precondition(scalar != 0);
vec<n, typename binary_arith_trait<T,S>::ret> tmp;
for (unsigned i = 0; i < n; ++i)
tmp[i] = lhs[i] / scalar;
@@ -349,6 +446,20 @@
return ostr;
}
+ // vprod
+
+ template <typename T, typename U>
+ vec<3, typename binary_arith_trait<T, U>::ret>
+ vprod(const vec<3, T>& lhs, const vec<3, U>& rhs)
+ {
+ vec<3, typename binary_arith_trait<T, U>::ret> tmp;
+ tmp[0] = lhs[1] * rhs[2] - lhs[2] * rhs[1];
+ tmp[1] = lhs[2] * rhs[0] - lhs[0] * rhs[2];
+ tmp[2] = lhs[0] * rhs[1] - lhs[1] * rhs[0];
+ return tmp;
+ }
+
+
# endif // MLN_INCLUDE_ONLY
Index: trunk/milena/mln/norm/l2.hh
===================================================================
--- trunk/milena/mln/norm/l2.hh (revision 0)
+++ trunk/milena/mln/norm/l2.hh (revision 1151)
@@ -0,0 +1,111 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_NORM_L2_HH
+# define MLN_NORM_L2_HH
+
+/*! \file mln/norm/l2.hh
+ *
+ * \brief Define some infinity-norm related routines.
+ */
+
+# include <cmath>
+
+# include <mln/metal/vec.hh>
+
+namespace mln
+{
+
+ namespace norm
+ {
+
+ /// Infinity-norm of a vector \p vec.
+ template <unsigned n, typename C>
+ float l2(const C (&vec)[n]);
+
+ /// Infinity-norm distance between vectors \p v1 and \p v2.
+ template <unsigned n, typename C>
+ float l2_distance(const C (&v1)[n], const C (&v2)[n]);
+
+ template <unsigned n, typename C>
+ float l2(const metal::vec<n,C>& vec);
+
+ template <unsigned n, typename C>
+ float l2_distance(const metal::vec<n,C>& vec1, const
metal::vec<n,C>& vec2);
+
+# ifndef MLN_INCLUDE_ONLY
+
+ template <unsigned n, typename C>
+ float l2(const C (&vec)[n])
+ {
+ C c = 0;
+ for (unsigned i = 0; i < n; ++i)
+ c += vec[i] * vec[i];
+ return sqrt(c);
+ }
+
+ template <unsigned n, typename C>
+ float l2_distance(const C (&v1)[n], const C (&v2)[n])
+ {
+ C d = 0;
+ for (unsigned i = 0; i < n; ++i)
+ {
+ C dd = v1[i] - v2[i];
+ d += dd * dd;
+ }
+ return sqrt(d);
+ }
+
+ template <unsigned n, typename C>
+ float l2(const metal::vec<n,C>& vec)
+ {
+ C c = 0;
+ for (unsigned i = 0; i < n; ++i)
+ c += vec[i] * vec[i];
+ return sqrt(c);
+ }
+
+ template <unsigned n, typename C>
+ float l2(const metal::vec<n,C>& vec1, const metal::vec<n,C>&
vec2)
+ {
+ C d = 0;
+ for (unsigned i = 0; i < n; ++i)
+ {
+ C dd = vec1[i] - vec2[i];
+ d += dd * dd;
+ }
+ return sqrt(d);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::norm
+
+} // end of namespace mln
+
+
+#endif // ! MLN_NORM_L2_HH
Index: trunk/milena/mln/value/quat.hh
===================================================================
--- trunk/milena/mln/value/quat.hh (revision 0)
+++ trunk/milena/mln/value/quat.hh (revision 1151)
@@ -0,0 +1,343 @@
+// Copyright (C) 2007 EPITA Research and Development Laboratory
+//
+// This file is part of the Olena Library. This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License version 2 as published by the
+// Free Software Foundation.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING. If not, write to
+// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+// Boston, MA 02111-1307, USA.
+//
+// As a special exception, you may use this file as part of a free
+// software library without restriction. Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License. This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+#ifndef MLN_VALUE_QUAT_HH
+# define MLN_VALUE_QUAT_HH
+
+# include <cmath>
+
+# include <mln/metal/vec.hh>
+# include <mln/norm/l2.hh>
+# include <mln/value/props.hh>
+
+namespace mln
+{
+
+ namespace value
+ {
+
+ class quat : public metal::vec<4, float>
+ {
+ public:
+
+ // ctors
+
+ quat();
+ quat(float s, float x, float y, float z);
+
+ template <typename T>
+ quat(float s, const metal::vec<3,T>& v);
+
+ template <typename T>
+ quat(const metal::vec<4,T>& v);
+
+ // accessors/modifiers as a 'scalar+metal::vec<3>'
+
+ float scal() const;
+ void set_scal(float s);
+
+ metal::vec<3,float> vect() const;
+ void set_vect(float x, float y, float z);
+ template <typename T>
+ void set_vect(const metal::vec<3,T>& v);
+
+ // multiplication
+
+ quat operator*(const quat& rhs) const;
+
+ // tests
+
+ bool is_unit() const;
+ bool is_null() const;
+
+ // conjugate and invert
+
+ quat conj() const;
+ quat inv() const;
+
+ // transform into unit quaternion
+
+ quat& set_unit();
+ template <typename T>
+ void set_unit(float theta, const metal::vec<3,T>& uv);
+
+ // only for unit quaternions described by theta and uv such as:
+ // q = ( cos(theta), sin(theta) * uv )
+
+ template <typename T>
+ quat(unsigned one, float theta, const metal::vec<3, T>& uv);
+
+ float theta() const;
+ void set_theta(float theta);
+
+ metal::vec<3, float> uvect() const;
+ template <typename T>
+ void set_uvect(const metal::vec<3,T>& uv);
+
+ };
+
+ // overloaded math procs
+
+ quat log(const quat& q);
+ quat exp(const quat& q);
+ quat pow(const quat& q, double t);
+ template <typename T>
+ bool about_equal(const T& f, const T& q);
+ bool about_equal(const quat& p, const quat& q);
+
+
+ // meths and procs bodies...
+
+# ifndef MLN_INCLUDE_ONLY
+
+ //ctors
+
+
+ quat::quat()
+ {
+ }
+
+ quat::quat(float s, float x, float y, float z)
+ {
+ set_scal(s);
+ set_vect(x, y, z);
+ }
+
+ template <typename T>
+ quat::quat(float s, const metal::vec<3,T>& v)
+ {
+ set_scal(s);
+ set_vect(v);
+ }
+
+ template <typename T>
+ quat::quat(const metal::vec<4,T>& v)
+ : metal::vec<4,float>(v)
+ {
+ }
+
+
+ // accessors/modifiers as a 'scalar+vec<3>'
+
+
+ float quat::scal() const
+ {
+ return data_[0];
+ }
+
+
+ void quat::set_scal(float s)
+ {
+ data_[0] = s;
+ }
+
+
+ metal::vec<3, float> quat::vect() const
+ {
+ return make::vec(data_[1], data_[2], data_[3]);
+ }
+
+
+ void quat::set_vect(float x, float y, float z)
+ {
+ data_[1] = x;
+ data_[2] = y;
+ data_[3] = z;
+ }
+
+ template <typename T>
+ void quat::set_vect(const metal::vec<3,T>& v)
+ {
+ set_vect(v[0], v[1], v[2]);
+ }
+
+
+ // multiplication
+
+
+ quat quat::operator*(const quat& rhs) const
+ {
+ float
+ s1 = scal(),
+ s2 = rhs.scal();
+
+ metal::vec<3,float>
+ v1 = vect(),
+ v2 = rhs.vect();
+
+ return quat(s1 * s2 - v1.sprod(v2),
+ metal::vprod(v1, v2)
+ + s1 * v2 + s2 * v1);
+ }
+
+
+ // tests
+
+
+ bool quat::is_unit() const
+ {
+ return about_equal(norm::l2(*this), 1.f);
+ }
+
+
+ bool quat::is_null() const
+ {
+ return about_equal(norm::l2(*this), 0.f);
+ }
+
+
+ // conjugate and invert
+
+
+ quat quat::conj() const
+ {
+ return quat(scal(), - vect());
+ }
+
+
+ quat quat::inv() const
+ {
+ assert(! is_null());
+ float f = norm::l2(*this);
+
+ return conj() / (f * f);
+ }
+
+
+ // transform into unit quaternion
+
+
+ quat& quat::set_unit()
+ {
+ normalize();
+ return *this;
+ }
+
+
+ template <typename T>
+ void quat::set_unit(float theta, const metal::vec<3,T>& uv)
+ {
+ static const float pi = 3.14159265358979323846;
+
+ mln_precondition(theta > - pi - props<float>::epsilon()
+ && theta < pi + props<float>::epsilon());
+ mln_precondition(about_equal(norm::l2(uv), 1.f));
+
+ data_[0] = cos(theta);
+ float sint = sin(theta);
+ data_[1] = uv[0] * sint;
+ data_[2] = uv[1] * sint;
+ data_[3] = uv[2] * sint;
+ }
+
+ // only for unit quaternions described by theta and uv such as:
+ // q = ( cos(theta), sin(theta) * uv )
+
+
+ template <typename T>
+ quat::quat(unsigned one, float theta, const metal::vec<3,T>& uv)
+ {
+ mln_precondition(one == 1);
+ set_unit(theta, uv);
+ }
+
+
+ float quat::theta() const
+ {
+ mln_precondition(is_unit());
+ return acos(scal());
+ }
+
+
+ void quat::set_theta(float theta)
+ {
+ mln_precondition(is_unit());
+ set_unit(theta, uvect());
+ }
+
+ metal::vec<3, float> quat::uvect() const
+ {
+ mln_precondition(is_unit());
+ metal::vec<3, float> v = vect();
+ return v.normalize();
+ }
+
+ template <typename T>
+ void quat::set_uvect(const metal::vec<3,T>& uv)
+ {
+ mln_precondition(is_unit());
+ set_unit(theta(), uv);
+ }
+
+
+ // overloaded math procs
+
+
+ quat log(const quat& q)
+ {
+ mln_precondition(q.is_unit());
+ return quat(0.f, q.theta() * q.uvect());
+ }
+
+
+ quat exp(const quat& q)
+ {
+ mln_precondition(about_equal(q.scal(), 0.f));
+ metal::vec<3, float> v = q.vect();
+ float theta = norm::l2(v);
+ mln_precondition(!about_equal(theta, 0.f));
+ metal::vec<3, float> uv = v / theta;
+ return quat(cos(theta), sin(theta) * uv);
+ }
+
+
+ quat pow(const quat& q, double t)
+ {
+ mln_precondition(q.is_unit());
+ return exp(t * log(q));
+ }
+
+ template <typename T>
+ bool about_equal(const T& f, const T& q)
+ {
+ if (f > q)
+ return (f - q ) < props<T>::epsilon();
+ return (q - f) < props<T>::epsilon();
+ }
+
+ bool about_equal(const quat& p, const quat& q)
+ {
+ return about_equal<float>(norm::l2(p - q), 0);
+ }
+
+# endif // ! MLN_INCLUDE_ONLY
+
+ } // end of namespace mln::value
+
+} // end of namespace mln
+
+#endif // ! MLN_VALUE_QUAT_HH