diff --git a/Eigen/src/Geometry/AngleAxis.h b/Eigen/src/Geometry/AngleAxis.h index 85d7b69b0..37dee5c76 100644 --- a/Eigen/src/Geometry/AngleAxis.h +++ b/Eigen/src/Geometry/AngleAxis.h @@ -149,6 +149,13 @@ public: m_axis = other.axis().template cast(); m_angle = other.angle(); } + + /** \returns \c true if \c *this is approximately equal to \a other, within the precision + * determined by \a prec. + * + * \sa MatrixBase::isApprox() */ + bool isApprox(const AngleAxis& other, typename NumTraits::Real prec = precision()) const + { return m_axis.isApprox(other.m_axis, prec) && ei_isApprox(m_angle,other.m_angle, prec); } }; /** \ingroup GeometryModule diff --git a/Eigen/src/Geometry/Hyperplane.h b/Eigen/src/Geometry/Hyperplane.h index d3327a418..a45268f07 100644 --- a/Eigen/src/Geometry/Hyperplane.h +++ b/Eigen/src/Geometry/Hyperplane.h @@ -256,6 +256,13 @@ public: inline explicit Hyperplane(const Hyperplane& other) { m_coeffs = other.coeffs().template cast(); } + /** \returns \c true if \c *this is approximately equal to \a other, within the precision + * determined by \a prec. + * + * \sa MatrixBase::isApprox() */ + bool isApprox(const Hyperplane& other, typename NumTraits::Real prec = precision()) const + { return m_coeffs.isApprox(other.m_coeffs, prec); } + protected: Coefficients m_coeffs; diff --git a/Eigen/src/Geometry/ParametrizedLine.h b/Eigen/src/Geometry/ParametrizedLine.h index e7d336e62..80ce72dcd 100644 --- a/Eigen/src/Geometry/ParametrizedLine.h +++ b/Eigen/src/Geometry/ParametrizedLine.h @@ -122,6 +122,13 @@ public: m_direction = other.direction().template cast(); } + /** \returns \c true if \c *this is approximately equal to \a other, within the precision + * determined by \a prec. + * + * \sa MatrixBase::isApprox() */ + bool isApprox(const ParametrizedLine& other, typename NumTraits::Real prec = precision()) const + { return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); } + protected: VectorType m_origin, m_direction; diff --git a/Eigen/src/Geometry/Quaternion.h b/Eigen/src/Geometry/Quaternion.h index 688fac885..5b1b41d5e 100644 --- a/Eigen/src/Geometry/Quaternion.h +++ b/Eigen/src/Geometry/Quaternion.h @@ -207,9 +207,14 @@ public: /** Copy constructor with scalar type conversion */ template inline explicit Quaternion(const Quaternion& other) - { - m_coeffs = other.coeffs().template cast(); - } + { m_coeffs = other.coeffs().template cast(); } + + /** \returns \c true if \c *this is approximately equal to \a other, within the precision + * determined by \a prec. + * + * \sa MatrixBase::isApprox() */ + bool isApprox(const Quaternion& other, typename NumTraits::Real prec = precision()) const + { return m_coeffs.isApprox(other.m_coeffs, prec); } }; diff --git a/Eigen/src/Geometry/Rotation2D.h b/Eigen/src/Geometry/Rotation2D.h index 8d9bb8b8f..aac7648b1 100644 --- a/Eigen/src/Geometry/Rotation2D.h +++ b/Eigen/src/Geometry/Rotation2D.h @@ -116,6 +116,13 @@ public: { m_angle = other.angle(); } + + /** \returns \c true if \c *this is approximately equal to \a other, within the precision + * determined by \a prec. + * + * \sa MatrixBase::isApprox() */ + bool isApprox(const Rotation2D& other, typename NumTraits::Real prec = precision()) const + { return ei_isApprox(m_angle,other.m_angle, prec); } }; /** \ingroup GeometryModule diff --git a/Eigen/src/Geometry/Scaling.h b/Eigen/src/Geometry/Scaling.h index 54e772e99..8e98bd58a 100644 --- a/Eigen/src/Geometry/Scaling.h +++ b/Eigen/src/Geometry/Scaling.h @@ -142,6 +142,13 @@ public: inline explicit Scaling(const Scaling& other) { m_coeffs = other.coeffs().template cast(); } + /** \returns \c true if \c *this is approximately equal to \a other, within the precision + * determined by \a prec. + * + * \sa MatrixBase::isApprox() */ + bool isApprox(const Scaling& other, typename NumTraits::Real prec = precision()) const + { return m_coeffs.isApprox(other.m_coeffs, prec); } + }; /** \addtogroup GeometryModule */ diff --git a/Eigen/src/Geometry/Transform.h b/Eigen/src/Geometry/Transform.h index 389c61f2c..a0c07e405 100644 --- a/Eigen/src/Geometry/Transform.h +++ b/Eigen/src/Geometry/Transform.h @@ -260,6 +260,13 @@ public: inline explicit Transform(const Transform& other) { m_matrix = other.matrix().template cast(); } + /** \returns \c true if \c *this is approximately equal to \a other, within the precision + * determined by \a prec. + * + * \sa MatrixBase::isApprox() */ + bool isApprox(const Transform& other, typename NumTraits::Real prec = precision()) const + { return m_matrix.isApprox(other.m_matrix, prec); } + protected: }; diff --git a/Eigen/src/Geometry/Translation.h b/Eigen/src/Geometry/Translation.h index c2e626112..8dce5dd4c 100644 --- a/Eigen/src/Geometry/Translation.h +++ b/Eigen/src/Geometry/Translation.h @@ -145,6 +145,13 @@ public: inline explicit Translation(const Translation& other) { m_coeffs = other.vector().template cast(); } + /** \returns \c true if \c *this is approximately equal to \a other, within the precision + * determined by \a prec. + * + * \sa MatrixBase::isApprox() */ + bool isApprox(const Translation& other, typename NumTraits::Real prec = precision()) const + { return m_coeffs.isApprox(other.m_coeffs, prec); } + }; /** \addtogroup GeometryModule */ diff --git a/test/geometry.cpp b/test/geometry.cpp index a87c8a2ad..24904e264 100644 --- a/test/geometry.cpp +++ b/test/geometry.cpp @@ -39,8 +39,8 @@ template void geometry(void) typedef Matrix Vector2; typedef Matrix Vector3; typedef Matrix Vector4; - typedef Quaternion Quaternion; - typedef AngleAxis AngleAxis; + typedef Quaternion Quaternionx; + typedef AngleAxis AngleAxisx; typedef Transform Transform2; typedef Transform Transform3; typedef Scaling Scaling2; @@ -52,7 +52,7 @@ template void geometry(void) if (ei_is_same_type::ret) largeEps = 1e-3f; - Quaternion q1, q2; + Quaternionx q1, q2; Vector3 v0 = Vector3::Random(), v1 = Vector3::Random(), v2 = Vector3::Random(); @@ -76,18 +76,18 @@ template void geometry(void) VERIFY_IS_APPROX(v0.unitOrthogonal().norm(), Scalar(1)); - VERIFY_IS_APPROX(v0, AngleAxis(a, v0.normalized()) * v0); - VERIFY_IS_APPROX(-v0, AngleAxis(M_PI, v0.unitOrthogonal()) * v0); - VERIFY_IS_APPROX(ei_cos(a)*v0.norm2(), v0.dot(AngleAxis(a, v0.unitOrthogonal()) * v0)); - m = AngleAxis(a, v0.normalized()).toRotationMatrix().adjoint(); - VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxis(a, v0.normalized())); - VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxis(a, v0.normalized()) * m); + VERIFY_IS_APPROX(v0, AngleAxisx(a, v0.normalized()) * v0); + VERIFY_IS_APPROX(-v0, AngleAxisx(M_PI, v0.unitOrthogonal()) * v0); + VERIFY_IS_APPROX(ei_cos(a)*v0.norm2(), v0.dot(AngleAxisx(a, v0.unitOrthogonal()) * v0)); + m = AngleAxisx(a, v0.normalized()).toRotationMatrix().adjoint(); + VERIFY_IS_APPROX(Matrix3::Identity(), m * AngleAxisx(a, v0.normalized())); + VERIFY_IS_APPROX(Matrix3::Identity(), AngleAxisx(a, v0.normalized()) * m); - q1 = AngleAxis(a, v0.normalized()); - q2 = AngleAxis(a, v1.normalized()); + q1 = AngleAxisx(a, v0.normalized()); + q2 = AngleAxisx(a, v1.normalized()); // angular distance - Scalar refangle = ei_abs(AngleAxis(q1.inverse()*q2).angle()); + Scalar refangle = ei_abs(AngleAxisx(q1.inverse()*q2).angle()); if (refangle>M_PI) refangle = 2.*M_PI - refangle; VERIFY(ei_isApprox(q1.angularDistance(q2), refangle, largeEps)); @@ -101,18 +101,18 @@ template void geometry(void) q2 = q1.toRotationMatrix(); VERIFY_IS_APPROX(q1*v1,q2*v1); - matrot1 = AngleAxis(0.1, Vector3::UnitX()) - * AngleAxis(0.2, Vector3::UnitY()) - * AngleAxis(0.3, Vector3::UnitZ()); + matrot1 = AngleAxisx(0.1, Vector3::UnitX()) + * AngleAxisx(0.2, Vector3::UnitY()) + * AngleAxisx(0.3, Vector3::UnitZ()); VERIFY_IS_APPROX(matrot1 * v1, - AngleAxis(0.1, Vector3(1,0,0)).toRotationMatrix() - * (AngleAxis(0.2, Vector3(0,1,0)).toRotationMatrix() - * (AngleAxis(0.3, Vector3(0,0,1)).toRotationMatrix() * v1))); + AngleAxisx(0.1, Vector3(1,0,0)).toRotationMatrix() + * (AngleAxisx(0.2, Vector3(0,1,0)).toRotationMatrix() + * (AngleAxisx(0.3, Vector3(0,0,1)).toRotationMatrix() * v1))); // angle-axis conversion - AngleAxis aa = q1; - VERIFY_IS_APPROX(q1 * v1, Quaternion(aa) * v1); - VERIFY_IS_NOT_APPROX(q1 * v1, Quaternion(AngleAxis(aa.angle()*2,aa.axis())) * v1); + 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()); @@ -123,21 +123,21 @@ template void geometry(void) VERIFY_IS_APPROX(q1 * (q1.conjugate() * v1), v1); // AngleAxis - VERIFY_IS_APPROX(AngleAxis(a,v1.normalized()).toRotationMatrix(), - Quaternion(AngleAxis(a,v1.normalized())).toRotationMatrix()); + VERIFY_IS_APPROX(AngleAxisx(a,v1.normalized()).toRotationMatrix(), + Quaternionx(AngleAxisx(a,v1.normalized())).toRotationMatrix()); - AngleAxis aa1; + AngleAxisx aa1; m = q1.toRotationMatrix(); aa1 = m; - VERIFY_IS_APPROX(AngleAxis(m).toRotationMatrix(), - Quaternion(m).toRotationMatrix()); + VERIFY_IS_APPROX(AngleAxisx(m).toRotationMatrix(), + Quaternionx(m).toRotationMatrix()); // Transform // TODO complete the tests ! a = 0; while (ei_abs(a)<0.1) a = ei_random(-0.4*M_PI, 0.4*M_PI); - q1 = AngleAxis(a, v0.normalized()); + q1 = AngleAxisx(a, v0.normalized()); Transform3 t0, t1, t2; t0.setIdentity(); t0.linear() = q1.toRotationMatrix(); @@ -171,7 +171,7 @@ template void geometry(void) t1.setIdentity(); t1.scale(v0).rotate(q1); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); - t0.setIdentity(); t0.scale(v0).rotate(AngleAxis(q1)); + t0.setIdentity(); t0.scale(v0).rotate(AngleAxisx(q1)); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); VERIFY_IS_APPROX(t0.scale(a).matrix(), t1.scale(Vector3::Constant(a)).matrix()); @@ -212,7 +212,7 @@ template void geometry(void) // scaling * mat and translation * mat t1 = Translation3(v0) * (Scaling3(v0) * Matrix3(q1)); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); - + t0.setIdentity(); t0.scale(v0).translate(v0).rotate(q1); // translation * mat and scaling * transformation @@ -226,7 +226,7 @@ template void geometry(void) t0.translate(v0); t1 = t1 * Translation3(v0); VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); - // translation * transformation + // translation * transformation t0.pretranslate(v0); t1 = Translation3(v0) * t1; VERIFY_IS_APPROX(t0.matrix(), t1.matrix()); @@ -284,6 +284,40 @@ template void geometry(void) t0.setIdentity(); t0.translate(v0).rotate(q1).scale(v1); VERIFY_IS_APPROX(t0.extractRotation(Affine) * v1, Matrix3(q1) * v1); + + // test casting + Transform t1f = t1.template cast(); + VERIFY_IS_APPROX(t1f.template cast(),t1); + Transform t1d = t1.template cast(); + VERIFY_IS_APPROX(t1d.template cast(),t1); + + Translation3 tr1(v0); + Translation tr1f = tr1.template cast(); + VERIFY_IS_APPROX(tr1f.template cast(),tr1); + Translation tr1d = tr1.template cast(); + VERIFY_IS_APPROX(tr1d.template cast(),tr1); + + Scaling3 sc1(v0); + Scaling sc1f = sc1.template cast(); + VERIFY_IS_APPROX(sc1f.template cast(),sc1); + Scaling sc1d = sc1.template cast(); + VERIFY_IS_APPROX(sc1d.template cast(),sc1); + + Quaternion q1f = q1.template cast(); + VERIFY_IS_APPROX(q1f.template cast(),q1); + Quaternion q1d = q1.template cast(); + VERIFY_IS_APPROX(q1d.template cast(),q1); + + AngleAxis aa1f = aa1.template cast(); + VERIFY_IS_APPROX(aa1f.template cast(),aa1); + AngleAxis aa1d = aa1.template cast(); + VERIFY_IS_APPROX(aa1d.template cast(),aa1); + + Rotation2D r2d1(ei_random()); + Rotation2D r2d1f = r2d1.template cast(); + VERIFY_IS_APPROX(r2d1f.template cast(),r2d1); + Rotation2D r2d1d = r2d1.template cast(); + VERIFY_IS_APPROX(r2d1d.template cast(),r2d1); } void test_geometry() diff --git a/test/hyperplane.cpp b/test/hyperplane.cpp index 0418c71b2..90312ca6e 100644 --- a/test/hyperplane.cpp +++ b/test/hyperplane.cpp @@ -46,7 +46,7 @@ template void hyperplane(const HyperplaneType& _plane) VectorType n0 = VectorType::Random(dim).normalized(); VectorType n1 = VectorType::Random(dim).normalized(); - + HyperplaneType pl0(n0, p0); HyperplaneType pl1(n1, p1); HyperplaneType pl2 = pl1; @@ -55,7 +55,7 @@ template void hyperplane(const HyperplaneType& _plane) Scalar s1 = ei_random(); VERIFY_IS_APPROX( n1.dot(n1), Scalar(1) ); - + VERIFY_IS_MUCH_SMALLER_THAN( pl0.absDistance(p0), Scalar(1) ); VERIFY_IS_APPROX( pl1.signedDistance(p1 + n1 * s0), s0 ); VERIFY_IS_MUCH_SMALLER_THAN( pl1.signedDistance(pl1.projection(p0)), Scalar(1) ); @@ -67,7 +67,7 @@ template void hyperplane(const HyperplaneType& _plane) MatrixType rot = MatrixType::Random(dim,dim).qr().matrixQ(); Scaling scaling(VectorType::Random()); Translation translation(VectorType::Random()); - + pl2 = pl1; VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot).absDistance(rot * p1), Scalar(1) ); pl2 = pl1; @@ -81,6 +81,14 @@ template void hyperplane(const HyperplaneType& _plane) VERIFY_IS_MUCH_SMALLER_THAN( pl2.transform(rot*translation,Isometry) .absDistance((rot*translation) * p1), Scalar(1) ); } + + // casting + const int Dim = HyperplaneType::AmbientDimAtCompileTime; + typedef typename GetDifferentType::type OtherScalar; + Hyperplane hp1f = pl1.template cast(); + VERIFY_IS_APPROX(hp1f.template cast(),pl1); + Hyperplane hp1d = pl1.template cast(); + VERIFY_IS_APPROX(hp1d.template cast(),pl1); } template void lines() diff --git a/test/main.h b/test/main.h index aeba4429d..b8507acef 100644 --- a/test/main.h +++ b/test/main.h @@ -209,11 +209,10 @@ inline bool test_ei_isMuchSmallerThan(const long double& a, const long double& b inline bool test_ei_isApproxOrLessThan(const long double& a, const long double& b) { return ei_isApproxOrLessThan(a, b, test_precision()); } -template -inline bool test_ei_isApprox(const MatrixBase& m1, - const MatrixBase& m2) +template +inline bool test_ei_isApprox(const Type1& a, const Type2& b) { - return m1.isApprox(m2, test_precision::Scalar>()); + return a.isApprox(b, test_precision()); } template @@ -232,6 +231,12 @@ inline bool test_ei_isMuchSmallerThan(const MatrixBase& m, } // end namespace Eigen +template struct GetDifferentType; + +template<> struct GetDifferentType { typedef double type; }; +template<> struct GetDifferentType { typedef float type; }; +template struct GetDifferentType > +{ typedef std::complex::type> type; }; // forward declaration of the main test function void EI_PP_CAT(test_,EIGEN_TEST_FUNC)(); diff --git a/test/parametrizedline.cpp b/test/parametrizedline.cpp index 82962807d..1031581da 100644 --- a/test/parametrizedline.cpp +++ b/test/parametrizedline.cpp @@ -45,7 +45,7 @@ template void parametrizedline(const LineType& _line) VectorType p1 = VectorType::Random(dim); VectorType d0 = VectorType::Random(dim).normalized(); - + LineType l0(p0, d0); Scalar s0 = ei_random(); @@ -55,7 +55,15 @@ template void parametrizedline(const LineType& _line) VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(p0+s0*d0), RealScalar(1) ); VERIFY_IS_APPROX( (l0.projection(p1)-p1).norm(), l0.distance(p1) ); VERIFY_IS_MUCH_SMALLER_THAN( l0.distance(l0.projection(p1)), RealScalar(1) ); - VERIFY_IS_APPROX( l0.distance((p0+s0*d0) + d0.unitOrthogonal() * s1), s1 ); + VERIFY_IS_APPROX( Scalar(l0.distance((p0+s0*d0) + d0.unitOrthogonal() * s1)), s1 ); + + // casting + const int Dim = LineType::AmbientDimAtCompileTime; + typedef typename GetDifferentType::type OtherScalar; + ParametrizedLine hp1f = l0.template cast(); + VERIFY_IS_APPROX(hp1f.template cast(),l0); + ParametrizedLine hp1d = l0.template cast(); + VERIFY_IS_APPROX(hp1d.template cast(),l0); } void test_parametrizedline()