aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Eigen/src/Array/PartialRedux.h38
-rw-r--r--Eigen/src/Geometry/OrthoMethods.h38
-rw-r--r--Eigen/src/Geometry/Quaternion.h11
-rw-r--r--demos/opengl/quaternion_demo.cpp89
-rw-r--r--doc/D01_StlContainers.dox4
-rw-r--r--doc/D11_UnalignedArrayAssert.dox2
-rw-r--r--doc/I05_FixedSizeVectorizable.dox2
-rw-r--r--test/CMakeLists.txt11
-rw-r--r--test/geo_alignedbox.cpp (renamed from test/alignedbox.cpp)4
-rw-r--r--test/geo_eulerangles.cpp70
-rw-r--r--test/geo_hyperplane.cpp (renamed from test/hyperplane.cpp)2
-rw-r--r--test/geo_orthomethods.cpp109
-rw-r--r--test/geo_parametrizedline.cpp (renamed from test/parametrizedline.cpp)2
-rw-r--r--test/geo_quaternion.cpp116
-rw-r--r--test/geo_transformations.cpp (renamed from test/geometry.cpp)103
-rw-r--r--test/sparse_product.cpp1
16 files changed, 445 insertions, 157 deletions
diff --git a/Eigen/src/Array/PartialRedux.h b/Eigen/src/Array/PartialRedux.h
index 2ae67663a..d1ed33c38 100644
--- a/Eigen/src/Array/PartialRedux.h
+++ b/Eigen/src/Array/PartialRedux.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
@@ -176,7 +176,7 @@ template<typename ExpressionType, int Direction> class PartialRedux
};
typedef typename ExpressionType::PlainMatrixType CrossReturnType;
-
+
inline PartialRedux(const ExpressionType& matrix) : m_matrix(matrix) {}
/** \internal */
@@ -249,7 +249,7 @@ template<typename ExpressionType, int Direction> class PartialRedux
* \sa MatrixBase::any() */
const typename ReturnType<ei_member_any>::Type any() const
{ return _expression(); }
-
+
/** \returns a row (or column) vector expression representing
* the number of \c true coefficients of each respective column (or row).
*
@@ -269,8 +269,8 @@ template<typename ExpressionType, int Direction> class PartialRedux
* \sa MatrixBase::prod() */
const typename ReturnType<ei_member_prod>::Type prod() const
{ return _expression(); }
-
-
+
+
/** \returns a matrix expression
* where each column (or row) are reversed.
*
@@ -282,33 +282,9 @@ template<typename ExpressionType, int Direction> class PartialRedux
{
return Reverse<ExpressionType, Direction>( _expression() );
}
-
-
- /** \returns a 3x3 matrix expression of the cross product
- * of each column or row of the referenced expression with the \a other vector.
- *
- * \geometry_module
- *
- * \sa MatrixBase::cross() */
+
template<typename OtherDerived>
- const CrossReturnType cross(const MatrixBase<OtherDerived>& other) const
- {
- EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(CrossReturnType,3,3)
- EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
- EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
- YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
-
- if(Direction==Vertical)
- return (CrossReturnType()
- << _expression().col(0).cross(other),
- _expression().col(1).cross(other),
- _expression().col(2).cross(other)).finished();
- else
- return (CrossReturnType()
- << _expression().row(0).cross(other),
- _expression().row(1).cross(other),
- _expression().row(2).cross(other)).finished();
- }
+ const CrossReturnType cross(const MatrixBase<OtherDerived>& other) const;
protected:
ExpressionTypeNested m_matrix;
diff --git a/Eigen/src/Geometry/OrthoMethods.h b/Eigen/src/Geometry/OrthoMethods.h
index 047152d0b..e22df114a 100644
--- a/Eigen/src/Geometry/OrthoMethods.h
+++ b/Eigen/src/Geometry/OrthoMethods.h
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
@@ -50,6 +50,42 @@ MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const
);
}
+/** \returns a matrix expression of the cross product of each column or row
+ * of the referenced expression with the \a other vector.
+ *
+ * The referenced matrix must have one dimension equal to 3.
+ * The result matrix has the same dimensions than the referenced one.
+ *
+ * \geometry_module
+ *
+ * \sa MatrixBase::cross() */
+template<typename ExpressionType, int Direction>
+template<typename OtherDerived>
+const typename PartialRedux<ExpressionType,Direction>::CrossReturnType
+PartialRedux<ExpressionType,Direction>::cross(const MatrixBase<OtherDerived>& other) const
+{
+ EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
+ EIGEN_STATIC_ASSERT((ei_is_same_type<Scalar, typename OtherDerived::Scalar>::ret),
+ YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
+
+ CrossReturnType res(_expression().rows(),_expression().cols());
+ if(Direction==Vertical)
+ {
+ ei_assert(CrossReturnType::RowsAtCompileTime==3 && "the matrix must have exactly 3 rows");
+ res.row(0) = _expression().row(1) * other.coeff(2) - _expression().row(2) * other.coeff(1);
+ res.row(1) = _expression().row(2) * other.coeff(0) - _expression().row(0) * other.coeff(2);
+ res.row(2) = _expression().row(0) * other.coeff(1) - _expression().row(1) * other.coeff(0);
+ }
+ else
+ {
+ ei_assert(CrossReturnType::ColsAtCompileTime==3 && "the matrix must have exactly 3 columns");
+ res.col(0) = _expression().col(1) * other.coeff(2) - _expression().col(2) * other.coeff(1);
+ res.col(1) = _expression().col(2) * other.coeff(0) - _expression().col(0) * other.coeff(2);
+ res.col(2) = _expression().col(0) * other.coeff(1) - _expression().col(1) * other.coeff(0);
+ }
+ return res;
+}
+
template<typename Derived, int Size = Derived::SizeAtCompileTime>
struct ei_unitOrthogonal_selector
{
diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h
index e72ce814f..0305fe176 100644
--- a/Eigen/src/Geometry/Quaternion.h
+++ b/Eigen/src/Geometry/Quaternion.h
@@ -345,7 +345,6 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
{
Vector3 v0 = a.normalized();
Vector3 v1 = b.normalized();
- Vector3 axis = v0.cross(v1);
Scalar c = v0.dot(v1);
// if dot == 1, vectors are the same
@@ -353,7 +352,17 @@ inline Quaternion<Scalar>& Quaternion<Scalar>::setFromTwoVectors(const MatrixBas
{
// set to identity
this->w() = 1; this->vec().setZero();
+ return *this;
}
+ // if dot == -1, vectors are opposites
+ if (ei_isApprox(c,Scalar(-1)))
+ {
+ this->vec() = v0.unitOrthogonal();
+ this->w() = 0;
+ return *this;
+ }
+
+ Vector3 axis = v0.cross(v1);
Scalar s = ei_sqrt((Scalar(1)+c)*Scalar(2));
Scalar invs = Scalar(1)/s;
this->vec() = axis * invs;
diff --git a/demos/opengl/quaternion_demo.cpp b/demos/opengl/quaternion_demo.cpp
index 31aeb4d73..f7ff0b77e 100644
--- a/demos/opengl/quaternion_demo.cpp
+++ b/demos/opengl/quaternion_demo.cpp
@@ -55,7 +55,7 @@ class FancySpheres
mCenters.push_back(Vector3f::Zero());
parents.push_back(-1);
mRadii.push_back(radius);
-
+
// generate level 1 using icosphere vertices
radius *= 0.45;
{
@@ -89,7 +89,7 @@ class FancySpheres
Vector3f ax1 = ax0.unitOrthogonal();
Quaternionf q;
q.setFromTwoVectors(Vector3f::UnitZ(), ax0);
- Transform3f t = Translation3f(c) * q * Scaling3f(mRadii[i]+radius);
+ Transform3f t = Translation3f(c) * q * Scaling(mRadii[i]+radius);
for (int j=0; j<5; ++j)
{
Vector3f newC = c + ( (AngleAxisf(angles[j*2+1], ax0)
@@ -103,14 +103,14 @@ class FancySpheres
start = end;
}
}
-
+
void draw()
{
int end = mCenters.size();
glEnable(GL_NORMALIZE);
for (int i=0; i<end; ++i)
{
- Transform3f t = Translation3f(mCenters[i]) * Scaling3f(mRadii[i]);
+ Transform3f t = Translation3f(mCenters[i]) * Scaling(mRadii[i]);
gpu.pushMatrix(GL_MODELVIEW);
gpu.multMatrix(t.matrix(),GL_MODELVIEW);
mIcoSphere.draw(2);
@@ -135,7 +135,7 @@ template<typename T> T lerp(float t, const T& a, const T& b)
template<> Quaternionf lerp(float t, const Quaternionf& a, const Quaternionf& b)
{ return a.slerp(t,b); }
-// linear interpolation of a frame using the type OrientationType
+// linear interpolation of a frame using the type OrientationType
// to perform the interpolation of the orientations
template<typename OrientationType>
inline static Frame lerpFrame(float alpha, const Frame& a, const Frame& b)
@@ -171,7 +171,7 @@ public:
Matrix3 m = q.toRotationMatrix();
return *this = m;
}
-
+
EulerAngles& operator=(const Matrix3& m)
{
// mat = cy*cz -cy*sz sy
@@ -240,7 +240,7 @@ void RenderingWidget::grabFrame(void)
void RenderingWidget::drawScene()
{
static FancySpheres sFancySpheres;
- float length = 200;
+ float length = 50;
gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitX(), Color(1,0,0,1));
gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitY(), Color(0,1,0,1));
gpu.drawVector(Vector3f::Zero(), length*Vector3f::UnitZ(), Color(0,0,1,1));
@@ -262,12 +262,60 @@ void RenderingWidget::drawScene()
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, Vector4f(1, 1, 1, 1).data());
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64);
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- glEnable(GL_LIGHT1);
-
+// glEnable(GL_LIGHTING);
+// glEnable(GL_LIGHT0);
+// glEnable(GL_LIGHT1);
+
glColor3f(0.4, 0.7, 0.4);
- sFancySpheres.draw();
+
+ {IcoSphere s(5);
+ float length = 6;
+// const std::vector<int>& indices = s.indices(2);
+ for (unsigned int i=0; i<s.vertices().size() ; ++i)
+ {
+ Vector3f n = s.vertices()[i].normalized();
+ Vector3f p = n*100;
+
+ int i,j;
+ float minc = n.minCoeff(&i);
+ float maxc = n.maxCoeff(&j);
+ Vector3f o = n;
+ o[i] = -n[j];
+ o[j] = n[i];
+
+ //Vector3f u = n.unitOrthogonal().normalized();
+ Vector3f u = n.cross(o).normalized();
+ Vector3f v = n.cross(u).normalized();
+ gpu.drawVector(p, length*u, Color(1,0,0,1));
+ gpu.drawVector(p, length*v, Color(0,1,0,1));
+// gpu.drawVector(p, length*n, Color(0,0,1,1));
+ }}
+
+ for(;;)
+ {
+ Vector3f n = Vector3f::Random().normalized();
+// Vector3f p = n*100;
+ //Vector3f u = n.unitOrthogonal().normalized();
+// int i,j;
+// float minc = n.minCoeff(&i);
+// float maxc = n.maxCoeff(&j);
+
+// Vector3f o = n;
+// o[i] = -n[j];
+// o[j] = n[i];
+ Vector3f o = Vector3f(-n.y(),n.z(),n.x()).normalized();
+ Vector3f u = n.cross(o).normalized();
+
+ float d = ei_abs(o.dot(n));
+
+ if (d>0.9999)
+ std::cout << d << " " << n.transpose() << "\n";
+
+// Vector3f v = n.cross(u).normalized();
+ }
+
+
+// sFancySpheres.draw();
// glVertexPointer(3, GL_FLOAT, 0, mVertices[0].data());
// glNormalPointer(GL_FLOAT, 0, mNormals[0].data());
// glEnableClientState(GL_VERTEX_ARRAY);
@@ -275,7 +323,7 @@ void RenderingWidget::drawScene()
// glDrawArrays(GL_TRIANGLES, 0, mVertices.size());
// glDisableClientState(GL_VERTEX_ARRAY);
// glDisableClientState(GL_NORMAL_ARRAY);
-
+
glDisable(GL_LIGHTING);
}
@@ -318,7 +366,7 @@ void RenderingWidget::animate()
currentFrame.orientation = currentFrame.orientation.inverse();
currentFrame.position = - (currentFrame.orientation * currentFrame.position);
mCamera.setFrame(currentFrame);
-
+
updateGL();
}
@@ -542,7 +590,7 @@ void RenderingWidget::resetCamera()
// put the camera at that time step:
aux1 = aux0.lerp(duration/2,mInitFrame);
- // and make it look at teh target again
+ // and make it look at the target again
aux1.orientation = aux1.orientation.inverse();
aux1.position = - (aux1.orientation * aux1.position);
mCamera.setFrame(aux1);
@@ -647,6 +695,17 @@ QuaternionDemo::QuaternionDemo()
int main(int argc, char *argv[])
{
+ std::cout << "Navigation:\n";
+ std::cout << " left button: rotate around the target\n";
+ std::cout << " middle button: zoom\n";
+ std::cout << " left button + ctrl quake rotate (rotate around camera position)\n";
+ std::cout << " middle button + ctrl walk (progress along camera's z direction)\n";
+ std::cout << " left button: pan (translate in the XY camera's plane)\n\n";
+ std::cout << "R : move the camera to initial position\n";
+ std::cout << "A : start/stop animation\n";
+ std::cout << "C : clear the animation\n";
+ std::cout << "G : add a key frame\n";
+
QApplication app(argc, argv);
QuaternionDemo demo;
demo.resize(600,500);
diff --git a/doc/D01_StlContainers.dox b/doc/D01_StlContainers.dox
index 9a2586023..845dea156 100644
--- a/doc/D01_StlContainers.dox
+++ b/doc/D01_StlContainers.dox
@@ -14,7 +14,7 @@ Using STL containers on \ref FixedSizeVectorizable "fixed-size vectorizable Eige
\li A 16-byte-aligned allocator must be used. Eigen does provide one ready for use: aligned_allocator.
\li If you want to use the std::vector container, you need to \#include <Eigen/StdVector>.
-These issues arise only with \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types". For other Eigen types, such as Vector3f or MatrixXd, no special care is needed when using STL containers.
+These issues arise only with \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types" and \ref StructHavingEigenMembers "structures having such Eigen objects as member". For other Eigen types, such as Vector3f or MatrixXd, no special care is needed when using STL containers.
\section allocator Using an aligned allocator
@@ -32,7 +32,7 @@ Note that here, the 3rd parameter "std::less<int>" is just the default value, we
\section vector The case of std::vector
-The situation with std::vector was even worse (explanation below) so we had to specialize it for Eigen types. The upside is that our specialization takes care of specifying the aligned allocator, so you don't need to worry about it. All you need to do is to \#include <Eigen/StdVector>.
+The situation with std::vector was even worse (explanation below) so we had to specialize it for Eigen types. The upside is that our specialization takes care of specifying the aligned allocator, so you don't need to worry about it. All you need to do is to \#include <Eigen/StdVector> instead of (or before) \#include <vector>.
So as soon as you have
\code
diff --git a/doc/D11_UnalignedArrayAssert.dox b/doc/D11_UnalignedArrayAssert.dox
index a5ad32de9..0f522b7b3 100644
--- a/doc/D11_UnalignedArrayAssert.dox
+++ b/doc/D11_UnalignedArrayAssert.dox
@@ -50,7 +50,7 @@ std::map<int, Eigen::Matrix2f> my_map;
then you need to read this separate page: \ref StlContainers "Using STL Containers with Eigen".
-Note that here, Eigen::Matrix2f is only used as an example, more generally the issue arises for all \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types".
+Note that here, Eigen::Matrix2f is only used as an example, more generally the issue arises for all \ref FixedSizeVectorizable "fixed-size vectorizable Eigen types" and \ref StructHavingEigenMembers "structures having such Eigen objects as member".
\section c3 Cause 3: Passing Eigen objects by value
diff --git a/doc/I05_FixedSizeVectorizable.dox b/doc/I05_FixedSizeVectorizable.dox
index 16f0c7f50..9ec36898e 100644
--- a/doc/I05_FixedSizeVectorizable.dox
+++ b/doc/I05_FixedSizeVectorizable.dox
@@ -31,7 +31,7 @@ Fixed-size objects are typically very small, which means that we want to handle
Now, vectorization (both SSE and AltiVec) works with 128-bit packets. Moreover, for performance reasons, these packets need to be have 128-bit alignment.
-So it turns out that the only way that fixed-size Eigen objects can be vectorized, is if their size is a multiple of 128 bits, or 16 bytes. Eigen will then request 16-byte alignment for these object, and henceforth rely on these objects being aligned so no runtime check for alignment is performed.
+So it turns out that the only way that fixed-size Eigen objects can be vectorized, is if their size is a multiple of 128 bits, or 16 bytes. Eigen will then request 16-byte alignment for these objects, and henceforth rely on these objects being aligned so no runtime check for alignment is performed.
*/
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 4046cf533..35cfee344 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -129,10 +129,13 @@ ei_add_test(inverse)
ei_add_test(qr)
ei_add_test(eigensolver " " "${GSL_LIBRARIES}")
ei_add_test(svd)
-ei_add_test(geometry)
-ei_add_test(hyperplane)
-ei_add_test(parametrizedline)
-ei_add_test(alignedbox)
+ei_add_test(geo_orthomethods)
+ei_add_test(geo_quaternion)
+ei_add_test(geo_transformations)
+ei_add_test(geo_eulerangles)
+ei_add_test(geo_hyperplane)
+ei_add_test(geo_parametrizedline)
+ei_add_test(geo_alignedbox)
ei_add_test(regression)
ei_add_test(stdvector)
ei_add_test(resize)
diff --git a/test/alignedbox.cpp b/test/geo_alignedbox.cpp
index 53d61b62d..1ccc0da14 100644
--- a/test/alignedbox.cpp
+++ b/test/geo_alignedbox.cpp
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -65,7 +65,7 @@ template<typename BoxType> void alignedbox(const BoxType& _box)
VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),b0);
}
-void test_alignedbox()
+void test_geo_alignedbox()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( alignedbox(AlignedBox<float,2>()) );
diff --git a/test/geo_eulerangles.cpp b/test/geo_eulerangles.cpp
new file mode 100644
index 000000000..fbb51cd83
--- /dev/null
+++ b/test/geo_eulerangles.cpp
@@ -0,0 +1,70 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen 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 Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/SVD>
+
+template<typename Scalar> void eulerangles(void)
+{
+ typedef Matrix<Scalar,3,3> Matrix3;
+ typedef Matrix<Scalar,3,1> Vector3;
+ typedef Quaternion<Scalar> Quaternionx;
+ typedef AngleAxis<Scalar> AngleAxisx;
+
+ Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+ Quaternionx q1;
+ q1 = AngleAxisx(a, Vector3::Random().normalized());
+ Matrix3 m;
+ m = q1;
+
+ #define VERIFY_EULER(I,J,K, X,Y,Z) { \
+ Vector3 ea = m.eulerAngles(I,J,K); \
+ Matrix3 m1 = Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z())); \
+ VERIFY_IS_APPROX(m, Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \
+ }
+ VERIFY_EULER(0,1,2, X,Y,Z);
+ VERIFY_EULER(0,1,0, X,Y,X);
+ VERIFY_EULER(0,2,1, X,Z,Y);
+ VERIFY_EULER(0,2,0, X,Z,X);
+
+ VERIFY_EULER(1,2,0, Y,Z,X);
+ VERIFY_EULER(1,2,1, Y,Z,Y);
+ VERIFY_EULER(1,0,2, Y,X,Z);
+ VERIFY_EULER(1,0,1, Y,X,Y);
+
+ VERIFY_EULER(2,0,1, Z,X,Y);
+ VERIFY_EULER(2,0,2, Z,X,Z);
+ VERIFY_EULER(2,1,0, Z,Y,X);
+ VERIFY_EULER(2,1,2, Z,Y,Z);
+}
+
+void test_geo_eulerangles()
+{
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST( eulerangles<float>() );
+ CALL_SUBTEST( eulerangles<double>() );
+ }
+}
diff --git a/test/hyperplane.cpp b/test/geo_hyperplane.cpp
index fdb32f75c..de1ee8ba0 100644
--- a/test/hyperplane.cpp
+++ b/test/geo_hyperplane.cpp
@@ -127,7 +127,7 @@ template<typename Scalar> void lines()
}
}
-void test_hyperplane()
+void test_geo_hyperplane()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( hyperplane(Hyperplane<float,2>()) );
diff --git a/test/geo_orthomethods.cpp b/test/geo_orthomethods.cpp
new file mode 100644
index 000000000..08110e6d8
--- /dev/null
+++ b/test/geo_orthomethods.cpp
@@ -0,0 +1,109 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen 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 Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/SVD>
+
+/* this test covers the following files:
+ Geometry/OrthoMethods.h
+*/
+
+template<typename Scalar> void orthomethods_3()
+{
+ typedef Matrix<Scalar,3,3> Matrix3;
+ typedef Matrix<Scalar,3,1> Vector3;
+
+ Vector3 v0 = Vector3::Random(),
+ v1 = Vector3::Random(),
+ v2 = Vector3::Random();
+
+ // cross product
+ VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1));
+ Matrix3 mat3;
+ mat3 << v0.normalized(),
+ (v0.cross(v1)).normalized(),
+ (v0.cross(v1).cross(v0)).normalized();
+ VERIFY(mat3.isUnitary());
+
+
+ // colwise/rowwise cross product
+ mat3.setRandom();
+ Vector3 vec3 = Vector3::Random();
+ Matrix3 mcross;
+ int i = ei_random<int>(0,2);
+ mcross = mat3.colwise().cross(vec3);
+ VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
+ mcross = mat3.rowwise().cross(vec3);
+ VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
+
+}
+
+template<typename Scalar, int Size> void orthomethods(int size=Size)
+{
+ typedef Matrix<Scalar,Size,1> VectorType;
+ typedef Matrix<Scalar,3,Size> Matrix3N;
+ typedef Matrix<Scalar,Size,3> MatrixN3;
+ typedef Matrix<Scalar,3,1> Vector3;
+
+ VectorType v0 = VectorType::Random(size),
+ v1 = VectorType::Random(size),
+ v2 = VectorType::Random(size);
+
+ // unitOrthogonal
+ VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
+ VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1));
+
+ // colwise/rowwise cross product
+ Vector3 vec3 = Vector3::Random();
+ int i = ei_random<int>(0,size-1);
+
+ Matrix3N mat3N(3,size), mcross3N(3,size);
+ mat3N.setRandom();
+ mcross3N = mat3N.colwise().cross(vec3);
+ VERIFY_IS_APPROX(mcross3N.col(i), mat3N.col(i).cross(vec3));
+
+ MatrixN3 matN3(size,3), mcrossN3(size,3);
+ matN3.setRandom();
+ mcrossN3 = matN3.rowwise().cross(vec3);
+ VERIFY_IS_APPROX(mcrossN3.row(i), matN3.row(i).cross(vec3));
+
+}
+
+void test_geo_orthomethods()
+{
+ for(int i = 0; i < g_repeat; i++) {
+ CALL_SUBTEST( orthomethods_3<float>() );
+ CALL_SUBTEST( orthomethods_3<double>() );
+ CALL_SUBTEST( (orthomethods<float,2>()) );
+ CALL_SUBTEST( (orthomethods<double,2>()) );
+ CALL_SUBTEST( (orthomethods<float,3>()) );
+ CALL_SUBTEST( (orthomethods<double,3>()) );
+ CALL_SUBTEST( (orthomethods<float,7>()) );
+ CALL_SUBTEST( (orthomethods<double,8>()) );
+ CALL_SUBTEST( (orthomethods<float,Dynamic>(36)) );
+ CALL_SUBTEST( (orthomethods<double,Dynamic>(35)) );
+ }
+}
diff --git a/test/parametrizedline.cpp b/test/geo_parametrizedline.cpp
index 4444432a6..ba4578a1c 100644
--- a/test/parametrizedline.cpp
+++ b/test/geo_parametrizedline.cpp
@@ -66,7 +66,7 @@ template<typename LineType> void parametrizedline(const LineType& _line)
VERIFY_IS_APPROX(hp1d.template cast<Scalar>(),l0);
}
-void test_parametrizedline()
+void test_geo_parametrizedline()
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST( parametrizedline(ParametrizedLine<float,2>()) );
diff --git a/test/geo_quaternion.cpp b/test/geo_quaternion.cpp
new file mode 100644
index 000000000..c9337c025
--- /dev/null
+++ b/test/geo_quaternion.cpp
@@ -0,0 +1,116 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra. Eigen itself is part of the KDE project.
+//
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
+//
+// Eigen is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 3 of the License, or (at your option) any later version.
+//
+// Alternatively, you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 2 of
+// the License, or (at your option) any later version.
+//
+// Eigen 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 Lesser General Public License or the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License and a copy of the GNU General Public License along with
+// Eigen. If not, see <http://www.gnu.org/licenses/>.
+
+#include "main.h"
+#include <Eigen/Geometry>
+#include <Eigen/LU>
+#include <Eigen/SVD>
+
+template<typename Scalar> void quaternion(void)
+{
+ /* this test covers the following files:
+ Quaternion.h
+ */
+
+ typedef Matrix<Scalar,3,3> Matrix3;
+ typedef Matrix<Scalar,3,1> Vector3;
+ typedef Quaternion<Scalar> Quaternionx;
+ typedef AngleAxis<Scalar> AngleAxisx;
+
+ Scalar largeEps = test_precision<Scalar>();
+ if (ei_is_same_type<Scalar,float>::ret)
+ largeEps = 1e-3f;
+
+ Scalar eps = ei_random<Scalar>() * 1e-2;
+
+ Vector3 v0 = Vector3::Random(),
+ v1 = Vector3::Random(),
+ v2 = Vector3::Random(),
+ v3 = Vector3::Random();
+
+ Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
+
+ // Quaternion: Identity(), setIdentity();
+ Quaternionx q1, q2;
+ q2.setIdentity();
+ VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
+ q1.coeffs().setRandom();
+ VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
+
+ q1 = AngleAxisx(a, v0.normalized());
+ q2 = AngleAxisx(a, v1.normalized());
+
+ // angular distance
+ Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
+ if (refangle>Scalar(M_PI))
+ refangle = Scalar(2)*Scalar(M_PI) - refangle;
+
+ if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
+ {
+ VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
+ }
+
+ // rotation matrix conversion
+ VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2);
+ VERIFY_IS_APPROX(q1 * q2 * v2,
+ q1.toRotationMatrix() * q2.toRotationMatrix() * v2);
+
+ VERIFY( (q2*q1).isApprox(q1*q2, largeEps)
+ || !(q2 * q1 * v2).isApprox(q1.toRotationMatrix() * q2.toRotationMatrix() * v2));
+
+ q2 = q1.toRotationMatrix();
+ VERIFY_IS_APPROX(q1*v1,q2*v1);
+
+
+ // angle-axis conversion
+ AngleAxisx aa = q1;
+ VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
+ VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
+
+ // from two vector creation
+ VERIFY_IS_APPROX( v2.normalized(),(q2.setFromTwoVectors(v1, v2)*v1).normalized());
+ VERIFY_IS_APPROX( v1.normalized(),(q2.setFromTwoVectors(v1, v1)*v1).normalized());
+ VERIFY_IS_APPROX(-v1.normalized(),(q2.setFromTwoVectors(v1,-v1)*v1).normalized());
+ v3 = v1.cwise()+eps;
+ VERIFY_IS_APPROX( v3.normalized(),(q2.setFromTwoVectors(v1, v3)*v1).normalized());
+ VERIFY_IS_APPROX(-v3.normalized(),(q2.setFromTwoVectors(v1,-v3)*v1).normalized());
+
+ // inverse and conjugate
+ VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
+ VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
+
+ // test casting
+ Quaternion<float> q1f = q1.template cast<float>();
+ VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1);
+ Quaternion<double> q1d = q1.template cast<double>();
+ VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1);
+}
+
+void test_geo_quaternion()
+{
+ for(int i = 0; i < g_repeat; i++) {
+// CALL_SUBTEST( quaternion<float>() );
+ CALL_SUBTEST( quaternion<double>() );
+ }
+}
diff --git a/test/geometry.cpp b/test/geo_transformations.cpp
index b80f9a4c4..35ecdb47b 100644
--- a/test/geometry.cpp
+++ b/test/geo_transformations.cpp
@@ -1,7 +1,7 @@
// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
-// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
+// Copyright (C) 2008-2009 Gael Guennebaud <g.gael@free.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -27,7 +27,7 @@
#include <Eigen/LU>
#include <Eigen/SVD>
-template<typename Scalar> void geometry(void)
+template<typename Scalar> void transformations(void)
{
/* this test covers the following files:
Cross.h Quaternion.h, Transform.cpp
@@ -56,32 +56,10 @@ template<typename Scalar> void geometry(void)
v1 = Vector3::Random(),
v2 = Vector3::Random();
Vector2 u0 = Vector2::Random();
- Matrix3 matrot1;
+ Matrix3 matrot1, m;
Scalar a = ei_random<Scalar>(-Scalar(M_PI), Scalar(M_PI));
- // cross product
- VERIFY_IS_MUCH_SMALLER_THAN(v1.cross(v2).dot(v1), Scalar(1));
- Matrix3 m;
- m << v0.normalized(),
- (v0.cross(v1)).normalized(),
- (v0.cross(v1).cross(v0)).normalized();
- VERIFY(m.isUnitary());
-
- // Quaternion: Identity(), setIdentity();
- Quaternionx q1, q2;
- q2.setIdentity();
- VERIFY_IS_APPROX(Quaternionx(Quaternionx::Identity()).coeffs(), q2.coeffs());
- q1.coeffs().setRandom();
- VERIFY_IS_APPROX(q1.coeffs(), (q1*q2).coeffs());
-
- // unitOrthogonal
- VERIFY_IS_MUCH_SMALLER_THAN(u0.unitOrthogonal().dot(u0), Scalar(1));
- VERIFY_IS_MUCH_SMALLER_THAN(v0.unitOrthogonal().dot(v0), Scalar(1));
- VERIFY_IS_APPROX(u0.unitOrthogonal().norm(), Scalar(1));
- VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1));
-
-
VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0);
VERIFY_IS_APPROX(-v0, AngleAxisx(Scalar(M_PI), v0.unitOrthogonal()) * v0);
VERIFY_IS_APPROX(ei_cos(a)*v0.squaredNorm(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0));
@@ -89,30 +67,11 @@ template<typename Scalar> void geometry(void)
VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized()));
VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m);
+ Quaternionx q1, q2;
q1 = AngleAxisx(a, v0.normalized());
q2 = AngleAxisx(a, v1.normalized());
- // angular distance
- Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle());
- if (refangle>Scalar(M_PI))
- refangle = Scalar(2)*Scalar(M_PI) - refangle;
-
- if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
- {
- VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps));
- }
-
// rotation matrix conversion
- VERIFY_IS_APPROX(q1 * v2, q1.toRotationMatrix() * v2);
- VERIFY_IS_APPROX(q1 * q2 * v2,
- q1.toRotationMatrix() * q2.toRotationMatrix() * v2);
-
- VERIFY( (q2*q1).isApprox(q1*q2, largeEps) || !(q2 * q1 * v2).isApprox(
- q1.toRotationMatrix() * q2.toRotationMatrix() * v2));
-
- q2 = q1.toRotationMatrix();
- VERIFY_IS_APPROX(q1*v1,q2*v1);
-
matrot1 = AngleAxisx(Scalar(0.1), Vector3::UnitX())
* AngleAxisx(Scalar(0.2), Vector3::UnitY())
* AngleAxisx(Scalar(0.3), Vector3::UnitZ());
@@ -126,14 +85,6 @@ template<typename Scalar> void geometry(void)
VERIFY_IS_APPROX(q1 * v1, Quaternionx(aa) * v1);
VERIFY_IS_NOT_APPROX(q1 * v1, Quaternionx(AngleAxisx(aa.angle()*2,aa.axis())) * v1);
- // from two vector creation
- VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
- VERIFY_IS_APPROX(v2.normalized(),(q2.setFromTwoVectors(v1,v2)*v1).normalized());
-
- // inverse and conjugate
- VERIFY_IS_APPROX(q1 * (q1.inverse() * v1), v1);
- VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1);
-
// AngleAxis
VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(),
Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix());
@@ -382,11 +333,6 @@ template<typename Scalar> void geometry(void)
DiagonalMatrix<double,3> sc1d; sc1d = (sc1.template cast<double>());
VERIFY_IS_APPROX(sc1d.template cast<Scalar>(),sc1);
- Quaternion<float> q1f = q1.template cast<float>();
- VERIFY_IS_APPROX(q1f.template cast<Scalar>(),q1);
- Quaternion<double> q1d = q1.template cast<double>();
- VERIFY_IS_APPROX(q1d.template cast<Scalar>(),q1);
-
AngleAxis<float> aa1f = aa1.template cast<float>();
VERIFY_IS_APPROX(aa1f.template cast<Scalar>(),aa1);
AngleAxis<double> aa1d = aa1.template cast<double>();
@@ -397,47 +343,12 @@ template<typename Scalar> void geometry(void)
VERIFY_IS_APPROX(r2d1f.template cast<Scalar>(),r2d1);
Rotation2D<double> r2d1d = r2d1.template cast<double>();
VERIFY_IS_APPROX(r2d1d.template cast<Scalar>(),r2d1);
-
- m = q1;
-// m.col(1) = Vector3(0,ei_random<Scalar>(),ei_random<Scalar>()).normalized();
-// m.col(0) = Vector3(-1,0,0).normalized();
-// m.col(2) = m.col(0).cross(m.col(1));
- #define VERIFY_EULER(I,J,K, X,Y,Z) { \
- Vector3 ea = m.eulerAngles(I,J,K); \
- Matrix3 m1 = Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z())); \
- VERIFY_IS_APPROX(m, Matrix3(AngleAxisx(ea[0], Vector3::Unit##X()) * AngleAxisx(ea[1], Vector3::Unit##Y()) * AngleAxisx(ea[2], Vector3::Unit##Z()))); \
- }
- VERIFY_EULER(0,1,2, X,Y,Z);
- VERIFY_EULER(0,1,0, X,Y,X);
- VERIFY_EULER(0,2,1, X,Z,Y);
- VERIFY_EULER(0,2,0, X,Z,X);
-
- VERIFY_EULER(1,2,0, Y,Z,X);
- VERIFY_EULER(1,2,1, Y,Z,Y);
- VERIFY_EULER(1,0,2, Y,X,Z);
- VERIFY_EULER(1,0,1, Y,X,Y);
-
- VERIFY_EULER(2,0,1, Z,X,Y);
- VERIFY_EULER(2,0,2, Z,X,Z);
- VERIFY_EULER(2,1,0, Z,Y,X);
- VERIFY_EULER(2,1,2, Z,Y,Z);
-
- // colwise/rowwise cross product
- mat3.setRandom();
- Vector3 vec3 = Vector3::Random();
- Matrix3 mcross;
- int i = ei_random<int>(0,2);
- mcross = mat3.colwise().cross(vec3);
- VERIFY_IS_APPROX(mcross.col(i), mat3.col(i).cross(vec3));
- mcross = mat3.rowwise().cross(vec3);
- VERIFY_IS_APPROX(mcross.row(i), mat3.row(i).cross(vec3));
-
}
-void test_geometry()
+void test_geo_transformations()
{
for(int i = 0; i < g_repeat; i++) {
- CALL_SUBTEST( geometry<float>() );
- CALL_SUBTEST( geometry<double>() );
+ CALL_SUBTEST( transformations<float>() );
+ CALL_SUBTEST( transformations<double>() );
}
}
diff --git a/test/sparse_product.cpp b/test/sparse_product.cpp
index d2c3b1c98..3a0356f00 100644
--- a/test/sparse_product.cpp
+++ b/test/sparse_product.cpp
@@ -34,7 +34,6 @@ template<typename SparseMatrixType> void sparse_product(const SparseMatrixType&
double density = std::max(8./(rows*cols), 0.01);
typedef Matrix<Scalar,Dynamic,Dynamic> DenseMatrix;
typedef Matrix<Scalar,Dynamic,1> DenseVector;
- Scalar eps = 1e-6;
// test matrix-matrix product
{