feat(3rdparty): add eigen and ceres
This commit is contained in:
392
3rdparty/eigen3/Eigen/src/Geometry/AlignedBox.h
vendored
Normal file
392
3rdparty/eigen3/Eigen/src/Geometry/AlignedBox.h
vendored
Normal file
@@ -0,0 +1,392 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_ALIGNEDBOX_H
|
||||
#define EIGEN_ALIGNEDBOX_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
*
|
||||
* \class AlignedBox
|
||||
*
|
||||
* \brief An axis aligned box
|
||||
*
|
||||
* \tparam _Scalar the type of the scalar coefficients
|
||||
* \tparam _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
*
|
||||
* This class represents an axis aligned box as a pair of the minimal and maximal corners.
|
||||
* \warning The result of most methods is undefined when applied to an empty box. You can check for empty boxes using isEmpty().
|
||||
* \sa alignedboxtypedefs
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim>
|
||||
class AlignedBox
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
enum { AmbientDimAtCompileTime = _AmbientDim };
|
||||
typedef _Scalar Scalar;
|
||||
typedef NumTraits<Scalar> ScalarTraits;
|
||||
typedef DenseIndex Index;
|
||||
typedef typename ScalarTraits::Real RealScalar;
|
||||
typedef typename ScalarTraits::NonInteger NonInteger;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
|
||||
/** Define constants to name the corners of a 1D, 2D or 3D axis aligned bounding box */
|
||||
enum CornerType
|
||||
{
|
||||
/** 1D names @{ */
|
||||
Min=0, Max=1,
|
||||
/** @} */
|
||||
|
||||
/** Identifier for 2D corner @{ */
|
||||
BottomLeft=0, BottomRight=1,
|
||||
TopLeft=2, TopRight=3,
|
||||
/** @} */
|
||||
|
||||
/** Identifier for 3D corner @{ */
|
||||
BottomLeftFloor=0, BottomRightFloor=1,
|
||||
TopLeftFloor=2, TopRightFloor=3,
|
||||
BottomLeftCeil=4, BottomRightCeil=5,
|
||||
TopLeftCeil=6, TopRightCeil=7
|
||||
/** @} */
|
||||
};
|
||||
|
||||
|
||||
/** Default constructor initializing a null box. */
|
||||
inline AlignedBox()
|
||||
{ if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); }
|
||||
|
||||
/** Constructs a null box with \a _dim the dimension of the ambient space. */
|
||||
inline explicit AlignedBox(Index _dim) : m_min(_dim), m_max(_dim)
|
||||
{ setEmpty(); }
|
||||
|
||||
/** Constructs a box with extremities \a _min and \a _max.
|
||||
* \warning If either component of \a _min is larger than the same component of \a _max, the constructed box is empty. */
|
||||
template<typename OtherVectorType1, typename OtherVectorType2>
|
||||
inline AlignedBox(const OtherVectorType1& _min, const OtherVectorType2& _max) : m_min(_min), m_max(_max) {}
|
||||
|
||||
/** Constructs a box containing a single point \a p. */
|
||||
template<typename Derived>
|
||||
inline explicit AlignedBox(const MatrixBase<Derived>& p) : m_min(p), m_max(m_min)
|
||||
{ }
|
||||
|
||||
~AlignedBox() {}
|
||||
|
||||
/** \returns the dimension in which the box holds */
|
||||
inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size() : Index(AmbientDimAtCompileTime); }
|
||||
|
||||
/** \deprecated use isEmpty() */
|
||||
inline bool isNull() const { return isEmpty(); }
|
||||
|
||||
/** \deprecated use setEmpty() */
|
||||
inline void setNull() { setEmpty(); }
|
||||
|
||||
/** \returns true if the box is empty.
|
||||
* \sa setEmpty */
|
||||
inline bool isEmpty() const { return (m_min.array() > m_max.array()).any(); }
|
||||
|
||||
/** Makes \c *this an empty box.
|
||||
* \sa isEmpty */
|
||||
inline void setEmpty()
|
||||
{
|
||||
m_min.setConstant( ScalarTraits::highest() );
|
||||
m_max.setConstant( ScalarTraits::lowest() );
|
||||
}
|
||||
|
||||
/** \returns the minimal corner */
|
||||
inline const VectorType& (min)() const { return m_min; }
|
||||
/** \returns a non const reference to the minimal corner */
|
||||
inline VectorType& (min)() { return m_min; }
|
||||
/** \returns the maximal corner */
|
||||
inline const VectorType& (max)() const { return m_max; }
|
||||
/** \returns a non const reference to the maximal corner */
|
||||
inline VectorType& (max)() { return m_max; }
|
||||
|
||||
/** \returns the center of the box */
|
||||
inline const CwiseUnaryOp<internal::scalar_quotient1_op<Scalar>,
|
||||
const CwiseBinaryOp<internal::scalar_sum_op<Scalar>, const VectorType, const VectorType> >
|
||||
center() const
|
||||
{ return (m_min+m_max)/2; }
|
||||
|
||||
/** \returns the lengths of the sides of the bounding box.
|
||||
* Note that this function does not get the same
|
||||
* result for integral or floating scalar types: see
|
||||
*/
|
||||
inline const CwiseBinaryOp< internal::scalar_difference_op<Scalar>, const VectorType, const VectorType> sizes() const
|
||||
{ return m_max - m_min; }
|
||||
|
||||
/** \returns the volume of the bounding box */
|
||||
inline Scalar volume() const
|
||||
{ return sizes().prod(); }
|
||||
|
||||
/** \returns an expression for the bounding box diagonal vector
|
||||
* if the length of the diagonal is needed: diagonal().norm()
|
||||
* will provide it.
|
||||
*/
|
||||
inline CwiseBinaryOp< internal::scalar_difference_op<Scalar>, const VectorType, const VectorType> diagonal() const
|
||||
{ return sizes(); }
|
||||
|
||||
/** \returns the vertex of the bounding box at the corner defined by
|
||||
* the corner-id corner. It works only for a 1D, 2D or 3D bounding box.
|
||||
* For 1D bounding boxes corners are named by 2 enum constants:
|
||||
* BottomLeft and BottomRight.
|
||||
* For 2D bounding boxes, corners are named by 4 enum constants:
|
||||
* BottomLeft, BottomRight, TopLeft, TopRight.
|
||||
* For 3D bounding boxes, the following names are added:
|
||||
* BottomLeftCeil, BottomRightCeil, TopLeftCeil, TopRightCeil.
|
||||
*/
|
||||
inline VectorType corner(CornerType corner) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(_AmbientDim <= 3, THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE);
|
||||
|
||||
VectorType res;
|
||||
|
||||
Index mult = 1;
|
||||
for(Index d=0; d<dim(); ++d)
|
||||
{
|
||||
if( mult & corner ) res[d] = m_max[d];
|
||||
else res[d] = m_min[d];
|
||||
mult *= 2;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/** \returns a random point inside the bounding box sampled with
|
||||
* a uniform distribution */
|
||||
inline VectorType sample() const
|
||||
{
|
||||
VectorType r(dim());
|
||||
for(Index d=0; d<dim(); ++d)
|
||||
{
|
||||
if(!ScalarTraits::IsInteger)
|
||||
{
|
||||
r[d] = m_min[d] + (m_max[d]-m_min[d])
|
||||
* internal::random<Scalar>(Scalar(0), Scalar(1));
|
||||
}
|
||||
else
|
||||
r[d] = internal::random(m_min[d], m_max[d]);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/** \returns true if the point \a p is inside the box \c *this. */
|
||||
template<typename Derived>
|
||||
inline bool contains(const MatrixBase<Derived>& p) const
|
||||
{
|
||||
typename internal::nested<Derived,2>::type p_n(p.derived());
|
||||
return (m_min.array()<=p_n.array()).all() && (p_n.array()<=m_max.array()).all();
|
||||
}
|
||||
|
||||
/** \returns true if the box \a b is entirely inside the box \c *this. */
|
||||
inline bool contains(const AlignedBox& b) const
|
||||
{ return (m_min.array()<=(b.min)().array()).all() && ((b.max)().array()<=m_max.array()).all(); }
|
||||
|
||||
/** \returns true if the box \a b is intersecting the box \c *this.
|
||||
* \sa intersection, clamp */
|
||||
inline bool intersects(const AlignedBox& b) const
|
||||
{ return (m_min.array()<=(b.max)().array()).all() && ((b.min)().array()<=m_max.array()).all(); }
|
||||
|
||||
/** Extends \c *this such that it contains the point \a p and returns a reference to \c *this.
|
||||
* \sa extend(const AlignedBox&) */
|
||||
template<typename Derived>
|
||||
inline AlignedBox& extend(const MatrixBase<Derived>& p)
|
||||
{
|
||||
typename internal::nested<Derived,2>::type p_n(p.derived());
|
||||
m_min = m_min.cwiseMin(p_n);
|
||||
m_max = m_max.cwiseMax(p_n);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Extends \c *this such that it contains the box \a b and returns a reference to \c *this.
|
||||
* \sa merged, extend(const MatrixBase&) */
|
||||
inline AlignedBox& extend(const AlignedBox& b)
|
||||
{
|
||||
m_min = m_min.cwiseMin(b.m_min);
|
||||
m_max = m_max.cwiseMax(b.m_max);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Clamps \c *this by the box \a b and returns a reference to \c *this.
|
||||
* \note If the boxes don't intersect, the resulting box is empty.
|
||||
* \sa intersection(), intersects() */
|
||||
inline AlignedBox& clamp(const AlignedBox& b)
|
||||
{
|
||||
m_min = m_min.cwiseMax(b.m_min);
|
||||
m_max = m_max.cwiseMin(b.m_max);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Returns an AlignedBox that is the intersection of \a b and \c *this
|
||||
* \note If the boxes don't intersect, the resulting box is empty.
|
||||
* \sa intersects(), clamp, contains() */
|
||||
inline AlignedBox intersection(const AlignedBox& b) const
|
||||
{return AlignedBox(m_min.cwiseMax(b.m_min), m_max.cwiseMin(b.m_max)); }
|
||||
|
||||
/** Returns an AlignedBox that is the union of \a b and \c *this.
|
||||
* \note Merging with an empty box may result in a box bigger than \c *this.
|
||||
* \sa extend(const AlignedBox&) */
|
||||
inline AlignedBox merged(const AlignedBox& b) const
|
||||
{ return AlignedBox(m_min.cwiseMin(b.m_min), m_max.cwiseMax(b.m_max)); }
|
||||
|
||||
/** Translate \c *this by the vector \a t and returns a reference to \c *this. */
|
||||
template<typename Derived>
|
||||
inline AlignedBox& translate(const MatrixBase<Derived>& a_t)
|
||||
{
|
||||
const typename internal::nested<Derived,2>::type t(a_t.derived());
|
||||
m_min += t;
|
||||
m_max += t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns the squared distance between the point \a p and the box \c *this,
|
||||
* and zero if \a p is inside the box.
|
||||
* \sa exteriorDistance(const MatrixBase&), squaredExteriorDistance(const AlignedBox&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Scalar squaredExteriorDistance(const MatrixBase<Derived>& p) const;
|
||||
|
||||
/** \returns the squared distance between the boxes \a b and \c *this,
|
||||
* and zero if the boxes intersect.
|
||||
* \sa exteriorDistance(const AlignedBox&), squaredExteriorDistance(const MatrixBase&)
|
||||
*/
|
||||
inline Scalar squaredExteriorDistance(const AlignedBox& b) const;
|
||||
|
||||
/** \returns the distance between the point \a p and the box \c *this,
|
||||
* and zero if \a p is inside the box.
|
||||
* \sa squaredExteriorDistance(const MatrixBase&), exteriorDistance(const AlignedBox&)
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline NonInteger exteriorDistance(const MatrixBase<Derived>& p) const
|
||||
{ using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(p))); }
|
||||
|
||||
/** \returns the distance between the boxes \a b and \c *this,
|
||||
* and zero if the boxes intersect.
|
||||
* \sa squaredExteriorDistance(const AlignedBox&), exteriorDistance(const MatrixBase&)
|
||||
*/
|
||||
inline NonInteger exteriorDistance(const AlignedBox& b) const
|
||||
{ using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance(b))); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<AlignedBox,
|
||||
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<AlignedBox,
|
||||
AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime>& other)
|
||||
{
|
||||
m_min = (other.min)().template cast<Scalar>();
|
||||
m_max = (other.max)().template cast<Scalar>();
|
||||
}
|
||||
|
||||
/** \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 AlignedBox& other, const RealScalar& prec = ScalarTraits::dummy_precision()) const
|
||||
{ return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_min, m_max;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Scalar,int AmbientDim>
|
||||
template<typename Derived>
|
||||
inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const MatrixBase<Derived>& a_p) const
|
||||
{
|
||||
typename internal::nested<Derived,2*AmbientDim>::type p(a_p.derived());
|
||||
Scalar dist2(0);
|
||||
Scalar aux;
|
||||
for (Index k=0; k<dim(); ++k)
|
||||
{
|
||||
if( m_min[k] > p[k] )
|
||||
{
|
||||
aux = m_min[k] - p[k];
|
||||
dist2 += aux*aux;
|
||||
}
|
||||
else if( p[k] > m_max[k] )
|
||||
{
|
||||
aux = p[k] - m_max[k];
|
||||
dist2 += aux*aux;
|
||||
}
|
||||
}
|
||||
return dist2;
|
||||
}
|
||||
|
||||
template<typename Scalar,int AmbientDim>
|
||||
inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance(const AlignedBox& b) const
|
||||
{
|
||||
Scalar dist2(0);
|
||||
Scalar aux;
|
||||
for (Index k=0; k<dim(); ++k)
|
||||
{
|
||||
if( m_min[k] > b.m_max[k] )
|
||||
{
|
||||
aux = m_min[k] - b.m_max[k];
|
||||
dist2 += aux*aux;
|
||||
}
|
||||
else if( b.m_min[k] > m_max[k] )
|
||||
{
|
||||
aux = b.m_min[k] - m_max[k];
|
||||
dist2 += aux*aux;
|
||||
}
|
||||
}
|
||||
return dist2;
|
||||
}
|
||||
|
||||
/** \defgroup alignedboxtypedefs Global aligned box typedefs
|
||||
*
|
||||
* \ingroup Geometry_Module
|
||||
*
|
||||
* Eigen defines several typedef shortcuts for most common aligned box types.
|
||||
*
|
||||
* The general patterns are the following:
|
||||
*
|
||||
* \c AlignedBoxSizeType where \c Size can be \c 1, \c 2,\c 3,\c 4 for fixed size boxes or \c X for dynamic size,
|
||||
* and where \c Type can be \c i for integer, \c f for float, \c d for double.
|
||||
*
|
||||
* For example, \c AlignedBox3d is a fixed-size 3x3 aligned box type of doubles, and \c AlignedBoxXf is a dynamic-size aligned box of floats.
|
||||
*
|
||||
* \sa class AlignedBox
|
||||
*/
|
||||
|
||||
#define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \
|
||||
/** \ingroup alignedboxtypedefs */ \
|
||||
typedef AlignedBox<Type, Size> AlignedBox##SizeSuffix##TypeSuffix;
|
||||
|
||||
#define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \
|
||||
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 1, 1) \
|
||||
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \
|
||||
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \
|
||||
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \
|
||||
EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Dynamic, X)
|
||||
|
||||
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(int, i)
|
||||
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(float, f)
|
||||
EIGEN_MAKE_TYPEDEFS_ALL_SIZES(double, d)
|
||||
|
||||
#undef EIGEN_MAKE_TYPEDEFS_ALL_SIZES
|
||||
#undef EIGEN_MAKE_TYPEDEFS
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ALIGNEDBOX_H
|
||||
240
3rdparty/eigen3/Eigen/src/Geometry/AngleAxis.h
vendored
Normal file
240
3rdparty/eigen3/Eigen/src/Geometry/AngleAxis.h
vendored
Normal file
@@ -0,0 +1,240 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_ANGLEAXIS_H
|
||||
#define EIGEN_ANGLEAXIS_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class AngleAxis
|
||||
*
|
||||
* \brief Represents a 3D rotation as a rotation angle around an arbitrary 3D axis
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients.
|
||||
*
|
||||
* \warning When setting up an AngleAxis object, the axis vector \b must \b be \b normalized.
|
||||
*
|
||||
* The following two typedefs are provided for convenience:
|
||||
* \li \c AngleAxisf for \c float
|
||||
* \li \c AngleAxisd for \c double
|
||||
*
|
||||
* Combined with MatrixBase::Unit{X,Y,Z}, AngleAxis can be used to easily
|
||||
* mimic Euler-angles. Here is an example:
|
||||
* \include AngleAxis_mimic_euler.cpp
|
||||
* Output: \verbinclude AngleAxis_mimic_euler.out
|
||||
*
|
||||
* \note This class is not aimed to be used to store a rotation transformation,
|
||||
* but rather to make easier the creation of other rotation (Quaternion, rotation Matrix)
|
||||
* and transformation objects.
|
||||
*
|
||||
* \sa class Quaternion, class Transform, MatrixBase::UnitX()
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
template<typename _Scalar> struct traits<AngleAxis<_Scalar> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename _Scalar>
|
||||
class AngleAxis : public RotationBase<AngleAxis<_Scalar>,3>
|
||||
{
|
||||
typedef RotationBase<AngleAxis<_Scalar>,3> Base;
|
||||
|
||||
public:
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
enum { Dim = 3 };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
typedef Quaternion<Scalar> QuaternionType;
|
||||
|
||||
protected:
|
||||
|
||||
Vector3 m_axis;
|
||||
Scalar m_angle;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
AngleAxis() {}
|
||||
/** Constructs and initialize the angle-axis rotation from an \a angle in radian
|
||||
* and an \a axis which \b must \b be \b normalized.
|
||||
*
|
||||
* \warning If the \a axis vector is not normalized, then the angle-axis object
|
||||
* represents an invalid rotation. */
|
||||
template<typename Derived>
|
||||
inline AngleAxis(const Scalar& angle, const MatrixBase<Derived>& axis) : m_axis(axis), m_angle(angle) {}
|
||||
/** Constructs and initialize the angle-axis rotation from a quaternion \a q. */
|
||||
template<typename QuatDerived> inline explicit AngleAxis(const QuaternionBase<QuatDerived>& q) { *this = q; }
|
||||
/** Constructs and initialize the angle-axis rotation from a 3x3 rotation matrix. */
|
||||
template<typename Derived>
|
||||
inline explicit AngleAxis(const MatrixBase<Derived>& m) { *this = m; }
|
||||
|
||||
/** \returns the value of the rotation angle in radian */
|
||||
Scalar angle() const { return m_angle; }
|
||||
/** \returns a read-write reference to the stored angle in radian */
|
||||
Scalar& angle() { return m_angle; }
|
||||
|
||||
/** \returns the rotation axis */
|
||||
const Vector3& axis() const { return m_axis; }
|
||||
/** \returns a read-write reference to the stored rotation axis.
|
||||
*
|
||||
* \warning The rotation axis must remain a \b unit vector.
|
||||
*/
|
||||
Vector3& axis() { return m_axis; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline QuaternionType operator* (const AngleAxis& other) const
|
||||
{ return QuaternionType(*this) * QuaternionType(other); }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline QuaternionType operator* (const QuaternionType& other) const
|
||||
{ return QuaternionType(*this) * other; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
friend inline QuaternionType operator* (const QuaternionType& a, const AngleAxis& b)
|
||||
{ return a * QuaternionType(b); }
|
||||
|
||||
/** \returns the inverse rotation, i.e., an angle-axis with opposite rotation angle */
|
||||
AngleAxis inverse() const
|
||||
{ return AngleAxis(-m_angle, m_axis); }
|
||||
|
||||
template<class QuatDerived>
|
||||
AngleAxis& operator=(const QuaternionBase<QuatDerived>& q);
|
||||
template<typename Derived>
|
||||
AngleAxis& operator=(const MatrixBase<Derived>& m);
|
||||
|
||||
template<typename Derived>
|
||||
AngleAxis& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
Matrix3 toRotationMatrix(void) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<AngleAxis,AngleAxis<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit AngleAxis(const AngleAxis<OtherScalarType>& other)
|
||||
{
|
||||
m_axis = other.axis().template cast<Scalar>();
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
static inline const AngleAxis Identity() { return AngleAxis(Scalar(0), Vector3::UnitX()); }
|
||||
|
||||
/** \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, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return m_axis.isApprox(other.m_axis, prec) && internal::isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision angle-axis type */
|
||||
typedef AngleAxis<float> AngleAxisf;
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision angle-axis type */
|
||||
typedef AngleAxis<double> AngleAxisd;
|
||||
|
||||
/** Set \c *this from a \b unit quaternion.
|
||||
* The axis is normalized.
|
||||
*
|
||||
* \warning As any other method dealing with quaternion, if the input quaternion
|
||||
* is not normalized then the result is undefined.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename QuatDerived>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const QuaternionBase<QuatDerived>& q)
|
||||
{
|
||||
using std::acos;
|
||||
using std::min;
|
||||
using std::max;
|
||||
using std::sqrt;
|
||||
Scalar n2 = q.vec().squaredNorm();
|
||||
if (n2 < NumTraits<Scalar>::dummy_precision()*NumTraits<Scalar>::dummy_precision())
|
||||
{
|
||||
m_angle = Scalar(0);
|
||||
m_axis << Scalar(1), Scalar(0), Scalar(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_angle = Scalar(2)*acos((min)((max)(Scalar(-1),q.w()),Scalar(1)));
|
||||
m_axis = q.vec() / sqrt(n2);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Set \c *this from a 3x3 rotation matrix \a mat.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::operator=(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
// Since a direct conversion would not be really faster,
|
||||
// let's use the robust Quaternion implementation:
|
||||
return *this = QuaternionType(mat);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets \c *this from a 3x3 rotation matrix.
|
||||
**/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
AngleAxis<Scalar>& AngleAxis<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
return *this = QuaternionType(mat);
|
||||
}
|
||||
|
||||
/** Constructs and \returns an equivalent 3x3 rotation matrix.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
typename AngleAxis<Scalar>::Matrix3
|
||||
AngleAxis<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
using std::sin;
|
||||
using std::cos;
|
||||
Matrix3 res;
|
||||
Vector3 sin_axis = sin(m_angle) * m_axis;
|
||||
Scalar c = cos(m_angle);
|
||||
Vector3 cos1_axis = (Scalar(1)-c) * m_axis;
|
||||
|
||||
Scalar tmp;
|
||||
tmp = cos1_axis.x() * m_axis.y();
|
||||
res.coeffRef(0,1) = tmp - sin_axis.z();
|
||||
res.coeffRef(1,0) = tmp + sin_axis.z();
|
||||
|
||||
tmp = cos1_axis.x() * m_axis.z();
|
||||
res.coeffRef(0,2) = tmp + sin_axis.y();
|
||||
res.coeffRef(2,0) = tmp - sin_axis.y();
|
||||
|
||||
tmp = cos1_axis.y() * m_axis.z();
|
||||
res.coeffRef(1,2) = tmp - sin_axis.x();
|
||||
res.coeffRef(2,1) = tmp + sin_axis.x();
|
||||
|
||||
res.diagonal() = (cos1_axis.cwiseProduct(m_axis)).array() + c;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ANGLEAXIS_H
|
||||
104
3rdparty/eigen3/Eigen/src/Geometry/EulerAngles.h
vendored
Normal file
104
3rdparty/eigen3/Eigen/src/Geometry/EulerAngles.h
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_EULERANGLES_H
|
||||
#define EIGEN_EULERANGLES_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
*
|
||||
* \returns the Euler-angles of the rotation matrix \c *this using the convention defined by the triplet (\a a0,\a a1,\a a2)
|
||||
*
|
||||
* Each of the three parameters \a a0,\a a1,\a a2 represents the respective rotation axis as an integer in {0,1,2}.
|
||||
* For instance, in:
|
||||
* \code Vector3f ea = mat.eulerAngles(2, 0, 2); \endcode
|
||||
* "2" represents the z axis and "0" the x axis, etc. The returned angles are such that
|
||||
* we have the following equality:
|
||||
* \code
|
||||
* mat == AngleAxisf(ea[0], Vector3f::UnitZ())
|
||||
* * AngleAxisf(ea[1], Vector3f::UnitX())
|
||||
* * AngleAxisf(ea[2], Vector3f::UnitZ()); \endcode
|
||||
* This corresponds to the right-multiply conventions (with right hand side frames).
|
||||
*
|
||||
* The returned angles are in the ranges [0:pi]x[-pi:pi]x[-pi:pi].
|
||||
*
|
||||
* \sa class AngleAxis
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline Matrix<typename MatrixBase<Derived>::Scalar,3,1>
|
||||
MatrixBase<Derived>::eulerAngles(Index a0, Index a1, Index a2) const
|
||||
{
|
||||
using std::atan2;
|
||||
using std::sin;
|
||||
using std::cos;
|
||||
/* Implemented from Graphics Gems IV */
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Derived,3,3)
|
||||
|
||||
Matrix<Scalar,3,1> res;
|
||||
typedef Matrix<typename Derived::Scalar,2,1> Vector2;
|
||||
|
||||
const Index odd = ((a0+1)%3 == a1) ? 0 : 1;
|
||||
const Index i = a0;
|
||||
const Index j = (a0 + 1 + odd)%3;
|
||||
const Index k = (a0 + 2 - odd)%3;
|
||||
|
||||
if (a0==a2)
|
||||
{
|
||||
res[0] = atan2(coeff(j,i), coeff(k,i));
|
||||
if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0)))
|
||||
{
|
||||
res[0] = (res[0] > Scalar(0)) ? res[0] - Scalar(M_PI) : res[0] + Scalar(M_PI);
|
||||
Scalar s2 = Vector2(coeff(j,i), coeff(k,i)).norm();
|
||||
res[1] = -atan2(s2, coeff(i,i));
|
||||
}
|
||||
else
|
||||
{
|
||||
Scalar s2 = Vector2(coeff(j,i), coeff(k,i)).norm();
|
||||
res[1] = atan2(s2, coeff(i,i));
|
||||
}
|
||||
|
||||
// With a=(0,1,0), we have i=0; j=1; k=2, and after computing the first two angles,
|
||||
// we can compute their respective rotation, and apply its inverse to M. Since the result must
|
||||
// be a rotation around x, we have:
|
||||
//
|
||||
// c2 s1.s2 c1.s2 1 0 0
|
||||
// 0 c1 -s1 * M = 0 c3 s3
|
||||
// -s2 s1.c2 c1.c2 0 -s3 c3
|
||||
//
|
||||
// Thus: m11.c1 - m21.s1 = c3 & m12.c1 - m22.s1 = s3
|
||||
|
||||
Scalar s1 = sin(res[0]);
|
||||
Scalar c1 = cos(res[0]);
|
||||
res[2] = atan2(c1*coeff(j,k)-s1*coeff(k,k), c1*coeff(j,j) - s1 * coeff(k,j));
|
||||
}
|
||||
else
|
||||
{
|
||||
res[0] = atan2(coeff(j,k), coeff(k,k));
|
||||
Scalar c2 = Vector2(coeff(i,i), coeff(i,j)).norm();
|
||||
if((odd && res[0]<Scalar(0)) || ((!odd) && res[0]>Scalar(0))) {
|
||||
res[0] = (res[0] > Scalar(0)) ? res[0] - Scalar(M_PI) : res[0] + Scalar(M_PI);
|
||||
res[1] = atan2(-coeff(i,k), -c2);
|
||||
}
|
||||
else
|
||||
res[1] = atan2(-coeff(i,k), c2);
|
||||
Scalar s1 = sin(res[0]);
|
||||
Scalar c1 = cos(res[0]);
|
||||
res[2] = atan2(s1*coeff(k,i)-c1*coeff(j,i), c1*coeff(j,j) - s1 * coeff(k,j));
|
||||
}
|
||||
if (!odd)
|
||||
res = -res;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_EULERANGLES_H
|
||||
307
3rdparty/eigen3/Eigen/src/Geometry/Homogeneous.h
vendored
Normal file
307
3rdparty/eigen3/Eigen/src/Geometry/Homogeneous.h
vendored
Normal file
@@ -0,0 +1,307 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_HOMOGENEOUS_H
|
||||
#define EIGEN_HOMOGENEOUS_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Homogeneous
|
||||
*
|
||||
* \brief Expression of one (or a set of) homogeneous vector(s)
|
||||
*
|
||||
* \param MatrixType the type of the object in which we are making homogeneous
|
||||
*
|
||||
* This class represents an expression of one (or a set of) homogeneous vector(s).
|
||||
* It is the return type of MatrixBase::homogeneous() and most of the time
|
||||
* this is the only way it is used.
|
||||
*
|
||||
* \sa MatrixBase::homogeneous()
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename MatrixType,int Direction>
|
||||
struct traits<Homogeneous<MatrixType,Direction> >
|
||||
: traits<MatrixType>
|
||||
{
|
||||
typedef typename traits<MatrixType>::StorageKind StorageKind;
|
||||
typedef typename nested<MatrixType>::type MatrixTypeNested;
|
||||
typedef typename remove_reference<MatrixTypeNested>::type _MatrixTypeNested;
|
||||
enum {
|
||||
RowsPlusOne = (MatrixType::RowsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::RowsAtCompileTime) + 1 : Dynamic,
|
||||
ColsPlusOne = (MatrixType::ColsAtCompileTime != Dynamic) ?
|
||||
int(MatrixType::ColsAtCompileTime) + 1 : Dynamic,
|
||||
RowsAtCompileTime = Direction==Vertical ? RowsPlusOne : MatrixType::RowsAtCompileTime,
|
||||
ColsAtCompileTime = Direction==Horizontal ? ColsPlusOne : MatrixType::ColsAtCompileTime,
|
||||
MaxRowsAtCompileTime = RowsAtCompileTime,
|
||||
MaxColsAtCompileTime = ColsAtCompileTime,
|
||||
TmpFlags = _MatrixTypeNested::Flags & HereditaryBits,
|
||||
Flags = ColsAtCompileTime==1 ? (TmpFlags & ~RowMajorBit)
|
||||
: RowsAtCompileTime==1 ? (TmpFlags | RowMajorBit)
|
||||
: TmpFlags,
|
||||
CoeffReadCost = _MatrixTypeNested::CoeffReadCost
|
||||
};
|
||||
};
|
||||
|
||||
template<typename MatrixType,typename Lhs> struct homogeneous_left_product_impl;
|
||||
template<typename MatrixType,typename Rhs> struct homogeneous_right_product_impl;
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
template<typename MatrixType,int _Direction> class Homogeneous
|
||||
: internal::no_assignment_operator, public MatrixBase<Homogeneous<MatrixType,_Direction> >
|
||||
{
|
||||
public:
|
||||
|
||||
enum { Direction = _Direction };
|
||||
|
||||
typedef MatrixBase<Homogeneous> Base;
|
||||
EIGEN_DENSE_PUBLIC_INTERFACE(Homogeneous)
|
||||
|
||||
inline Homogeneous(const MatrixType& matrix)
|
||||
: m_matrix(matrix)
|
||||
{}
|
||||
|
||||
inline Index rows() const { return m_matrix.rows() + (int(Direction)==Vertical ? 1 : 0); }
|
||||
inline Index cols() const { return m_matrix.cols() + (int(Direction)==Horizontal ? 1 : 0); }
|
||||
|
||||
inline Scalar coeff(Index row, Index col=0) const
|
||||
{
|
||||
if( (int(Direction)==Vertical && row==m_matrix.rows())
|
||||
|| (int(Direction)==Horizontal && col==m_matrix.cols()))
|
||||
return Scalar(1);
|
||||
return m_matrix.coeff(row, col);
|
||||
}
|
||||
|
||||
template<typename Rhs>
|
||||
inline const internal::homogeneous_right_product_impl<Homogeneous,Rhs>
|
||||
operator* (const MatrixBase<Rhs>& rhs) const
|
||||
{
|
||||
eigen_assert(int(Direction)==Horizontal);
|
||||
return internal::homogeneous_right_product_impl<Homogeneous,Rhs>(m_matrix,rhs.derived());
|
||||
}
|
||||
|
||||
template<typename Lhs> friend
|
||||
inline const internal::homogeneous_left_product_impl<Homogeneous,Lhs>
|
||||
operator* (const MatrixBase<Lhs>& lhs, const Homogeneous& rhs)
|
||||
{
|
||||
eigen_assert(int(Direction)==Vertical);
|
||||
return internal::homogeneous_left_product_impl<Homogeneous,Lhs>(lhs.derived(),rhs.m_matrix);
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, int Mode, int Options> friend
|
||||
inline const internal::homogeneous_left_product_impl<Homogeneous,Transform<Scalar,Dim,Mode,Options> >
|
||||
operator* (const Transform<Scalar,Dim,Mode,Options>& lhs, const Homogeneous& rhs)
|
||||
{
|
||||
eigen_assert(int(Direction)==Vertical);
|
||||
return internal::homogeneous_left_product_impl<Homogeneous,Transform<Scalar,Dim,Mode,Options> >(lhs,rhs.m_matrix);
|
||||
}
|
||||
|
||||
protected:
|
||||
typename MatrixType::Nested m_matrix;
|
||||
};
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* \return an expression of the equivalent homogeneous vector
|
||||
*
|
||||
* \only_for_vectors
|
||||
*
|
||||
* Example: \include MatrixBase_homogeneous.cpp
|
||||
* Output: \verbinclude MatrixBase_homogeneous.out
|
||||
*
|
||||
* \sa class Homogeneous
|
||||
*/
|
||||
template<typename Derived>
|
||||
inline typename MatrixBase<Derived>::HomogeneousReturnType
|
||||
MatrixBase<Derived>::homogeneous() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* \returns a matrix expression of homogeneous column (or row) vectors
|
||||
*
|
||||
* Example: \include VectorwiseOp_homogeneous.cpp
|
||||
* Output: \verbinclude VectorwiseOp_homogeneous.out
|
||||
*
|
||||
* \sa MatrixBase::homogeneous() */
|
||||
template<typename ExpressionType, int Direction>
|
||||
inline Homogeneous<ExpressionType,Direction>
|
||||
VectorwiseOp<ExpressionType,Direction>::homogeneous() const
|
||||
{
|
||||
return _expression();
|
||||
}
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* \returns an expression of the homogeneous normalized vector of \c *this
|
||||
*
|
||||
* Example: \include MatrixBase_hnormalized.cpp
|
||||
* Output: \verbinclude MatrixBase_hnormalized.out
|
||||
*
|
||||
* \sa VectorwiseOp::hnormalized() */
|
||||
template<typename Derived>
|
||||
inline const typename MatrixBase<Derived>::HNormalizedReturnType
|
||||
MatrixBase<Derived>::hnormalized() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived);
|
||||
return ConstStartMinusOne(derived(),0,0,
|
||||
ColsAtCompileTime==1?size()-1:1,
|
||||
ColsAtCompileTime==1?1:size()-1) / coeff(size()-1);
|
||||
}
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* \returns an expression of the homogeneous normalized vector of \c *this
|
||||
*
|
||||
* Example: \include DirectionWise_hnormalized.cpp
|
||||
* Output: \verbinclude DirectionWise_hnormalized.out
|
||||
*
|
||||
* \sa MatrixBase::hnormalized() */
|
||||
template<typename ExpressionType, int Direction>
|
||||
inline const typename VectorwiseOp<ExpressionType,Direction>::HNormalizedReturnType
|
||||
VectorwiseOp<ExpressionType,Direction>::hnormalized() const
|
||||
{
|
||||
return HNormalized_Block(_expression(),0,0,
|
||||
Direction==Vertical ? _expression().rows()-1 : _expression().rows(),
|
||||
Direction==Horizontal ? _expression().cols()-1 : _expression().cols()).cwiseQuotient(
|
||||
Replicate<HNormalized_Factors,
|
||||
Direction==Vertical ? HNormalized_SizeMinusOne : 1,
|
||||
Direction==Horizontal ? HNormalized_SizeMinusOne : 1>
|
||||
(HNormalized_Factors(_expression(),
|
||||
Direction==Vertical ? _expression().rows()-1:0,
|
||||
Direction==Horizontal ? _expression().cols()-1:0,
|
||||
Direction==Vertical ? 1 : _expression().rows(),
|
||||
Direction==Horizontal ? 1 : _expression().cols()),
|
||||
Direction==Vertical ? _expression().rows()-1 : 1,
|
||||
Direction==Horizontal ? _expression().cols()-1 : 1));
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename MatrixOrTransformType>
|
||||
struct take_matrix_for_product
|
||||
{
|
||||
typedef MatrixOrTransformType type;
|
||||
static const type& run(const type &x) { return x; }
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim, int Mode,int Options>
|
||||
struct take_matrix_for_product<Transform<Scalar, Dim, Mode, Options> >
|
||||
{
|
||||
typedef Transform<Scalar, Dim, Mode, Options> TransformType;
|
||||
typedef typename internal::add_const<typename TransformType::ConstAffinePart>::type type;
|
||||
static type run (const TransformType& x) { return x.affine(); }
|
||||
};
|
||||
|
||||
template<typename Scalar, int Dim, int Options>
|
||||
struct take_matrix_for_product<Transform<Scalar, Dim, Projective, Options> >
|
||||
{
|
||||
typedef Transform<Scalar, Dim, Projective, Options> TransformType;
|
||||
typedef typename TransformType::MatrixType type;
|
||||
static const type& run (const TransformType& x) { return x.matrix(); }
|
||||
};
|
||||
|
||||
template<typename MatrixType,typename Lhs>
|
||||
struct traits<homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs> >
|
||||
{
|
||||
typedef typename take_matrix_for_product<Lhs>::type LhsMatrixType;
|
||||
typedef typename remove_all<MatrixType>::type MatrixTypeCleaned;
|
||||
typedef typename remove_all<LhsMatrixType>::type LhsMatrixTypeCleaned;
|
||||
typedef typename make_proper_matrix_type<
|
||||
typename traits<MatrixTypeCleaned>::Scalar,
|
||||
LhsMatrixTypeCleaned::RowsAtCompileTime,
|
||||
MatrixTypeCleaned::ColsAtCompileTime,
|
||||
MatrixTypeCleaned::PlainObject::Options,
|
||||
LhsMatrixTypeCleaned::MaxRowsAtCompileTime,
|
||||
MatrixTypeCleaned::MaxColsAtCompileTime>::type ReturnType;
|
||||
};
|
||||
|
||||
template<typename MatrixType,typename Lhs>
|
||||
struct homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs>
|
||||
: public ReturnByValue<homogeneous_left_product_impl<Homogeneous<MatrixType,Vertical>,Lhs> >
|
||||
{
|
||||
typedef typename traits<homogeneous_left_product_impl>::LhsMatrixType LhsMatrixType;
|
||||
typedef typename remove_all<LhsMatrixType>::type LhsMatrixTypeCleaned;
|
||||
typedef typename remove_all<typename LhsMatrixTypeCleaned::Nested>::type LhsMatrixTypeNested;
|
||||
typedef typename MatrixType::Index Index;
|
||||
homogeneous_left_product_impl(const Lhs& lhs, const MatrixType& rhs)
|
||||
: m_lhs(take_matrix_for_product<Lhs>::run(lhs)),
|
||||
m_rhs(rhs)
|
||||
{}
|
||||
|
||||
inline Index rows() const { return m_lhs.rows(); }
|
||||
inline Index cols() const { return m_rhs.cols(); }
|
||||
|
||||
template<typename Dest> void evalTo(Dest& dst) const
|
||||
{
|
||||
// FIXME investigate how to allow lazy evaluation of this product when possible
|
||||
dst = Block<const LhsMatrixTypeNested,
|
||||
LhsMatrixTypeNested::RowsAtCompileTime,
|
||||
LhsMatrixTypeNested::ColsAtCompileTime==Dynamic?Dynamic:LhsMatrixTypeNested::ColsAtCompileTime-1>
|
||||
(m_lhs,0,0,m_lhs.rows(),m_lhs.cols()-1) * m_rhs;
|
||||
dst += m_lhs.col(m_lhs.cols()-1).rowwise()
|
||||
.template replicate<MatrixType::ColsAtCompileTime>(m_rhs.cols());
|
||||
}
|
||||
|
||||
typename LhsMatrixTypeCleaned::Nested m_lhs;
|
||||
typename MatrixType::Nested m_rhs;
|
||||
};
|
||||
|
||||
template<typename MatrixType,typename Rhs>
|
||||
struct traits<homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs> >
|
||||
{
|
||||
typedef typename make_proper_matrix_type<typename traits<MatrixType>::Scalar,
|
||||
MatrixType::RowsAtCompileTime,
|
||||
Rhs::ColsAtCompileTime,
|
||||
MatrixType::PlainObject::Options,
|
||||
MatrixType::MaxRowsAtCompileTime,
|
||||
Rhs::MaxColsAtCompileTime>::type ReturnType;
|
||||
};
|
||||
|
||||
template<typename MatrixType,typename Rhs>
|
||||
struct homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs>
|
||||
: public ReturnByValue<homogeneous_right_product_impl<Homogeneous<MatrixType,Horizontal>,Rhs> >
|
||||
{
|
||||
typedef typename remove_all<typename Rhs::Nested>::type RhsNested;
|
||||
typedef typename MatrixType::Index Index;
|
||||
homogeneous_right_product_impl(const MatrixType& lhs, const Rhs& rhs)
|
||||
: m_lhs(lhs), m_rhs(rhs)
|
||||
{}
|
||||
|
||||
inline Index rows() const { return m_lhs.rows(); }
|
||||
inline Index cols() const { return m_rhs.cols(); }
|
||||
|
||||
template<typename Dest> void evalTo(Dest& dst) const
|
||||
{
|
||||
// FIXME investigate how to allow lazy evaluation of this product when possible
|
||||
dst = m_lhs * Block<const RhsNested,
|
||||
RhsNested::RowsAtCompileTime==Dynamic?Dynamic:RhsNested::RowsAtCompileTime-1,
|
||||
RhsNested::ColsAtCompileTime>
|
||||
(m_rhs,0,0,m_rhs.rows()-1,m_rhs.cols());
|
||||
dst += m_rhs.row(m_rhs.rows()-1).colwise()
|
||||
.template replicate<MatrixType::RowsAtCompileTime>(m_lhs.rows());
|
||||
}
|
||||
|
||||
typename MatrixType::Nested m_lhs;
|
||||
typename Rhs::Nested m_rhs;
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_HOMOGENEOUS_H
|
||||
280
3rdparty/eigen3/Eigen/src/Geometry/Hyperplane.h
vendored
Normal file
280
3rdparty/eigen3/Eigen/src/Geometry/Hyperplane.h
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_HYPERPLANE_H
|
||||
#define EIGEN_HYPERPLANE_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Hyperplane
|
||||
*
|
||||
* \brief A hyperplane
|
||||
*
|
||||
* A hyperplane is an affine subspace of dimension n-1 in a space of dimension n.
|
||||
* For example, a hyperplane in a plane is a line; a hyperplane in 3-space is a plane.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
* Notice that the dimension of the hyperplane is _AmbientDim-1.
|
||||
*
|
||||
* This class represents an hyperplane as the zero set of the implicit equation
|
||||
* \f$ n \cdot x + d = 0 \f$ where \f$ n \f$ is a unit normal vector of the plane (linear part)
|
||||
* and \f$ d \f$ is the distance (offset) to the origin.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
class Hyperplane
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1)
|
||||
enum {
|
||||
AmbientDimAtCompileTime = _AmbientDim,
|
||||
Options = _Options
|
||||
};
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef DenseIndex Index;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;
|
||||
typedef Matrix<Scalar,Index(AmbientDimAtCompileTime)==Dynamic
|
||||
? Dynamic
|
||||
: Index(AmbientDimAtCompileTime)+1,1,Options> Coefficients;
|
||||
typedef Block<Coefficients,AmbientDimAtCompileTime,1> NormalReturnType;
|
||||
typedef const Block<const Coefficients,AmbientDimAtCompileTime,1> ConstNormalReturnType;
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline Hyperplane() {}
|
||||
|
||||
template<int OtherOptions>
|
||||
Hyperplane(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
: m_coeffs(other.coeffs())
|
||||
{}
|
||||
|
||||
/** Constructs a dynamic-size hyperplane with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit Hyperplane(Index _dim) : m_coeffs(_dim+1) {}
|
||||
|
||||
/** Construct a plane from its normal \a n and a point \a e onto the plane.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, const VectorType& e)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = -n.dot(e);
|
||||
}
|
||||
|
||||
/** Constructs a plane from its normal \a n and distance to the origin \a d
|
||||
* such that the algebraic equation of the plane is \f$ n \cdot x + d = 0 \f$.
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline Hyperplane(const VectorType& n, const Scalar& d)
|
||||
: m_coeffs(n.size()+1)
|
||||
{
|
||||
normal() = n;
|
||||
offset() = d;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the two points. If the dimension of the ambient space
|
||||
* is greater than 2, then there isn't uniqueness, so an arbitrary choice is made.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1)
|
||||
{
|
||||
Hyperplane result(p0.size());
|
||||
result.normal() = (p1 - p0).unitOrthogonal();
|
||||
result.offset() = -p0.dot(result.normal());
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the three points. The dimension of the ambient space
|
||||
* is required to be exactly 3.
|
||||
*/
|
||||
static inline Hyperplane Through(const VectorType& p0, const VectorType& p1, const VectorType& p2)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 3)
|
||||
Hyperplane result(p0.size());
|
||||
VectorType v0(p2 - p0), v1(p1 - p0);
|
||||
result.normal() = v0.cross(v1);
|
||||
RealScalar norm = result.normal().norm();
|
||||
if(norm <= v0.norm() * v1.norm() * NumTraits<RealScalar>::epsilon())
|
||||
{
|
||||
Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
|
||||
JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
|
||||
result.normal() = svd.matrixV().col(2);
|
||||
}
|
||||
else
|
||||
result.normal() /= norm;
|
||||
result.offset() = -p0.dot(result.normal());
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Constructs a hyperplane passing through the parametrized line \a parametrized.
|
||||
* If the dimension of the ambient space is greater than 2, then there isn't uniqueness,
|
||||
* so an arbitrary choice is made.
|
||||
*/
|
||||
// FIXME to be consitent with the rest this could be implemented as a static Through function ??
|
||||
explicit Hyperplane(const ParametrizedLine<Scalar, AmbientDimAtCompileTime>& parametrized)
|
||||
{
|
||||
normal() = parametrized.direction().unitOrthogonal();
|
||||
offset() = -parametrized.origin().dot(normal());
|
||||
}
|
||||
|
||||
~Hyperplane() {}
|
||||
|
||||
/** \returns the dimension in which the plane holds */
|
||||
inline Index dim() const { return AmbientDimAtCompileTime==Dynamic ? m_coeffs.size()-1 : Index(AmbientDimAtCompileTime); }
|
||||
|
||||
/** normalizes \c *this */
|
||||
void normalize(void)
|
||||
{
|
||||
m_coeffs /= normal().norm();
|
||||
}
|
||||
|
||||
/** \returns the signed distance between the plane \c *this and a point \a p.
|
||||
* \sa absDistance()
|
||||
*/
|
||||
inline Scalar signedDistance(const VectorType& p) const { return normal().dot(p) + offset(); }
|
||||
|
||||
/** \returns the absolute distance between the plane \c *this and a point \a p.
|
||||
* \sa signedDistance()
|
||||
*/
|
||||
inline Scalar absDistance(const VectorType& p) const { using std::abs; return abs(signedDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the plane \c *this.
|
||||
*/
|
||||
inline VectorType projection(const VectorType& p) const { return p - signedDistance(p) * normal(); }
|
||||
|
||||
/** \returns a constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline ConstNormalReturnType normal() const { return ConstNormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns a non-constant reference to the unit normal vector of the plane, which corresponds
|
||||
* to the linear part of the implicit equation.
|
||||
*/
|
||||
inline NormalReturnType normal() { return NormalReturnType(m_coeffs,0,0,dim(),1); }
|
||||
|
||||
/** \returns the distance to the origin, which is also the "constant term" of the implicit equation
|
||||
* \warning the vector normal is assumed to be normalized.
|
||||
*/
|
||||
inline const Scalar& offset() const { return m_coeffs.coeff(dim()); }
|
||||
|
||||
/** \returns a non-constant reference to the distance to the origin, which is also the constant part
|
||||
* of the implicit equation */
|
||||
inline Scalar& offset() { return m_coeffs(dim()); }
|
||||
|
||||
/** \returns a constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
/** \returns a non-constant reference to the coefficients c_i of the plane equation:
|
||||
* \f$ c_0*x_0 + ... + c_{d-1}*x_{d-1} + c_d = 0 \f$
|
||||
*/
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
|
||||
/** \returns the intersection of *this with \a other.
|
||||
*
|
||||
* \warning The ambient space must be a plane, i.e. have dimension 2, so that \c *this and \a other are lines.
|
||||
*
|
||||
* \note If \a other is approximately parallel to *this, this method will return any point on *this.
|
||||
*/
|
||||
VectorType intersection(const Hyperplane& other) const
|
||||
{
|
||||
using std::abs;
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
Scalar det = coeffs().coeff(0) * other.coeffs().coeff(1) - coeffs().coeff(1) * other.coeffs().coeff(0);
|
||||
// since the line equations ax+by=c are normalized with a^2+b^2=1, the following tests
|
||||
// whether the two lines are approximately parallel.
|
||||
if(internal::isMuchSmallerThan(det, Scalar(1)))
|
||||
{ // special case where the two lines are approximately parallel. Pick any point on the first line.
|
||||
if(abs(coeffs().coeff(1))>abs(coeffs().coeff(0)))
|
||||
return VectorType(coeffs().coeff(1), -coeffs().coeff(2)/coeffs().coeff(1)-coeffs().coeff(0));
|
||||
else
|
||||
return VectorType(-coeffs().coeff(2)/coeffs().coeff(0)-coeffs().coeff(1), coeffs().coeff(0));
|
||||
}
|
||||
else
|
||||
{ // general case
|
||||
Scalar invdet = Scalar(1) / det;
|
||||
return VectorType(invdet*(coeffs().coeff(1)*other.coeffs().coeff(2)-other.coeffs().coeff(1)*coeffs().coeff(2)),
|
||||
invdet*(other.coeffs().coeff(0)*coeffs().coeff(2)-coeffs().coeff(0)*other.coeffs().coeff(2)));
|
||||
}
|
||||
}
|
||||
|
||||
/** Applies the transformation matrix \a mat to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* \param mat the Dim x Dim transformation matrix
|
||||
* \param traits specifies whether the matrix \a mat represents an #Isometry
|
||||
* or a more generic #Affine transformation. The default is #Affine.
|
||||
*/
|
||||
template<typename XprType>
|
||||
inline Hyperplane& transform(const MatrixBase<XprType>& mat, TransformTraits traits = Affine)
|
||||
{
|
||||
if (traits==Affine)
|
||||
normal() = mat.inverse().transpose() * normal();
|
||||
else if (traits==Isometry)
|
||||
normal() = mat * normal();
|
||||
else
|
||||
{
|
||||
eigen_assert(0 && "invalid traits value in Hyperplane::transform()");
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Applies the transformation \a t to \c *this and returns a reference to \c *this.
|
||||
*
|
||||
* \param t the transformation of dimension Dim
|
||||
* \param traits specifies whether the transformation \a t represents an #Isometry
|
||||
* or a more generic #Affine transformation. The default is #Affine.
|
||||
* Other kind of transformations are not supported.
|
||||
*/
|
||||
template<int TrOptions>
|
||||
inline Hyperplane& transform(const Transform<Scalar,AmbientDimAtCompileTime,Affine,TrOptions>& t,
|
||||
TransformTraits traits = Affine)
|
||||
{
|
||||
transform(t.linear(), traits);
|
||||
offset() -= normal().dot(t.translation());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Hyperplane,
|
||||
Hyperplane<NewScalarType,AmbientDimAtCompileTime,Options> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<Hyperplane,
|
||||
Hyperplane<NewScalarType,AmbientDimAtCompileTime,Options> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType,int OtherOptions>
|
||||
inline explicit Hyperplane(const Hyperplane<OtherScalarType,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
template<int OtherOptions>
|
||||
bool isApprox(const Hyperplane<Scalar,AmbientDimAtCompileTime,OtherOptions>& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_HYPERPLANE_H
|
||||
218
3rdparty/eigen3/Eigen/src/Geometry/OrthoMethods.h
vendored
Normal file
218
3rdparty/eigen3/Eigen/src/Geometry/OrthoMethods.h
vendored
Normal file
@@ -0,0 +1,218 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_ORTHOMETHODS_H
|
||||
#define EIGEN_ORTHOMETHODS_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* \returns the cross product of \c *this and \a other
|
||||
*
|
||||
* Here is a very good explanation of cross-product: http://xkcd.com/199/
|
||||
* \sa MatrixBase::cross3()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline typename MatrixBase<Derived>::template cross_product_return_type<OtherDerived>::type
|
||||
MatrixBase<Derived>::cross(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,3)
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
|
||||
|
||||
// Note that there is no need for an expression here since the compiler
|
||||
// optimize such a small temporary very well (even within a complex expression)
|
||||
typename internal::nested<Derived,2>::type lhs(derived());
|
||||
typename internal::nested<OtherDerived,2>::type rhs(other.derived());
|
||||
return typename cross_product_return_type<OtherDerived>::type(
|
||||
numext::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)),
|
||||
numext::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)),
|
||||
numext::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0))
|
||||
);
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template< int Arch,typename VectorLhs,typename VectorRhs,
|
||||
typename Scalar = typename VectorLhs::Scalar,
|
||||
bool Vectorizable = bool((VectorLhs::Flags&VectorRhs::Flags)&PacketAccessBit)>
|
||||
struct cross3_impl {
|
||||
static inline typename internal::plain_matrix_type<VectorLhs>::type
|
||||
run(const VectorLhs& lhs, const VectorRhs& rhs)
|
||||
{
|
||||
return typename internal::plain_matrix_type<VectorLhs>::type(
|
||||
numext::conj(lhs.coeff(1) * rhs.coeff(2) - lhs.coeff(2) * rhs.coeff(1)),
|
||||
numext::conj(lhs.coeff(2) * rhs.coeff(0) - lhs.coeff(0) * rhs.coeff(2)),
|
||||
numext::conj(lhs.coeff(0) * rhs.coeff(1) - lhs.coeff(1) * rhs.coeff(0)),
|
||||
0
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* \returns the cross product of \c *this and \a other using only the x, y, and z coefficients
|
||||
*
|
||||
* The size of \c *this and \a other must be four. This function is especially useful
|
||||
* when using 4D vectors instead of 3D ones to get advantage of SSE/AltiVec vectorization.
|
||||
*
|
||||
* \sa MatrixBase::cross()
|
||||
*/
|
||||
template<typename Derived>
|
||||
template<typename OtherDerived>
|
||||
inline typename MatrixBase<Derived>::PlainObject
|
||||
MatrixBase<Derived>::cross3(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(Derived,4)
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,4)
|
||||
|
||||
typedef typename internal::nested<Derived,2>::type DerivedNested;
|
||||
typedef typename internal::nested<OtherDerived,2>::type OtherDerivedNested;
|
||||
DerivedNested lhs(derived());
|
||||
OtherDerivedNested rhs(other.derived());
|
||||
|
||||
return internal::cross3_impl<Architecture::Target,
|
||||
typename internal::remove_all<DerivedNested>::type,
|
||||
typename internal::remove_all<OtherDerivedNested>::type>::run(lhs,rhs);
|
||||
}
|
||||
|
||||
/** \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 VectorwiseOp<ExpressionType,Direction>::CrossReturnType
|
||||
VectorwiseOp<ExpressionType,Direction>::cross(const MatrixBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(OtherDerived,3)
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename OtherDerived::Scalar>::value),
|
||||
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)
|
||||
{
|
||||
eigen_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)).conjugate();
|
||||
res.row(1) = (_expression().row(2) * other.coeff(0) - _expression().row(0) * other.coeff(2)).conjugate();
|
||||
res.row(2) = (_expression().row(0) * other.coeff(1) - _expression().row(1) * other.coeff(0)).conjugate();
|
||||
}
|
||||
else
|
||||
{
|
||||
eigen_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)).conjugate();
|
||||
res.col(1) = (_expression().col(2) * other.coeff(0) - _expression().col(0) * other.coeff(2)).conjugate();
|
||||
res.col(2) = (_expression().col(0) * other.coeff(1) - _expression().col(1) * other.coeff(0)).conjugate();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename Derived, int Size = Derived::SizeAtCompileTime>
|
||||
struct unitOrthogonal_selector
|
||||
{
|
||||
typedef typename plain_matrix_type<Derived>::type VectorType;
|
||||
typedef typename traits<Derived>::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef typename Derived::Index Index;
|
||||
typedef Matrix<Scalar,2,1> Vector2;
|
||||
static inline VectorType run(const Derived& src)
|
||||
{
|
||||
VectorType perp = VectorType::Zero(src.size());
|
||||
Index maxi = 0;
|
||||
Index sndi = 0;
|
||||
src.cwiseAbs().maxCoeff(&maxi);
|
||||
if (maxi==0)
|
||||
sndi = 1;
|
||||
RealScalar invnm = RealScalar(1)/(Vector2() << src.coeff(sndi),src.coeff(maxi)).finished().norm();
|
||||
perp.coeffRef(maxi) = -numext::conj(src.coeff(sndi)) * invnm;
|
||||
perp.coeffRef(sndi) = numext::conj(src.coeff(maxi)) * invnm;
|
||||
|
||||
return perp;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct unitOrthogonal_selector<Derived,3>
|
||||
{
|
||||
typedef typename plain_matrix_type<Derived>::type VectorType;
|
||||
typedef typename traits<Derived>::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
static inline VectorType run(const Derived& src)
|
||||
{
|
||||
VectorType perp;
|
||||
/* Let us compute the crossed product of *this with a vector
|
||||
* that is not too close to being colinear to *this.
|
||||
*/
|
||||
|
||||
/* unless the x and y coords are both close to zero, we can
|
||||
* simply take ( -y, x, 0 ) and normalize it.
|
||||
*/
|
||||
if((!isMuchSmallerThan(src.x(), src.z()))
|
||||
|| (!isMuchSmallerThan(src.y(), src.z())))
|
||||
{
|
||||
RealScalar invnm = RealScalar(1)/src.template head<2>().norm();
|
||||
perp.coeffRef(0) = -numext::conj(src.y())*invnm;
|
||||
perp.coeffRef(1) = numext::conj(src.x())*invnm;
|
||||
perp.coeffRef(2) = 0;
|
||||
}
|
||||
/* if both x and y are close to zero, then the vector is close
|
||||
* to the z-axis, so it's far from colinear to the x-axis for instance.
|
||||
* So we take the crossed product with (1,0,0) and normalize it.
|
||||
*/
|
||||
else
|
||||
{
|
||||
RealScalar invnm = RealScalar(1)/src.template tail<2>().norm();
|
||||
perp.coeffRef(0) = 0;
|
||||
perp.coeffRef(1) = -numext::conj(src.z())*invnm;
|
||||
perp.coeffRef(2) = numext::conj(src.y())*invnm;
|
||||
}
|
||||
|
||||
return perp;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Derived>
|
||||
struct unitOrthogonal_selector<Derived,2>
|
||||
{
|
||||
typedef typename plain_matrix_type<Derived>::type VectorType;
|
||||
static inline VectorType run(const Derived& src)
|
||||
{ return VectorType(-numext::conj(src.y()), numext::conj(src.x())).normalized(); }
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/** \returns a unit vector which is orthogonal to \c *this
|
||||
*
|
||||
* The size of \c *this must be at least 2. If the size is exactly 2,
|
||||
* then the returned vector is a counter clock wise rotation of \c *this, i.e., (-y,x).normalized().
|
||||
*
|
||||
* \sa cross()
|
||||
*/
|
||||
template<typename Derived>
|
||||
typename MatrixBase<Derived>::PlainObject
|
||||
MatrixBase<Derived>::unitOrthogonal() const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_ONLY(Derived)
|
||||
return internal::unitOrthogonal_selector<Derived>::run(derived());
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ORTHOMETHODS_H
|
||||
195
3rdparty/eigen3/Eigen/src/Geometry/ParametrizedLine.h
vendored
Normal file
195
3rdparty/eigen3/Eigen/src/Geometry/ParametrizedLine.h
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_PARAMETRIZEDLINE_H
|
||||
#define EIGEN_PARAMETRIZEDLINE_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class ParametrizedLine
|
||||
*
|
||||
* \brief A parametrized line
|
||||
*
|
||||
* A parametrized line is defined by an origin point \f$ \mathbf{o} \f$ and a unit
|
||||
* direction vector \f$ \mathbf{d} \f$ such that the line corresponds to
|
||||
* the set \f$ l(t) = \mathbf{o} + t \mathbf{d} \f$, \f$ t \in \mathbf{R} \f$.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \param _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic.
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
class ParametrizedLine
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim)
|
||||
enum {
|
||||
AmbientDimAtCompileTime = _AmbientDim,
|
||||
Options = _Options
|
||||
};
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef DenseIndex Index;
|
||||
typedef Matrix<Scalar,AmbientDimAtCompileTime,1,Options> VectorType;
|
||||
|
||||
/** Default constructor without initialization */
|
||||
inline ParametrizedLine() {}
|
||||
|
||||
template<int OtherOptions>
|
||||
ParametrizedLine(const ParametrizedLine<Scalar,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
: m_origin(other.origin()), m_direction(other.direction())
|
||||
{}
|
||||
|
||||
/** Constructs a dynamic-size line with \a _dim the dimension
|
||||
* of the ambient space */
|
||||
inline explicit ParametrizedLine(Index _dim) : m_origin(_dim), m_direction(_dim) {}
|
||||
|
||||
/** Initializes a parametrized line of direction \a direction and origin \a origin.
|
||||
* \warning the vector direction is assumed to be normalized.
|
||||
*/
|
||||
ParametrizedLine(const VectorType& origin, const VectorType& direction)
|
||||
: m_origin(origin), m_direction(direction) {}
|
||||
|
||||
template <int OtherOptions>
|
||||
explicit ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane);
|
||||
|
||||
/** Constructs a parametrized line going from \a p0 to \a p1. */
|
||||
static inline ParametrizedLine Through(const VectorType& p0, const VectorType& p1)
|
||||
{ return ParametrizedLine(p0, (p1-p0).normalized()); }
|
||||
|
||||
~ParametrizedLine() {}
|
||||
|
||||
/** \returns the dimension in which the line holds */
|
||||
inline Index dim() const { return m_direction.size(); }
|
||||
|
||||
const VectorType& origin() const { return m_origin; }
|
||||
VectorType& origin() { return m_origin; }
|
||||
|
||||
const VectorType& direction() const { return m_direction; }
|
||||
VectorType& direction() { return m_direction; }
|
||||
|
||||
/** \returns the squared distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa distance()
|
||||
*/
|
||||
RealScalar squaredDistance(const VectorType& p) const
|
||||
{
|
||||
VectorType diff = p - origin();
|
||||
return (diff - direction().dot(diff) * direction()).squaredNorm();
|
||||
}
|
||||
/** \returns the distance of a point \a p to its projection onto the line \c *this.
|
||||
* \sa squaredDistance()
|
||||
*/
|
||||
RealScalar distance(const VectorType& p) const { using std::sqrt; return sqrt(squaredDistance(p)); }
|
||||
|
||||
/** \returns the projection of a point \a p onto the line \c *this. */
|
||||
VectorType projection(const VectorType& p) const
|
||||
{ return origin() + direction().dot(p-origin()) * direction(); }
|
||||
|
||||
VectorType pointAt(const Scalar& t) const;
|
||||
|
||||
template <int OtherOptions>
|
||||
Scalar intersectionParameter(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||
|
||||
template <int OtherOptions>
|
||||
Scalar intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||
|
||||
template <int OtherOptions>
|
||||
VectorType intersectionPoint(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<ParametrizedLine,
|
||||
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime,Options> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<ParametrizedLine,
|
||||
ParametrizedLine<NewScalarType,AmbientDimAtCompileTime,Options> >::type(*this);
|
||||
}
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType,int OtherOptions>
|
||||
inline explicit ParametrizedLine(const ParametrizedLine<OtherScalarType,AmbientDimAtCompileTime,OtherOptions>& other)
|
||||
{
|
||||
m_origin = other.origin().template cast<Scalar>();
|
||||
m_direction = other.direction().template cast<Scalar>();
|
||||
}
|
||||
|
||||
/** \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, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return m_origin.isApprox(other.m_origin, prec) && m_direction.isApprox(other.m_direction, prec); }
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_origin, m_direction;
|
||||
};
|
||||
|
||||
/** Constructs a parametrized line from a 2D hyperplane
|
||||
*
|
||||
* \warning the ambient space must have dimension 2 such that the hyperplane actually describes a line
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
template <int OtherOptions>
|
||||
inline ParametrizedLine<_Scalar, _AmbientDim,_Options>::ParametrizedLine(const Hyperplane<_Scalar, _AmbientDim,OtherOptions>& hyperplane)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(VectorType, 2)
|
||||
direction() = hyperplane.normal().unitOrthogonal();
|
||||
origin() = -hyperplane.normal()*hyperplane.offset();
|
||||
}
|
||||
|
||||
/** \returns the point at \a t along this line
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
inline typename ParametrizedLine<_Scalar, _AmbientDim,_Options>::VectorType
|
||||
ParametrizedLine<_Scalar, _AmbientDim,_Options>::pointAt(const _Scalar& t) const
|
||||
{
|
||||
return origin() + (direction()*t);
|
||||
}
|
||||
|
||||
/** \returns the parameter value of the intersection between \c *this and the given \a hyperplane
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
template <int OtherOptions>
|
||||
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionParameter(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||
{
|
||||
return -(hyperplane.offset()+hyperplane.normal().dot(origin()))
|
||||
/ hyperplane.normal().dot(direction());
|
||||
}
|
||||
|
||||
|
||||
/** \deprecated use intersectionParameter()
|
||||
* \returns the parameter value of the intersection between \c *this and the given \a hyperplane
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
template <int OtherOptions>
|
||||
inline _Scalar ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersection(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||
{
|
||||
return intersectionParameter(hyperplane);
|
||||
}
|
||||
|
||||
/** \returns the point of the intersection between \c *this and the given hyperplane
|
||||
*/
|
||||
template <typename _Scalar, int _AmbientDim, int _Options>
|
||||
template <int OtherOptions>
|
||||
inline typename ParametrizedLine<_Scalar, _AmbientDim,_Options>::VectorType
|
||||
ParametrizedLine<_Scalar, _AmbientDim,_Options>::intersectionPoint(const Hyperplane<_Scalar, _AmbientDim, OtherOptions>& hyperplane) const
|
||||
{
|
||||
return pointAt(intersectionParameter(hyperplane));
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_PARAMETRIZEDLINE_H
|
||||
776
3rdparty/eigen3/Eigen/src/Geometry/Quaternion.h
vendored
Normal file
776
3rdparty/eigen3/Eigen/src/Geometry/Quaternion.h
vendored
Normal file
@@ -0,0 +1,776 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
// Copyright (C) 2009 Mathieu Gautier <mathieu.gautier@cea.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_QUATERNION_H
|
||||
#define EIGEN_QUATERNION_H
|
||||
namespace Eigen {
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
* Definition of QuaternionBase<Derived>
|
||||
* The implementation is at the end of the file
|
||||
***************************************************************************/
|
||||
|
||||
namespace internal {
|
||||
template<typename Other,
|
||||
int OtherRows=Other::RowsAtCompileTime,
|
||||
int OtherCols=Other::ColsAtCompileTime>
|
||||
struct quaternionbase_assign_impl;
|
||||
}
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
* \class QuaternionBase
|
||||
* \brief Base class for quaternion expressions
|
||||
* \tparam Derived derived type (CRTP)
|
||||
* \sa class Quaternion
|
||||
*/
|
||||
template<class Derived>
|
||||
class QuaternionBase : public RotationBase<Derived, 3>
|
||||
{
|
||||
typedef RotationBase<Derived, 3> Base;
|
||||
public:
|
||||
using Base::operator*;
|
||||
using Base::derived;
|
||||
|
||||
typedef typename internal::traits<Derived>::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef typename internal::traits<Derived>::Coefficients Coefficients;
|
||||
enum {
|
||||
Flags = Eigen::internal::traits<Derived>::Flags
|
||||
};
|
||||
|
||||
// typedef typename Matrix<Scalar,4,1> Coefficients;
|
||||
/** the type of a 3D vector */
|
||||
typedef Matrix<Scalar,3,1> Vector3;
|
||||
/** the equivalent rotation matrix type */
|
||||
typedef Matrix<Scalar,3,3> Matrix3;
|
||||
/** the equivalent angle-axis type */
|
||||
typedef AngleAxis<Scalar> AngleAxisType;
|
||||
|
||||
|
||||
|
||||
/** \returns the \c x coefficient */
|
||||
inline Scalar x() const { return this->derived().coeffs().coeff(0); }
|
||||
/** \returns the \c y coefficient */
|
||||
inline Scalar y() const { return this->derived().coeffs().coeff(1); }
|
||||
/** \returns the \c z coefficient */
|
||||
inline Scalar z() const { return this->derived().coeffs().coeff(2); }
|
||||
/** \returns the \c w coefficient */
|
||||
inline Scalar w() const { return this->derived().coeffs().coeff(3); }
|
||||
|
||||
/** \returns a reference to the \c x coefficient */
|
||||
inline Scalar& x() { return this->derived().coeffs().coeffRef(0); }
|
||||
/** \returns a reference to the \c y coefficient */
|
||||
inline Scalar& y() { return this->derived().coeffs().coeffRef(1); }
|
||||
/** \returns a reference to the \c z coefficient */
|
||||
inline Scalar& z() { return this->derived().coeffs().coeffRef(2); }
|
||||
/** \returns a reference to the \c w coefficient */
|
||||
inline Scalar& w() { return this->derived().coeffs().coeffRef(3); }
|
||||
|
||||
/** \returns a read-only vector expression of the imaginary part (x,y,z) */
|
||||
inline const VectorBlock<const Coefficients,3> vec() const { return coeffs().template head<3>(); }
|
||||
|
||||
/** \returns a vector expression of the imaginary part (x,y,z) */
|
||||
inline VectorBlock<Coefficients,3> vec() { return coeffs().template head<3>(); }
|
||||
|
||||
/** \returns a read-only vector expression of the coefficients (x,y,z,w) */
|
||||
inline const typename internal::traits<Derived>::Coefficients& coeffs() const { return derived().coeffs(); }
|
||||
|
||||
/** \returns a vector expression of the coefficients (x,y,z,w) */
|
||||
inline typename internal::traits<Derived>::Coefficients& coeffs() { return derived().coeffs(); }
|
||||
|
||||
EIGEN_STRONG_INLINE QuaternionBase<Derived>& operator=(const QuaternionBase<Derived>& other);
|
||||
template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator=(const QuaternionBase<OtherDerived>& other);
|
||||
|
||||
// disabled this copy operator as it is giving very strange compilation errors when compiling
|
||||
// test_stdvector with GCC 4.4.2. This looks like a GCC bug though, so feel free to re-enable it if it's
|
||||
// useful; however notice that we already have the templated operator= above and e.g. in MatrixBase
|
||||
// we didn't have to add, in addition to templated operator=, such a non-templated copy operator.
|
||||
// Derived& operator=(const QuaternionBase& other)
|
||||
// { return operator=<Derived>(other); }
|
||||
|
||||
Derived& operator=(const AngleAxisType& aa);
|
||||
template<class OtherDerived> Derived& operator=(const MatrixBase<OtherDerived>& m);
|
||||
|
||||
/** \returns a quaternion representing an identity rotation
|
||||
* \sa MatrixBase::Identity()
|
||||
*/
|
||||
static inline Quaternion<Scalar> Identity() { return Quaternion<Scalar>(Scalar(1), Scalar(0), Scalar(0), Scalar(0)); }
|
||||
|
||||
/** \sa QuaternionBase::Identity(), MatrixBase::setIdentity()
|
||||
*/
|
||||
inline QuaternionBase& setIdentity() { coeffs() << Scalar(0), Scalar(0), Scalar(0), Scalar(1); return *this; }
|
||||
|
||||
/** \returns the squared norm of the quaternion's coefficients
|
||||
* \sa QuaternionBase::norm(), MatrixBase::squaredNorm()
|
||||
*/
|
||||
inline Scalar squaredNorm() const { return coeffs().squaredNorm(); }
|
||||
|
||||
/** \returns the norm of the quaternion's coefficients
|
||||
* \sa QuaternionBase::squaredNorm(), MatrixBase::norm()
|
||||
*/
|
||||
inline Scalar norm() const { return coeffs().norm(); }
|
||||
|
||||
/** Normalizes the quaternion \c *this
|
||||
* \sa normalized(), MatrixBase::normalize() */
|
||||
inline void normalize() { coeffs().normalize(); }
|
||||
/** \returns a normalized copy of \c *this
|
||||
* \sa normalize(), MatrixBase::normalized() */
|
||||
inline Quaternion<Scalar> normalized() const { return Quaternion<Scalar>(coeffs().normalized()); }
|
||||
|
||||
/** \returns the dot product of \c *this and \a other
|
||||
* Geometrically speaking, the dot product of two unit quaternions
|
||||
* corresponds to the cosine of half the angle between the two rotations.
|
||||
* \sa angularDistance()
|
||||
*/
|
||||
template<class OtherDerived> inline Scalar dot(const QuaternionBase<OtherDerived>& other) const { return coeffs().dot(other.coeffs()); }
|
||||
|
||||
template<class OtherDerived> Scalar angularDistance(const QuaternionBase<OtherDerived>& other) const;
|
||||
|
||||
/** \returns an equivalent 3x3 rotation matrix */
|
||||
Matrix3 toRotationMatrix() const;
|
||||
|
||||
/** \returns the quaternion which transform \a a into \a b through a rotation */
|
||||
template<typename Derived1, typename Derived2>
|
||||
Derived& setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
|
||||
|
||||
template<class OtherDerived> EIGEN_STRONG_INLINE Quaternion<Scalar> operator* (const QuaternionBase<OtherDerived>& q) const;
|
||||
template<class OtherDerived> EIGEN_STRONG_INLINE Derived& operator*= (const QuaternionBase<OtherDerived>& q);
|
||||
|
||||
/** \returns the quaternion describing the inverse rotation */
|
||||
Quaternion<Scalar> inverse() const;
|
||||
|
||||
/** \returns the conjugated quaternion */
|
||||
Quaternion<Scalar> conjugate() const;
|
||||
|
||||
template<class OtherDerived> Quaternion<Scalar> slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const;
|
||||
|
||||
/** \returns \c true if \c *this is approximately equal to \a other, within the precision
|
||||
* determined by \a prec.
|
||||
*
|
||||
* \sa MatrixBase::isApprox() */
|
||||
template<class OtherDerived>
|
||||
bool isApprox(const QuaternionBase<OtherDerived>& other, const RealScalar& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return coeffs().isApprox(other.coeffs(), prec); }
|
||||
|
||||
/** return the result vector of \a v through the rotation*/
|
||||
EIGEN_STRONG_INLINE Vector3 _transformVector(const Vector3& v) const;
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type cast() const
|
||||
{
|
||||
return typename internal::cast_return_type<Derived,Quaternion<NewScalarType> >::type(derived());
|
||||
}
|
||||
|
||||
#ifdef EIGEN_QUATERNIONBASE_PLUGIN
|
||||
# include EIGEN_QUATERNIONBASE_PLUGIN
|
||||
#endif
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* Definition/implementation of Quaternion<Scalar>
|
||||
***************************************************************************/
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Quaternion
|
||||
*
|
||||
* \brief The quaternion class used to represent 3D orientations and rotations
|
||||
*
|
||||
* \tparam _Scalar the scalar type, i.e., the type of the coefficients
|
||||
* \tparam _Options controls the memory alignment of the coefficients. Can be \# AutoAlign or \# DontAlign. Default is AutoAlign.
|
||||
*
|
||||
* This class represents a quaternion \f$ w+xi+yj+zk \f$ that is a convenient representation of
|
||||
* orientations and rotations of objects in three dimensions. Compared to other representations
|
||||
* like Euler angles or 3x3 matrices, quaternions offer the following advantages:
|
||||
* \li \b compact storage (4 scalars)
|
||||
* \li \b efficient to compose (28 flops),
|
||||
* \li \b stable spherical interpolation
|
||||
*
|
||||
* The following two typedefs are provided for convenience:
|
||||
* \li \c Quaternionf for \c float
|
||||
* \li \c Quaterniond for \c double
|
||||
*
|
||||
* \warning Operations interpreting the quaternion as rotation have undefined behavior if the quaternion is not normalized.
|
||||
*
|
||||
* \sa class AngleAxis, class Transform
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
template<typename _Scalar,int _Options>
|
||||
struct traits<Quaternion<_Scalar,_Options> >
|
||||
{
|
||||
typedef Quaternion<_Scalar,_Options> PlainObject;
|
||||
typedef _Scalar Scalar;
|
||||
typedef Matrix<_Scalar,4,1,_Options> Coefficients;
|
||||
enum{
|
||||
IsAligned = internal::traits<Coefficients>::Flags & AlignedBit,
|
||||
Flags = IsAligned ? (AlignedBit | LvalueBit) : LvalueBit
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template<typename _Scalar, int _Options>
|
||||
class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> >
|
||||
{
|
||||
typedef QuaternionBase<Quaternion<_Scalar,_Options> > Base;
|
||||
enum { IsAligned = internal::traits<Quaternion>::IsAligned };
|
||||
|
||||
public:
|
||||
typedef _Scalar Scalar;
|
||||
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Quaternion)
|
||||
using Base::operator*=;
|
||||
|
||||
typedef typename internal::traits<Quaternion>::Coefficients Coefficients;
|
||||
typedef typename Base::AngleAxisType AngleAxisType;
|
||||
|
||||
/** Default constructor leaving the quaternion uninitialized. */
|
||||
inline Quaternion() {}
|
||||
|
||||
/** Constructs and initializes the quaternion \f$ w+xi+yj+zk \f$ from
|
||||
* its four coefficients \a w, \a x, \a y and \a z.
|
||||
*
|
||||
* \warning Note the order of the arguments: the real \a w coefficient first,
|
||||
* while internally the coefficients are stored in the following order:
|
||||
* [\c x, \c y, \c z, \c w]
|
||||
*/
|
||||
inline Quaternion(const Scalar& w, const Scalar& x, const Scalar& y, const Scalar& z) : m_coeffs(x, y, z, w){}
|
||||
|
||||
/** Constructs and initialize a quaternion from the array data */
|
||||
inline Quaternion(const Scalar* data) : m_coeffs(data) {}
|
||||
|
||||
/** Copy constructor */
|
||||
template<class Derived> EIGEN_STRONG_INLINE Quaternion(const QuaternionBase<Derived>& other) { this->Base::operator=(other); }
|
||||
|
||||
/** Constructs and initializes a quaternion from the angle-axis \a aa */
|
||||
explicit inline Quaternion(const AngleAxisType& aa) { *this = aa; }
|
||||
|
||||
/** Constructs and initializes a quaternion from either:
|
||||
* - a rotation matrix expression,
|
||||
* - a 4D vector expression representing quaternion coefficients.
|
||||
*/
|
||||
template<typename Derived>
|
||||
explicit inline Quaternion(const MatrixBase<Derived>& other) { *this = other; }
|
||||
|
||||
/** Explicit copy constructor with scalar conversion */
|
||||
template<typename OtherScalar, int OtherOptions>
|
||||
explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other)
|
||||
{ m_coeffs = other.coeffs().template cast<Scalar>(); }
|
||||
|
||||
template<typename Derived1, typename Derived2>
|
||||
static Quaternion FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b);
|
||||
|
||||
inline Coefficients& coeffs() { return m_coeffs;}
|
||||
inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(bool(IsAligned))
|
||||
|
||||
protected:
|
||||
Coefficients m_coeffs;
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
static EIGEN_STRONG_INLINE void _check_template_params()
|
||||
{
|
||||
EIGEN_STATIC_ASSERT( (_Options & DontAlign) == _Options,
|
||||
INVALID_MATRIX_TEMPLATE_PARAMETERS)
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision quaternion type */
|
||||
typedef Quaternion<float> Quaternionf;
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision quaternion type */
|
||||
typedef Quaternion<double> Quaterniond;
|
||||
|
||||
/***************************************************************************
|
||||
* Specialization of Map<Quaternion<Scalar>>
|
||||
***************************************************************************/
|
||||
|
||||
namespace internal {
|
||||
template<typename _Scalar, int _Options>
|
||||
struct traits<Map<Quaternion<_Scalar>, _Options> > : traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> >
|
||||
{
|
||||
typedef Map<Matrix<_Scalar,4,1>, _Options> Coefficients;
|
||||
};
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
template<typename _Scalar, int _Options>
|
||||
struct traits<Map<const Quaternion<_Scalar>, _Options> > : traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> >
|
||||
{
|
||||
typedef Map<const Matrix<_Scalar,4,1>, _Options> Coefficients;
|
||||
typedef traits<Quaternion<_Scalar, (int(_Options)&Aligned)==Aligned ? AutoAlign : DontAlign> > TraitsBase;
|
||||
enum {
|
||||
Flags = TraitsBase::Flags & ~LvalueBit
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* \brief Quaternion expression mapping a constant memory buffer
|
||||
*
|
||||
* \tparam _Scalar the type of the Quaternion coefficients
|
||||
* \tparam _Options see class Map
|
||||
*
|
||||
* This is a specialization of class Map for Quaternion. This class allows to view
|
||||
* a 4 scalar memory buffer as an Eigen's Quaternion object.
|
||||
*
|
||||
* \sa class Map, class Quaternion, class QuaternionBase
|
||||
*/
|
||||
template<typename _Scalar, int _Options>
|
||||
class Map<const Quaternion<_Scalar>, _Options >
|
||||
: public QuaternionBase<Map<const Quaternion<_Scalar>, _Options> >
|
||||
{
|
||||
typedef QuaternionBase<Map<const Quaternion<_Scalar>, _Options> > Base;
|
||||
|
||||
public:
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename internal::traits<Map>::Coefficients Coefficients;
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
|
||||
using Base::operator*=;
|
||||
|
||||
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
|
||||
*
|
||||
* The pointer \a coeffs must reference the four coefficients of Quaternion in the following order:
|
||||
* \code *coeffs == {x, y, z, w} \endcode
|
||||
*
|
||||
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
|
||||
EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
|
||||
|
||||
inline const Coefficients& coeffs() const { return m_coeffs;}
|
||||
|
||||
protected:
|
||||
const Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* \brief Expression of a quaternion from a memory buffer
|
||||
*
|
||||
* \tparam _Scalar the type of the Quaternion coefficients
|
||||
* \tparam _Options see class Map
|
||||
*
|
||||
* This is a specialization of class Map for Quaternion. This class allows to view
|
||||
* a 4 scalar memory buffer as an Eigen's Quaternion object.
|
||||
*
|
||||
* \sa class Map, class Quaternion, class QuaternionBase
|
||||
*/
|
||||
template<typename _Scalar, int _Options>
|
||||
class Map<Quaternion<_Scalar>, _Options >
|
||||
: public QuaternionBase<Map<Quaternion<_Scalar>, _Options> >
|
||||
{
|
||||
typedef QuaternionBase<Map<Quaternion<_Scalar>, _Options> > Base;
|
||||
|
||||
public:
|
||||
typedef _Scalar Scalar;
|
||||
typedef typename internal::traits<Map>::Coefficients Coefficients;
|
||||
EIGEN_INHERIT_ASSIGNMENT_OPERATORS(Map)
|
||||
using Base::operator*=;
|
||||
|
||||
/** Constructs a Mapped Quaternion object from the pointer \a coeffs
|
||||
*
|
||||
* The pointer \a coeffs must reference the four coefficients of Quaternion in the following order:
|
||||
* \code *coeffs == {x, y, z, w} \endcode
|
||||
*
|
||||
* If the template parameter _Options is set to #Aligned, then the pointer coeffs must be aligned. */
|
||||
EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
|
||||
|
||||
inline Coefficients& coeffs() { return m_coeffs; }
|
||||
inline const Coefficients& coeffs() const { return m_coeffs; }
|
||||
|
||||
protected:
|
||||
Coefficients m_coeffs;
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* Map an unaligned array of single precision scalars as a quaternion */
|
||||
typedef Map<Quaternion<float>, 0> QuaternionMapf;
|
||||
/** \ingroup Geometry_Module
|
||||
* Map an unaligned array of double precision scalars as a quaternion */
|
||||
typedef Map<Quaternion<double>, 0> QuaternionMapd;
|
||||
/** \ingroup Geometry_Module
|
||||
* Map a 16-byte aligned array of single precision scalars as a quaternion */
|
||||
typedef Map<Quaternion<float>, Aligned> QuaternionMapAlignedf;
|
||||
/** \ingroup Geometry_Module
|
||||
* Map a 16-byte aligned array of double precision scalars as a quaternion */
|
||||
typedef Map<Quaternion<double>, Aligned> QuaternionMapAlignedd;
|
||||
|
||||
/***************************************************************************
|
||||
* Implementation of QuaternionBase methods
|
||||
***************************************************************************/
|
||||
|
||||
// Generic Quaternion * Quaternion product
|
||||
// This product can be specialized for a given architecture via the Arch template argument.
|
||||
namespace internal {
|
||||
template<int Arch, class Derived1, class Derived2, typename Scalar, int _Options> struct quat_product
|
||||
{
|
||||
static EIGEN_STRONG_INLINE Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
|
||||
return Quaternion<Scalar>
|
||||
(
|
||||
a.w() * b.w() - a.x() * b.x() - a.y() * b.y() - a.z() * b.z(),
|
||||
a.w() * b.x() + a.x() * b.w() + a.y() * b.z() - a.z() * b.y(),
|
||||
a.w() * b.y() + a.y() * b.w() + a.z() * b.x() - a.x() * b.z(),
|
||||
a.w() * b.z() + a.z() * b.w() + a.x() * b.y() - a.y() * b.x()
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/** \returns the concatenation of two rotations as a quaternion-quaternion product */
|
||||
template <class Derived>
|
||||
template <class OtherDerived>
|
||||
EIGEN_STRONG_INLINE Quaternion<typename internal::traits<Derived>::Scalar>
|
||||
QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) const
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename OtherDerived::Scalar>::value),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
return internal::quat_product<Architecture::Target, Derived, OtherDerived,
|
||||
typename internal::traits<Derived>::Scalar,
|
||||
internal::traits<Derived>::IsAligned && internal::traits<OtherDerived>::IsAligned>::run(*this, other);
|
||||
}
|
||||
|
||||
/** \sa operator*(Quaternion) */
|
||||
template <class Derived>
|
||||
template <class OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator*= (const QuaternionBase<OtherDerived>& other)
|
||||
{
|
||||
derived() = derived() * other.derived();
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** Rotation of a vector by a quaternion.
|
||||
* \remarks If the quaternion is used to rotate several points (>1)
|
||||
* then it is much more efficient to first convert it to a 3x3 Matrix.
|
||||
* Comparison of the operation cost for n transformations:
|
||||
* - Quaternion2: 30n
|
||||
* - Via a Matrix3: 24 + 15n
|
||||
*/
|
||||
template <class Derived>
|
||||
EIGEN_STRONG_INLINE typename QuaternionBase<Derived>::Vector3
|
||||
QuaternionBase<Derived>::_transformVector(const Vector3& v) const
|
||||
{
|
||||
// Note that this algorithm comes from the optimization by hand
|
||||
// of the conversion to a Matrix followed by a Matrix/Vector product.
|
||||
// It appears to be much faster than the common algorithm found
|
||||
// in the literature (30 versus 39 flops). It also requires two
|
||||
// Vector3 as temporaries.
|
||||
Vector3 uv = this->vec().cross(v);
|
||||
uv += uv;
|
||||
return v + this->w() * uv + this->vec().cross(uv);
|
||||
}
|
||||
|
||||
template<class Derived>
|
||||
EIGEN_STRONG_INLINE QuaternionBase<Derived>& QuaternionBase<Derived>::operator=(const QuaternionBase<Derived>& other)
|
||||
{
|
||||
coeffs() = other.coeffs();
|
||||
return derived();
|
||||
}
|
||||
|
||||
template<class Derived>
|
||||
template<class OtherDerived>
|
||||
EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const QuaternionBase<OtherDerived>& other)
|
||||
{
|
||||
coeffs() = other.coeffs();
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** Set \c *this from an angle-axis \a aa and returns a reference to \c *this
|
||||
*/
|
||||
template<class Derived>
|
||||
EIGEN_STRONG_INLINE Derived& QuaternionBase<Derived>::operator=(const AngleAxisType& aa)
|
||||
{
|
||||
using std::cos;
|
||||
using std::sin;
|
||||
Scalar ha = Scalar(0.5)*aa.angle(); // Scalar(0.5) to suppress precision loss warnings
|
||||
this->w() = cos(ha);
|
||||
this->vec() = sin(ha) * aa.axis();
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** Set \c *this from the expression \a xpr:
|
||||
* - if \a xpr is a 4x1 vector, then \a xpr is assumed to be a quaternion
|
||||
* - if \a xpr is a 3x3 matrix, then \a xpr is assumed to be rotation matrix
|
||||
* and \a xpr is converted to a quaternion
|
||||
*/
|
||||
|
||||
template<class Derived>
|
||||
template<class MatrixDerived>
|
||||
inline Derived& QuaternionBase<Derived>::operator=(const MatrixBase<MatrixDerived>& xpr)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<typename Derived::Scalar, typename MatrixDerived::Scalar>::value),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
internal::quaternionbase_assign_impl<MatrixDerived>::run(*this, xpr.derived());
|
||||
return derived();
|
||||
}
|
||||
|
||||
/** Convert the quaternion to a 3x3 rotation matrix. The quaternion is required to
|
||||
* be normalized, otherwise the result is undefined.
|
||||
*/
|
||||
template<class Derived>
|
||||
inline typename QuaternionBase<Derived>::Matrix3
|
||||
QuaternionBase<Derived>::toRotationMatrix(void) const
|
||||
{
|
||||
// NOTE if inlined, then gcc 4.2 and 4.4 get rid of the temporary (not gcc 4.3 !!)
|
||||
// if not inlined then the cost of the return by value is huge ~ +35%,
|
||||
// however, not inlining this function is an order of magnitude slower, so
|
||||
// it has to be inlined, and so the return by value is not an issue
|
||||
Matrix3 res;
|
||||
|
||||
const Scalar tx = Scalar(2)*this->x();
|
||||
const Scalar ty = Scalar(2)*this->y();
|
||||
const Scalar tz = Scalar(2)*this->z();
|
||||
const Scalar twx = tx*this->w();
|
||||
const Scalar twy = ty*this->w();
|
||||
const Scalar twz = tz*this->w();
|
||||
const Scalar txx = tx*this->x();
|
||||
const Scalar txy = ty*this->x();
|
||||
const Scalar txz = tz*this->x();
|
||||
const Scalar tyy = ty*this->y();
|
||||
const Scalar tyz = tz*this->y();
|
||||
const Scalar tzz = tz*this->z();
|
||||
|
||||
res.coeffRef(0,0) = Scalar(1)-(tyy+tzz);
|
||||
res.coeffRef(0,1) = txy-twz;
|
||||
res.coeffRef(0,2) = txz+twy;
|
||||
res.coeffRef(1,0) = txy+twz;
|
||||
res.coeffRef(1,1) = Scalar(1)-(txx+tzz);
|
||||
res.coeffRef(1,2) = tyz-twx;
|
||||
res.coeffRef(2,0) = txz-twy;
|
||||
res.coeffRef(2,1) = tyz+twx;
|
||||
res.coeffRef(2,2) = Scalar(1)-(txx+tyy);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Sets \c *this to be a quaternion representing a rotation between
|
||||
* the two arbitrary vectors \a a and \a b. In other words, the built
|
||||
* rotation represent a rotation sending the line of direction \a a
|
||||
* to the line of direction \a b, both lines passing through the origin.
|
||||
*
|
||||
* \returns a reference to \c *this.
|
||||
*
|
||||
* Note that the two input vectors do \b not have to be normalized, and
|
||||
* do not need to have the same norm.
|
||||
*/
|
||||
template<class Derived>
|
||||
template<typename Derived1, typename Derived2>
|
||||
inline Derived& QuaternionBase<Derived>::setFromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
||||
{
|
||||
using std::max;
|
||||
using std::sqrt;
|
||||
Vector3 v0 = a.normalized();
|
||||
Vector3 v1 = b.normalized();
|
||||
Scalar c = v1.dot(v0);
|
||||
|
||||
// if dot == -1, vectors are nearly opposites
|
||||
// => accurately compute the rotation axis by computing the
|
||||
// intersection of the two planes. This is done by solving:
|
||||
// x^T v0 = 0
|
||||
// x^T v1 = 0
|
||||
// under the constraint:
|
||||
// ||x|| = 1
|
||||
// which yields a singular value problem
|
||||
if (c < Scalar(-1)+NumTraits<Scalar>::dummy_precision())
|
||||
{
|
||||
c = (max)(c,Scalar(-1));
|
||||
Matrix<Scalar,2,3> m; m << v0.transpose(), v1.transpose();
|
||||
JacobiSVD<Matrix<Scalar,2,3> > svd(m, ComputeFullV);
|
||||
Vector3 axis = svd.matrixV().col(2);
|
||||
|
||||
Scalar w2 = (Scalar(1)+c)*Scalar(0.5);
|
||||
this->w() = sqrt(w2);
|
||||
this->vec() = axis * sqrt(Scalar(1) - w2);
|
||||
return derived();
|
||||
}
|
||||
Vector3 axis = v0.cross(v1);
|
||||
Scalar s = sqrt((Scalar(1)+c)*Scalar(2));
|
||||
Scalar invs = Scalar(1)/s;
|
||||
this->vec() = axis * invs;
|
||||
this->w() = s * Scalar(0.5);
|
||||
|
||||
return derived();
|
||||
}
|
||||
|
||||
|
||||
/** Returns a quaternion representing a rotation between
|
||||
* the two arbitrary vectors \a a and \a b. In other words, the built
|
||||
* rotation represent a rotation sending the line of direction \a a
|
||||
* to the line of direction \a b, both lines passing through the origin.
|
||||
*
|
||||
* \returns resulting quaternion
|
||||
*
|
||||
* Note that the two input vectors do \b not have to be normalized, and
|
||||
* do not need to have the same norm.
|
||||
*/
|
||||
template<typename Scalar, int Options>
|
||||
template<typename Derived1, typename Derived2>
|
||||
Quaternion<Scalar,Options> Quaternion<Scalar,Options>::FromTwoVectors(const MatrixBase<Derived1>& a, const MatrixBase<Derived2>& b)
|
||||
{
|
||||
Quaternion quat;
|
||||
quat.setFromTwoVectors(a, b);
|
||||
return quat;
|
||||
}
|
||||
|
||||
|
||||
/** \returns the multiplicative inverse of \c *this
|
||||
* Note that in most cases, i.e., if you simply want the opposite rotation,
|
||||
* and/or the quaternion is normalized, then it is enough to use the conjugate.
|
||||
*
|
||||
* \sa QuaternionBase::conjugate()
|
||||
*/
|
||||
template <class Derived>
|
||||
inline Quaternion<typename internal::traits<Derived>::Scalar> QuaternionBase<Derived>::inverse() const
|
||||
{
|
||||
// FIXME should this function be called multiplicativeInverse and conjugate() be called inverse() or opposite() ??
|
||||
Scalar n2 = this->squaredNorm();
|
||||
if (n2 > Scalar(0))
|
||||
return Quaternion<Scalar>(conjugate().coeffs() / n2);
|
||||
else
|
||||
{
|
||||
// return an invalid result to flag the error
|
||||
return Quaternion<Scalar>(Coefficients::Zero());
|
||||
}
|
||||
}
|
||||
|
||||
/** \returns the conjugate of the \c *this which is equal to the multiplicative inverse
|
||||
* if the quaternion is normalized.
|
||||
* The conjugate of a quaternion represents the opposite rotation.
|
||||
*
|
||||
* \sa Quaternion2::inverse()
|
||||
*/
|
||||
template <class Derived>
|
||||
inline Quaternion<typename internal::traits<Derived>::Scalar>
|
||||
QuaternionBase<Derived>::conjugate() const
|
||||
{
|
||||
return Quaternion<Scalar>(this->w(),-this->x(),-this->y(),-this->z());
|
||||
}
|
||||
|
||||
/** \returns the angle (in radian) between two rotations
|
||||
* \sa dot()
|
||||
*/
|
||||
template <class Derived>
|
||||
template <class OtherDerived>
|
||||
inline typename internal::traits<Derived>::Scalar
|
||||
QuaternionBase<Derived>::angularDistance(const QuaternionBase<OtherDerived>& other) const
|
||||
{
|
||||
using std::atan2;
|
||||
using std::abs;
|
||||
Quaternion<Scalar> d = (*this) * other.conjugate();
|
||||
return Scalar(2) * atan2( d.vec().norm(), abs(d.w()) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** \returns the spherical linear interpolation between the two quaternions
|
||||
* \c *this and \a other at the parameter \a t in [0;1].
|
||||
*
|
||||
* This represents an interpolation for a constant motion between \c *this and \a other,
|
||||
* see also http://en.wikipedia.org/wiki/Slerp.
|
||||
*/
|
||||
template <class Derived>
|
||||
template <class OtherDerived>
|
||||
Quaternion<typename internal::traits<Derived>::Scalar>
|
||||
QuaternionBase<Derived>::slerp(const Scalar& t, const QuaternionBase<OtherDerived>& other) const
|
||||
{
|
||||
using std::acos;
|
||||
using std::sin;
|
||||
using std::abs;
|
||||
static const Scalar one = Scalar(1) - NumTraits<Scalar>::epsilon();
|
||||
Scalar d = this->dot(other);
|
||||
Scalar absD = abs(d);
|
||||
|
||||
Scalar scale0;
|
||||
Scalar scale1;
|
||||
|
||||
if(absD>=one)
|
||||
{
|
||||
scale0 = Scalar(1) - t;
|
||||
scale1 = t;
|
||||
}
|
||||
else
|
||||
{
|
||||
// theta is the angle between the 2 quaternions
|
||||
Scalar theta = acos(absD);
|
||||
Scalar sinTheta = sin(theta);
|
||||
|
||||
scale0 = sin( ( Scalar(1) - t ) * theta) / sinTheta;
|
||||
scale1 = sin( ( t * theta) ) / sinTheta;
|
||||
}
|
||||
if(d<Scalar(0)) scale1 = -scale1;
|
||||
|
||||
return Quaternion<Scalar>(scale0 * coeffs() + scale1 * other.coeffs());
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
// set from a rotation matrix
|
||||
template<typename Other>
|
||||
struct quaternionbase_assign_impl<Other,3,3>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
typedef DenseIndex Index;
|
||||
template<class Derived> static inline void run(QuaternionBase<Derived>& q, const Other& mat)
|
||||
{
|
||||
using std::sqrt;
|
||||
// This algorithm comes from "Quaternion Calculus and Fast Animation",
|
||||
// Ken Shoemake, 1987 SIGGRAPH course notes
|
||||
Scalar t = mat.trace();
|
||||
if (t > Scalar(0))
|
||||
{
|
||||
t = sqrt(t + Scalar(1.0));
|
||||
q.w() = Scalar(0.5)*t;
|
||||
t = Scalar(0.5)/t;
|
||||
q.x() = (mat.coeff(2,1) - mat.coeff(1,2)) * t;
|
||||
q.y() = (mat.coeff(0,2) - mat.coeff(2,0)) * t;
|
||||
q.z() = (mat.coeff(1,0) - mat.coeff(0,1)) * t;
|
||||
}
|
||||
else
|
||||
{
|
||||
DenseIndex i = 0;
|
||||
if (mat.coeff(1,1) > mat.coeff(0,0))
|
||||
i = 1;
|
||||
if (mat.coeff(2,2) > mat.coeff(i,i))
|
||||
i = 2;
|
||||
DenseIndex j = (i+1)%3;
|
||||
DenseIndex k = (j+1)%3;
|
||||
|
||||
t = sqrt(mat.coeff(i,i)-mat.coeff(j,j)-mat.coeff(k,k) + Scalar(1.0));
|
||||
q.coeffs().coeffRef(i) = Scalar(0.5) * t;
|
||||
t = Scalar(0.5)/t;
|
||||
q.w() = (mat.coeff(k,j)-mat.coeff(j,k))*t;
|
||||
q.coeffs().coeffRef(j) = (mat.coeff(j,i)+mat.coeff(i,j))*t;
|
||||
q.coeffs().coeffRef(k) = (mat.coeff(k,i)+mat.coeff(i,k))*t;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// set from a vector of coefficients assumed to be a quaternion
|
||||
template<typename Other>
|
||||
struct quaternionbase_assign_impl<Other,4,1>
|
||||
{
|
||||
typedef typename Other::Scalar Scalar;
|
||||
template<class Derived> static inline void run(QuaternionBase<Derived>& q, const Other& vec)
|
||||
{
|
||||
q.coeffs() = vec;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_QUATERNION_H
|
||||
160
3rdparty/eigen3/Eigen/src/Geometry/Rotation2D.h
vendored
Normal file
160
3rdparty/eigen3/Eigen/src/Geometry/Rotation2D.h
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_ROTATION2D_H
|
||||
#define EIGEN_ROTATION2D_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Rotation2D
|
||||
*
|
||||
* \brief Represents a rotation/orientation in a 2 dimensional space.
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients
|
||||
*
|
||||
* This class is equivalent to a single scalar representing a counter clock wise rotation
|
||||
* as a single angle in radian. It provides some additional features such as the automatic
|
||||
* conversion from/to a 2x2 rotation matrix. Moreover this class aims to provide a similar
|
||||
* interface to Quaternion in order to facilitate the writing of generic algorithms
|
||||
* dealing with rotations.
|
||||
*
|
||||
* \sa class Quaternion, class Transform
|
||||
*/
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<typename _Scalar> struct traits<Rotation2D<_Scalar> >
|
||||
{
|
||||
typedef _Scalar Scalar;
|
||||
};
|
||||
} // end namespace internal
|
||||
|
||||
template<typename _Scalar>
|
||||
class Rotation2D : public RotationBase<Rotation2D<_Scalar>,2>
|
||||
{
|
||||
typedef RotationBase<Rotation2D<_Scalar>,2> Base;
|
||||
|
||||
public:
|
||||
|
||||
using Base::operator*;
|
||||
|
||||
enum { Dim = 2 };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
typedef Matrix<Scalar,2,1> Vector2;
|
||||
typedef Matrix<Scalar,2,2> Matrix2;
|
||||
|
||||
protected:
|
||||
|
||||
Scalar m_angle;
|
||||
|
||||
public:
|
||||
|
||||
/** Construct a 2D counter clock wise rotation from the angle \a a in radian. */
|
||||
inline Rotation2D(const Scalar& a) : m_angle(a) {}
|
||||
|
||||
/** Default constructor wihtout initialization. The represented rotation is undefined. */
|
||||
Rotation2D() {}
|
||||
|
||||
/** \returns the rotation angle */
|
||||
inline Scalar angle() const { return m_angle; }
|
||||
|
||||
/** \returns a read-write reference to the rotation angle */
|
||||
inline Scalar& angle() { return m_angle; }
|
||||
|
||||
/** \returns the inverse rotation */
|
||||
inline Rotation2D inverse() const { return -m_angle; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Rotation2D operator*(const Rotation2D& other) const
|
||||
{ return m_angle + other.m_angle; }
|
||||
|
||||
/** Concatenates two rotations */
|
||||
inline Rotation2D& operator*=(const Rotation2D& other)
|
||||
{ m_angle += other.m_angle; return *this; }
|
||||
|
||||
/** Applies the rotation to a 2D vector */
|
||||
Vector2 operator* (const Vector2& vec) const
|
||||
{ return toRotationMatrix() * vec; }
|
||||
|
||||
template<typename Derived>
|
||||
Rotation2D& fromRotationMatrix(const MatrixBase<Derived>& m);
|
||||
Matrix2 toRotationMatrix() const;
|
||||
|
||||
/** \returns the spherical interpolation between \c *this and \a other using
|
||||
* parameter \a t. It is in fact equivalent to a linear interpolation.
|
||||
*/
|
||||
inline Rotation2D slerp(const Scalar& t, const Rotation2D& other) const
|
||||
{ return m_angle * (1-t) + other.angle() * t; }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Rotation2D,Rotation2D<NewScalarType> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Rotation2D(const Rotation2D<OtherScalarType>& other)
|
||||
{
|
||||
m_angle = Scalar(other.angle());
|
||||
}
|
||||
|
||||
static inline Rotation2D Identity() { return Rotation2D(0); }
|
||||
|
||||
/** \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, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return internal::isApprox(m_angle,other.m_angle, prec); }
|
||||
};
|
||||
|
||||
/** \ingroup Geometry_Module
|
||||
* single precision 2D rotation type */
|
||||
typedef Rotation2D<float> Rotation2Df;
|
||||
/** \ingroup Geometry_Module
|
||||
* double precision 2D rotation type */
|
||||
typedef Rotation2D<double> Rotation2Dd;
|
||||
|
||||
/** Set \c *this from a 2x2 rotation matrix \a mat.
|
||||
* In other words, this function extract the rotation angle
|
||||
* from the rotation matrix.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
template<typename Derived>
|
||||
Rotation2D<Scalar>& Rotation2D<Scalar>::fromRotationMatrix(const MatrixBase<Derived>& mat)
|
||||
{
|
||||
using std::atan2;
|
||||
EIGEN_STATIC_ASSERT(Derived::RowsAtCompileTime==2 && Derived::ColsAtCompileTime==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
m_angle = atan2(mat.coeff(1,0), mat.coeff(0,0));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Constructs and \returns an equivalent 2x2 rotation matrix.
|
||||
*/
|
||||
template<typename Scalar>
|
||||
typename Rotation2D<Scalar>::Matrix2
|
||||
Rotation2D<Scalar>::toRotationMatrix(void) const
|
||||
{
|
||||
using std::sin;
|
||||
using std::cos;
|
||||
Scalar sinA = sin(m_angle);
|
||||
Scalar cosA = cos(m_angle);
|
||||
return (Matrix2() << cosA, -sinA, sinA, cosA).finished();
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ROTATION2D_H
|
||||
206
3rdparty/eigen3/Eigen/src/Geometry/RotationBase.h
vendored
Normal file
206
3rdparty/eigen3/Eigen/src/Geometry/RotationBase.h
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_ROTATIONBASE_H
|
||||
#define EIGEN_ROTATIONBASE_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// forward declaration
|
||||
namespace internal {
|
||||
template<typename RotationDerived, typename MatrixType, bool IsVector=MatrixType::IsVectorAtCompileTime>
|
||||
struct rotation_base_generic_product_selector;
|
||||
}
|
||||
|
||||
/** \class RotationBase
|
||||
*
|
||||
* \brief Common base class for compact rotation representations
|
||||
*
|
||||
* \param Derived is the derived type, i.e., a rotation type
|
||||
* \param _Dim the dimension of the space
|
||||
*/
|
||||
template<typename Derived, int _Dim>
|
||||
class RotationBase
|
||||
{
|
||||
public:
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef typename internal::traits<Derived>::Scalar Scalar;
|
||||
|
||||
/** corresponding linear transformation matrix type */
|
||||
typedef Matrix<Scalar,Dim,Dim> RotationMatrixType;
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
|
||||
public:
|
||||
inline const Derived& derived() const { return *static_cast<const Derived*>(this); }
|
||||
inline Derived& derived() { return *static_cast<Derived*>(this); }
|
||||
|
||||
/** \returns an equivalent rotation matrix */
|
||||
inline RotationMatrixType toRotationMatrix() const { return derived().toRotationMatrix(); }
|
||||
|
||||
/** \returns an equivalent rotation matrix
|
||||
* This function is added to be conform with the Transform class' naming scheme.
|
||||
*/
|
||||
inline RotationMatrixType matrix() const { return derived().toRotationMatrix(); }
|
||||
|
||||
/** \returns the inverse rotation */
|
||||
inline Derived inverse() const { return derived().inverse(); }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a translation \a t */
|
||||
inline Transform<Scalar,Dim,Isometry> operator*(const Translation<Scalar,Dim>& t) const
|
||||
{ return Transform<Scalar,Dim,Isometry>(*this) * t; }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a uniform scaling \a s */
|
||||
inline RotationMatrixType operator*(const UniformScaling<Scalar>& s) const
|
||||
{ return toRotationMatrix() * s.factor(); }
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a generic expression \a e
|
||||
* \a e can be:
|
||||
* - a DimxDim linear transformation matrix
|
||||
* - a DimxDim diagonal matrix (axis aligned scaling)
|
||||
* - a vector of size Dim
|
||||
*/
|
||||
template<typename OtherDerived>
|
||||
EIGEN_STRONG_INLINE typename internal::rotation_base_generic_product_selector<Derived,OtherDerived,OtherDerived::IsVectorAtCompileTime>::ReturnType
|
||||
operator*(const EigenBase<OtherDerived>& e) const
|
||||
{ return internal::rotation_base_generic_product_selector<Derived,OtherDerived>::run(derived(), e.derived()); }
|
||||
|
||||
/** \returns the concatenation of a linear transformation \a l with the rotation \a r */
|
||||
template<typename OtherDerived> friend
|
||||
inline RotationMatrixType operator*(const EigenBase<OtherDerived>& l, const Derived& r)
|
||||
{ return l.derived() * r.toRotationMatrix(); }
|
||||
|
||||
/** \returns the concatenation of a scaling \a l with the rotation \a r */
|
||||
friend inline Transform<Scalar,Dim,Affine> operator*(const DiagonalMatrix<Scalar,Dim>& l, const Derived& r)
|
||||
{
|
||||
Transform<Scalar,Dim,Affine> res(r);
|
||||
res.linear().applyOnTheLeft(l);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** \returns the concatenation of the rotation \c *this with a transformation \a t */
|
||||
template<int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,Mode> operator*(const Transform<Scalar,Dim,Mode,Options>& t) const
|
||||
{ return toRotationMatrix() * t; }
|
||||
|
||||
template<typename OtherVectorType>
|
||||
inline VectorType _transformVector(const OtherVectorType& v) const
|
||||
{ return toRotationMatrix() * v; }
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
|
||||
// implementation of the generic product rotation * matrix
|
||||
template<typename RotationDerived, typename MatrixType>
|
||||
struct rotation_base_generic_product_selector<RotationDerived,MatrixType,false>
|
||||
{
|
||||
enum { Dim = RotationDerived::Dim };
|
||||
typedef Matrix<typename RotationDerived::Scalar,Dim,Dim> ReturnType;
|
||||
static inline ReturnType run(const RotationDerived& r, const MatrixType& m)
|
||||
{ return r.toRotationMatrix() * m; }
|
||||
};
|
||||
|
||||
template<typename RotationDerived, typename Scalar, int Dim, int MaxDim>
|
||||
struct rotation_base_generic_product_selector< RotationDerived, DiagonalMatrix<Scalar,Dim,MaxDim>, false >
|
||||
{
|
||||
typedef Transform<Scalar,Dim,Affine> ReturnType;
|
||||
static inline ReturnType run(const RotationDerived& r, const DiagonalMatrix<Scalar,Dim,MaxDim>& m)
|
||||
{
|
||||
ReturnType res(r);
|
||||
res.linear() *= m;
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename RotationDerived,typename OtherVectorType>
|
||||
struct rotation_base_generic_product_selector<RotationDerived,OtherVectorType,true>
|
||||
{
|
||||
enum { Dim = RotationDerived::Dim };
|
||||
typedef Matrix<typename RotationDerived::Scalar,Dim,1> ReturnType;
|
||||
static EIGEN_STRONG_INLINE ReturnType run(const RotationDerived& r, const OtherVectorType& v)
|
||||
{
|
||||
return r._transformVector(v);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* \brief Constructs a Dim x Dim rotation matrix from the rotation \a r
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||
template<typename OtherDerived>
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::Matrix(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
||||
*this = r.toRotationMatrix();
|
||||
}
|
||||
|
||||
/** \geometry_module
|
||||
*
|
||||
* \brief Set a Dim x Dim rotation matrix from the rotation \a r
|
||||
*/
|
||||
template<typename _Scalar, int _Rows, int _Cols, int _Storage, int _MaxRows, int _MaxCols>
|
||||
template<typename OtherDerived>
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>&
|
||||
Matrix<_Scalar, _Rows, _Cols, _Storage, _MaxRows, _MaxCols>
|
||||
::operator=(const RotationBase<OtherDerived,ColsAtCompileTime>& r)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(Matrix,int(OtherDerived::Dim),int(OtherDerived::Dim))
|
||||
return *this = r.toRotationMatrix();
|
||||
}
|
||||
|
||||
namespace internal {
|
||||
|
||||
/** \internal
|
||||
*
|
||||
* Helper function to return an arbitrary rotation object to a rotation matrix.
|
||||
*
|
||||
* \param Scalar the numeric type of the matrix coefficients
|
||||
* \param Dim the dimension of the current space
|
||||
*
|
||||
* It returns a Dim x Dim fixed size matrix.
|
||||
*
|
||||
* Default specializations are provided for:
|
||||
* - any scalar type (2D),
|
||||
* - any matrix expression,
|
||||
* - any type based on RotationBase (e.g., Quaternion, AngleAxis, Rotation2D)
|
||||
*
|
||||
* Currently toRotationMatrix is only used by Transform.
|
||||
*
|
||||
* \sa class Transform, class Rotation2D, class Quaternion, class AngleAxis
|
||||
*/
|
||||
template<typename Scalar, int Dim>
|
||||
static inline Matrix<Scalar,2,2> toRotationMatrix(const Scalar& s)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(Dim==2,YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return Rotation2D<Scalar>(s).toRotationMatrix();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, typename OtherDerived>
|
||||
static inline Matrix<Scalar,Dim,Dim> toRotationMatrix(const RotationBase<OtherDerived,Dim>& r)
|
||||
{
|
||||
return r.toRotationMatrix();
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim, typename OtherDerived>
|
||||
static inline const MatrixBase<OtherDerived>& toRotationMatrix(const MatrixBase<OtherDerived>& mat)
|
||||
{
|
||||
EIGEN_STATIC_ASSERT(OtherDerived::RowsAtCompileTime==Dim && OtherDerived::ColsAtCompileTime==Dim,
|
||||
YOU_MADE_A_PROGRAMMING_MISTAKE)
|
||||
return mat;
|
||||
}
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_ROTATIONBASE_H
|
||||
166
3rdparty/eigen3/Eigen/src/Geometry/Scaling.h
vendored
Normal file
166
3rdparty/eigen3/Eigen/src/Geometry/Scaling.h
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_SCALING_H
|
||||
#define EIGEN_SCALING_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Scaling
|
||||
*
|
||||
* \brief Represents a generic uniform scaling transformation
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients.
|
||||
*
|
||||
* This class represent a uniform scaling transformation. It is the return
|
||||
* type of Scaling(Scalar), and most of the time this is the only way it
|
||||
* is used. In particular, this class is not aimed to be used to store a scaling transformation,
|
||||
* but rather to make easier the constructions and updates of Transform objects.
|
||||
*
|
||||
* To represent an axis aligned scaling, use the DiagonalMatrix class.
|
||||
*
|
||||
* \sa Scaling(), class DiagonalMatrix, MatrixBase::asDiagonal(), class Translation, class Transform
|
||||
*/
|
||||
template<typename _Scalar>
|
||||
class UniformScaling
|
||||
{
|
||||
public:
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
|
||||
protected:
|
||||
|
||||
Scalar m_factor;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
UniformScaling() {}
|
||||
/** Constructs and initialize a uniform scaling transformation */
|
||||
explicit inline UniformScaling(const Scalar& s) : m_factor(s) {}
|
||||
|
||||
inline const Scalar& factor() const { return m_factor; }
|
||||
inline Scalar& factor() { return m_factor; }
|
||||
|
||||
/** Concatenates two uniform scaling */
|
||||
inline UniformScaling operator* (const UniformScaling& other) const
|
||||
{ return UniformScaling(m_factor * other.factor()); }
|
||||
|
||||
/** Concatenates a uniform scaling and a translation */
|
||||
template<int Dim>
|
||||
inline Transform<Scalar,Dim,Affine> operator* (const Translation<Scalar,Dim>& t) const;
|
||||
|
||||
/** Concatenates a uniform scaling and an affine transformation */
|
||||
template<int Dim, int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Mode)> operator* (const Transform<Scalar,Dim, Mode, Options>& t) const
|
||||
{
|
||||
Transform<Scalar,Dim,(int(Mode)==int(Isometry)?Affine:Mode)> res = t;
|
||||
res.prescale(factor());
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Concatenates a uniform scaling and a linear transformation matrix */
|
||||
// TODO returns an expression
|
||||
template<typename Derived>
|
||||
inline typename internal::plain_matrix_type<Derived>::type operator* (const MatrixBase<Derived>& other) const
|
||||
{ return other * m_factor; }
|
||||
|
||||
template<typename Derived,int Dim>
|
||||
inline Matrix<Scalar,Dim,Dim> operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{ return r.toRotationMatrix() * m_factor; }
|
||||
|
||||
/** \returns the inverse scaling */
|
||||
inline UniformScaling inverse() const
|
||||
{ return UniformScaling(Scalar(1)/m_factor); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline UniformScaling<NewScalarType> cast() const
|
||||
{ return UniformScaling<NewScalarType>(NewScalarType(m_factor)); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit UniformScaling(const UniformScaling<OtherScalarType>& other)
|
||||
{ m_factor = Scalar(other.factor()); }
|
||||
|
||||
/** \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 UniformScaling& other, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return internal::isApprox(m_factor, other.factor(), prec); }
|
||||
|
||||
};
|
||||
|
||||
/** Concatenates a linear transformation matrix and a uniform scaling */
|
||||
// NOTE this operator is defiend in MatrixBase and not as a friend function
|
||||
// of UniformScaling to fix an internal crash of Intel's ICC
|
||||
template<typename Derived> typename MatrixBase<Derived>::ScalarMultipleReturnType
|
||||
MatrixBase<Derived>::operator*(const UniformScaling<Scalar>& s) const
|
||||
{ return derived() * s.factor(); }
|
||||
|
||||
/** Constructs a uniform scaling from scale factor \a s */
|
||||
static inline UniformScaling<float> Scaling(float s) { return UniformScaling<float>(s); }
|
||||
/** Constructs a uniform scaling from scale factor \a s */
|
||||
static inline UniformScaling<double> Scaling(double s) { return UniformScaling<double>(s); }
|
||||
/** Constructs a uniform scaling from scale factor \a s */
|
||||
template<typename RealScalar>
|
||||
static inline UniformScaling<std::complex<RealScalar> > Scaling(const std::complex<RealScalar>& s)
|
||||
{ return UniformScaling<std::complex<RealScalar> >(s); }
|
||||
|
||||
/** Constructs a 2D axis aligned scaling */
|
||||
template<typename Scalar>
|
||||
static inline DiagonalMatrix<Scalar,2> Scaling(const Scalar& sx, const Scalar& sy)
|
||||
{ return DiagonalMatrix<Scalar,2>(sx, sy); }
|
||||
/** Constructs a 3D axis aligned scaling */
|
||||
template<typename Scalar>
|
||||
static inline DiagonalMatrix<Scalar,3> Scaling(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
{ return DiagonalMatrix<Scalar,3>(sx, sy, sz); }
|
||||
|
||||
/** Constructs an axis aligned scaling expression from vector expression \a coeffs
|
||||
* This is an alias for coeffs.asDiagonal()
|
||||
*/
|
||||
template<typename Derived>
|
||||
static inline const DiagonalWrapper<const Derived> Scaling(const MatrixBase<Derived>& coeffs)
|
||||
{ return coeffs.asDiagonal(); }
|
||||
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
/** \deprecated */
|
||||
typedef DiagonalMatrix<float, 2> AlignedScaling2f;
|
||||
/** \deprecated */
|
||||
typedef DiagonalMatrix<double,2> AlignedScaling2d;
|
||||
/** \deprecated */
|
||||
typedef DiagonalMatrix<float, 3> AlignedScaling3f;
|
||||
/** \deprecated */
|
||||
typedef DiagonalMatrix<double,3> AlignedScaling3d;
|
||||
//@}
|
||||
|
||||
template<typename Scalar>
|
||||
template<int Dim>
|
||||
inline Transform<Scalar,Dim,Affine>
|
||||
UniformScaling<Scalar>::operator* (const Translation<Scalar,Dim>& t) const
|
||||
{
|
||||
Transform<Scalar,Dim,Affine> res;
|
||||
res.matrix().setZero();
|
||||
res.linear().diagonal().fill(factor());
|
||||
res.translation() = factor() * t.vector();
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_SCALING_H
|
||||
1474
3rdparty/eigen3/Eigen/src/Geometry/Transform.h
vendored
Normal file
1474
3rdparty/eigen3/Eigen/src/Geometry/Transform.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
208
3rdparty/eigen3/Eigen/src/Geometry/Translation.h
vendored
Normal file
208
3rdparty/eigen3/Eigen/src/Geometry/Translation.h
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_TRANSLATION_H
|
||||
#define EIGEN_TRANSLATION_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
/** \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \class Translation
|
||||
*
|
||||
* \brief Represents a translation transformation
|
||||
*
|
||||
* \param _Scalar the scalar type, i.e., the type of the coefficients.
|
||||
* \param _Dim the dimension of the space, can be a compile time value or Dynamic
|
||||
*
|
||||
* \note This class is not aimed to be used to store a translation transformation,
|
||||
* but rather to make easier the constructions and updates of Transform objects.
|
||||
*
|
||||
* \sa class Scaling, class Transform
|
||||
*/
|
||||
template<typename _Scalar, int _Dim>
|
||||
class Translation
|
||||
{
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_Dim)
|
||||
/** dimension of the space */
|
||||
enum { Dim = _Dim };
|
||||
/** the scalar type of the coefficients */
|
||||
typedef _Scalar Scalar;
|
||||
/** corresponding vector type */
|
||||
typedef Matrix<Scalar,Dim,1> VectorType;
|
||||
/** corresponding linear transformation matrix type */
|
||||
typedef Matrix<Scalar,Dim,Dim> LinearMatrixType;
|
||||
/** corresponding affine transformation type */
|
||||
typedef Transform<Scalar,Dim,Affine> AffineTransformType;
|
||||
/** corresponding isometric transformation type */
|
||||
typedef Transform<Scalar,Dim,Isometry> IsometryTransformType;
|
||||
|
||||
protected:
|
||||
|
||||
VectorType m_coeffs;
|
||||
|
||||
public:
|
||||
|
||||
/** Default constructor without initialization. */
|
||||
Translation() {}
|
||||
/** */
|
||||
inline Translation(const Scalar& sx, const Scalar& sy)
|
||||
{
|
||||
eigen_assert(Dim==2);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
}
|
||||
/** */
|
||||
inline Translation(const Scalar& sx, const Scalar& sy, const Scalar& sz)
|
||||
{
|
||||
eigen_assert(Dim==3);
|
||||
m_coeffs.x() = sx;
|
||||
m_coeffs.y() = sy;
|
||||
m_coeffs.z() = sz;
|
||||
}
|
||||
/** Constructs and initialize the translation transformation from a vector of translation coefficients */
|
||||
explicit inline Translation(const VectorType& vector) : m_coeffs(vector) {}
|
||||
|
||||
/** \brief Retruns the x-translation by value. **/
|
||||
inline Scalar x() const { return m_coeffs.x(); }
|
||||
/** \brief Retruns the y-translation by value. **/
|
||||
inline Scalar y() const { return m_coeffs.y(); }
|
||||
/** \brief Retruns the z-translation by value. **/
|
||||
inline Scalar z() const { return m_coeffs.z(); }
|
||||
|
||||
/** \brief Retruns the x-translation as a reference. **/
|
||||
inline Scalar& x() { return m_coeffs.x(); }
|
||||
/** \brief Retruns the y-translation as a reference. **/
|
||||
inline Scalar& y() { return m_coeffs.y(); }
|
||||
/** \brief Retruns the z-translation as a reference. **/
|
||||
inline Scalar& z() { return m_coeffs.z(); }
|
||||
|
||||
const VectorType& vector() const { return m_coeffs; }
|
||||
VectorType& vector() { return m_coeffs; }
|
||||
|
||||
const VectorType& translation() const { return m_coeffs; }
|
||||
VectorType& translation() { return m_coeffs; }
|
||||
|
||||
/** Concatenates two translation */
|
||||
inline Translation operator* (const Translation& other) const
|
||||
{ return Translation(m_coeffs + other.m_coeffs); }
|
||||
|
||||
/** Concatenates a translation and a uniform scaling */
|
||||
inline AffineTransformType operator* (const UniformScaling<Scalar>& other) const;
|
||||
|
||||
/** Concatenates a translation and a linear transformation */
|
||||
template<typename OtherDerived>
|
||||
inline AffineTransformType operator* (const EigenBase<OtherDerived>& linear) const;
|
||||
|
||||
/** Concatenates a translation and a rotation */
|
||||
template<typename Derived>
|
||||
inline IsometryTransformType operator*(const RotationBase<Derived,Dim>& r) const
|
||||
{ return *this * IsometryTransformType(r); }
|
||||
|
||||
/** \returns the concatenation of a linear transformation \a l with the translation \a t */
|
||||
// its a nightmare to define a templated friend function outside its declaration
|
||||
template<typename OtherDerived> friend
|
||||
inline AffineTransformType operator*(const EigenBase<OtherDerived>& linear, const Translation& t)
|
||||
{
|
||||
AffineTransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear() = linear.derived();
|
||||
res.translation() = linear.derived() * t.m_coeffs;
|
||||
res.matrix().row(Dim).setZero();
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Concatenates a translation and a transformation */
|
||||
template<int Mode, int Options>
|
||||
inline Transform<Scalar,Dim,Mode> operator* (const Transform<Scalar,Dim,Mode,Options>& t) const
|
||||
{
|
||||
Transform<Scalar,Dim,Mode> res = t;
|
||||
res.pretranslate(m_coeffs);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** Applies translation to vector */
|
||||
template<typename Derived>
|
||||
inline typename internal::enable_if<Derived::IsVectorAtCompileTime,VectorType>::type
|
||||
operator* (const MatrixBase<Derived>& vec) const
|
||||
{ return m_coeffs + vec.derived(); }
|
||||
|
||||
/** \returns the inverse translation (opposite) */
|
||||
Translation inverse() const { return Translation(-m_coeffs); }
|
||||
|
||||
Translation& operator=(const Translation& other)
|
||||
{
|
||||
m_coeffs = other.m_coeffs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
static const Translation Identity() { return Translation(VectorType::Zero()); }
|
||||
|
||||
/** \returns \c *this with scalar type casted to \a NewScalarType
|
||||
*
|
||||
* Note that if \a NewScalarType is equal to the current scalar type of \c *this
|
||||
* then this function smartly returns a const reference to \c *this.
|
||||
*/
|
||||
template<typename NewScalarType>
|
||||
inline typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type cast() const
|
||||
{ return typename internal::cast_return_type<Translation,Translation<NewScalarType,Dim> >::type(*this); }
|
||||
|
||||
/** Copy constructor with scalar type conversion */
|
||||
template<typename OtherScalarType>
|
||||
inline explicit Translation(const Translation<OtherScalarType,Dim>& other)
|
||||
{ m_coeffs = other.vector().template cast<Scalar>(); }
|
||||
|
||||
/** \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, const typename NumTraits<Scalar>::Real& prec = NumTraits<Scalar>::dummy_precision()) const
|
||||
{ return m_coeffs.isApprox(other.m_coeffs, prec); }
|
||||
|
||||
};
|
||||
|
||||
/** \addtogroup Geometry_Module */
|
||||
//@{
|
||||
typedef Translation<float, 2> Translation2f;
|
||||
typedef Translation<double,2> Translation2d;
|
||||
typedef Translation<float, 3> Translation3f;
|
||||
typedef Translation<double,3> Translation3d;
|
||||
//@}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
inline typename Translation<Scalar,Dim>::AffineTransformType
|
||||
Translation<Scalar,Dim>::operator* (const UniformScaling<Scalar>& other) const
|
||||
{
|
||||
AffineTransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear().diagonal().fill(other.factor());
|
||||
res.translation() = m_coeffs;
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename Scalar, int Dim>
|
||||
template<typename OtherDerived>
|
||||
inline typename Translation<Scalar,Dim>::AffineTransformType
|
||||
Translation<Scalar,Dim>::operator* (const EigenBase<OtherDerived>& linear) const
|
||||
{
|
||||
AffineTransformType res;
|
||||
res.matrix().setZero();
|
||||
res.linear() = linear.derived();
|
||||
res.translation() = m_coeffs;
|
||||
res.matrix().row(Dim).setZero();
|
||||
res(Dim,Dim) = Scalar(1);
|
||||
return res;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_TRANSLATION_H
|
||||
177
3rdparty/eigen3/Eigen/src/Geometry/Umeyama.h
vendored
Normal file
177
3rdparty/eigen3/Eigen/src/Geometry/Umeyama.h
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 Hauke Heibel <hauke.heibel@gmail.com>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_UMEYAMA_H
|
||||
#define EIGEN_UMEYAMA_H
|
||||
|
||||
// This file requires the user to include
|
||||
// * Eigen/Core
|
||||
// * Eigen/LU
|
||||
// * Eigen/SVD
|
||||
// * Eigen/Array
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
#ifndef EIGEN_PARSED_BY_DOXYGEN
|
||||
|
||||
// These helpers are required since it allows to use mixed types as parameters
|
||||
// for the Umeyama. The problem with mixed parameters is that the return type
|
||||
// cannot trivially be deduced when float and double types are mixed.
|
||||
namespace internal {
|
||||
|
||||
// Compile time return type deduction for different MatrixBase types.
|
||||
// Different means here different alignment and parameters but the same underlying
|
||||
// real scalar type.
|
||||
template<typename MatrixType, typename OtherMatrixType>
|
||||
struct umeyama_transform_matrix_type
|
||||
{
|
||||
enum {
|
||||
MinRowsAtCompileTime = EIGEN_SIZE_MIN_PREFER_DYNAMIC(MatrixType::RowsAtCompileTime, OtherMatrixType::RowsAtCompileTime),
|
||||
|
||||
// When possible we want to choose some small fixed size value since the result
|
||||
// is likely to fit on the stack. So here, EIGEN_SIZE_MIN_PREFER_DYNAMIC is not what we want.
|
||||
HomogeneousDimension = int(MinRowsAtCompileTime) == Dynamic ? Dynamic : int(MinRowsAtCompileTime)+1
|
||||
};
|
||||
|
||||
typedef Matrix<typename traits<MatrixType>::Scalar,
|
||||
HomogeneousDimension,
|
||||
HomogeneousDimension,
|
||||
AutoAlign | (traits<MatrixType>::Flags & RowMajorBit ? RowMajor : ColMajor),
|
||||
HomogeneousDimension,
|
||||
HomogeneousDimension
|
||||
> type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \geometry_module \ingroup Geometry_Module
|
||||
*
|
||||
* \brief Returns the transformation between two point sets.
|
||||
*
|
||||
* The algorithm is based on:
|
||||
* "Least-squares estimation of transformation parameters between two point patterns",
|
||||
* Shinji Umeyama, PAMI 1991, DOI: 10.1109/34.88573
|
||||
*
|
||||
* It estimates parameters \f$ c, \mathbf{R}, \f$ and \f$ \mathbf{t} \f$ such that
|
||||
* \f{align*}
|
||||
* \frac{1}{n} \sum_{i=1}^n \vert\vert y_i - (c\mathbf{R}x_i + \mathbf{t}) \vert\vert_2^2
|
||||
* \f}
|
||||
* is minimized.
|
||||
*
|
||||
* The algorithm is based on the analysis of the covariance matrix
|
||||
* \f$ \Sigma_{\mathbf{x}\mathbf{y}} \in \mathbb{R}^{d \times d} \f$
|
||||
* of the input point sets \f$ \mathbf{x} \f$ and \f$ \mathbf{y} \f$ where
|
||||
* \f$d\f$ is corresponding to the dimension (which is typically small).
|
||||
* The analysis is involving the SVD having a complexity of \f$O(d^3)\f$
|
||||
* though the actual computational effort lies in the covariance
|
||||
* matrix computation which has an asymptotic lower bound of \f$O(dm)\f$ when
|
||||
* the input point sets have dimension \f$d \times m\f$.
|
||||
*
|
||||
* Currently the method is working only for floating point matrices.
|
||||
*
|
||||
* \todo Should the return type of umeyama() become a Transform?
|
||||
*
|
||||
* \param src Source points \f$ \mathbf{x} = \left( x_1, \hdots, x_n \right) \f$.
|
||||
* \param dst Destination points \f$ \mathbf{y} = \left( y_1, \hdots, y_n \right) \f$.
|
||||
* \param with_scaling Sets \f$ c=1 \f$ when <code>false</code> is passed.
|
||||
* \return The homogeneous transformation
|
||||
* \f{align*}
|
||||
* T = \begin{bmatrix} c\mathbf{R} & \mathbf{t} \\ \mathbf{0} & 1 \end{bmatrix}
|
||||
* \f}
|
||||
* minimizing the resudiual above. This transformation is always returned as an
|
||||
* Eigen::Matrix.
|
||||
*/
|
||||
template <typename Derived, typename OtherDerived>
|
||||
typename internal::umeyama_transform_matrix_type<Derived, OtherDerived>::type
|
||||
umeyama(const MatrixBase<Derived>& src, const MatrixBase<OtherDerived>& dst, bool with_scaling = true)
|
||||
{
|
||||
typedef typename internal::umeyama_transform_matrix_type<Derived, OtherDerived>::type TransformationMatrixType;
|
||||
typedef typename internal::traits<TransformationMatrixType>::Scalar Scalar;
|
||||
typedef typename NumTraits<Scalar>::Real RealScalar;
|
||||
typedef typename Derived::Index Index;
|
||||
|
||||
EIGEN_STATIC_ASSERT(!NumTraits<Scalar>::IsComplex, NUMERIC_TYPE_MUST_BE_REAL)
|
||||
EIGEN_STATIC_ASSERT((internal::is_same<Scalar, typename internal::traits<OtherDerived>::Scalar>::value),
|
||||
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
|
||||
|
||||
enum { Dimension = EIGEN_SIZE_MIN_PREFER_DYNAMIC(Derived::RowsAtCompileTime, OtherDerived::RowsAtCompileTime) };
|
||||
|
||||
typedef Matrix<Scalar, Dimension, 1> VectorType;
|
||||
typedef Matrix<Scalar, Dimension, Dimension> MatrixType;
|
||||
typedef typename internal::plain_matrix_type_row_major<Derived>::type RowMajorMatrixType;
|
||||
|
||||
const Index m = src.rows(); // dimension
|
||||
const Index n = src.cols(); // number of measurements
|
||||
|
||||
// required for demeaning ...
|
||||
const RealScalar one_over_n = RealScalar(1) / static_cast<RealScalar>(n);
|
||||
|
||||
// computation of mean
|
||||
const VectorType src_mean = src.rowwise().sum() * one_over_n;
|
||||
const VectorType dst_mean = dst.rowwise().sum() * one_over_n;
|
||||
|
||||
// demeaning of src and dst points
|
||||
const RowMajorMatrixType src_demean = src.colwise() - src_mean;
|
||||
const RowMajorMatrixType dst_demean = dst.colwise() - dst_mean;
|
||||
|
||||
// Eq. (36)-(37)
|
||||
const Scalar src_var = src_demean.rowwise().squaredNorm().sum() * one_over_n;
|
||||
|
||||
// Eq. (38)
|
||||
const MatrixType sigma = one_over_n * dst_demean * src_demean.transpose();
|
||||
|
||||
JacobiSVD<MatrixType> svd(sigma, ComputeFullU | ComputeFullV);
|
||||
|
||||
// Initialize the resulting transformation with an identity matrix...
|
||||
TransformationMatrixType Rt = TransformationMatrixType::Identity(m+1,m+1);
|
||||
|
||||
// Eq. (39)
|
||||
VectorType S = VectorType::Ones(m);
|
||||
if (sigma.determinant()<Scalar(0)) S(m-1) = Scalar(-1);
|
||||
|
||||
// Eq. (40) and (43)
|
||||
const VectorType& d = svd.singularValues();
|
||||
Index rank = 0; for (Index i=0; i<m; ++i) if (!internal::isMuchSmallerThan(d.coeff(i),d.coeff(0))) ++rank;
|
||||
if (rank == m-1) {
|
||||
if ( svd.matrixU().determinant() * svd.matrixV().determinant() > Scalar(0) ) {
|
||||
Rt.block(0,0,m,m).noalias() = svd.matrixU()*svd.matrixV().transpose();
|
||||
} else {
|
||||
const Scalar s = S(m-1); S(m-1) = Scalar(-1);
|
||||
Rt.block(0,0,m,m).noalias() = svd.matrixU() * S.asDiagonal() * svd.matrixV().transpose();
|
||||
S(m-1) = s;
|
||||
}
|
||||
} else {
|
||||
Rt.block(0,0,m,m).noalias() = svd.matrixU() * S.asDiagonal() * svd.matrixV().transpose();
|
||||
}
|
||||
|
||||
if (with_scaling)
|
||||
{
|
||||
// Eq. (42)
|
||||
const Scalar c = Scalar(1)/src_var * svd.singularValues().dot(S);
|
||||
|
||||
// Eq. (41)
|
||||
Rt.col(m).head(m) = dst_mean;
|
||||
Rt.col(m).head(m).noalias() -= c*Rt.topLeftCorner(m,m)*src_mean;
|
||||
Rt.block(0,0,m,m) *= c;
|
||||
}
|
||||
else
|
||||
{
|
||||
Rt.col(m).head(m) = dst_mean;
|
||||
Rt.col(m).head(m).noalias() -= Rt.topLeftCorner(m,m)*src_mean;
|
||||
}
|
||||
|
||||
return Rt;
|
||||
}
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_UMEYAMA_H
|
||||
115
3rdparty/eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h
vendored
Normal file
115
3rdparty/eigen3/Eigen/src/Geometry/arch/Geometry_SSE.h
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// This file is part of Eigen, a lightweight C++ template library
|
||||
// for linear algebra.
|
||||
//
|
||||
// Copyright (C) 2009 Rohit Garg <rpg.314@gmail.com>
|
||||
// Copyright (C) 2009-2010 Gael Guennebaud <gael.guennebaud@inria.fr>
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla
|
||||
// Public License v. 2.0. If a copy of the MPL was not distributed
|
||||
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef EIGEN_GEOMETRY_SSE_H
|
||||
#define EIGEN_GEOMETRY_SSE_H
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template<class Derived, class OtherDerived>
|
||||
struct quat_product<Architecture::SSE, Derived, OtherDerived, float, Aligned>
|
||||
{
|
||||
static inline Quaternion<float> run(const QuaternionBase<Derived>& _a, const QuaternionBase<OtherDerived>& _b)
|
||||
{
|
||||
const __m128 mask = _mm_castsi128_ps(_mm_setr_epi32(0,0,0,0x80000000));
|
||||
Quaternion<float> res;
|
||||
__m128 a = _a.coeffs().template packet<Aligned>(0);
|
||||
__m128 b = _b.coeffs().template packet<Aligned>(0);
|
||||
__m128 flip1 = _mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a,1,2,0,2),
|
||||
vec4f_swizzle1(b,2,0,1,2)),mask);
|
||||
__m128 flip2 = _mm_xor_ps(_mm_mul_ps(vec4f_swizzle1(a,3,3,3,1),
|
||||
vec4f_swizzle1(b,0,1,2,1)),mask);
|
||||
pstore(&res.x(),
|
||||
_mm_add_ps(_mm_sub_ps(_mm_mul_ps(a,vec4f_swizzle1(b,3,3,3,3)),
|
||||
_mm_mul_ps(vec4f_swizzle1(a,2,0,1,0),
|
||||
vec4f_swizzle1(b,1,2,0,0))),
|
||||
_mm_add_ps(flip1,flip2)));
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename VectorLhs,typename VectorRhs>
|
||||
struct cross3_impl<Architecture::SSE,VectorLhs,VectorRhs,float,true>
|
||||
{
|
||||
static inline typename plain_matrix_type<VectorLhs>::type
|
||||
run(const VectorLhs& lhs, const VectorRhs& rhs)
|
||||
{
|
||||
__m128 a = lhs.template packet<VectorLhs::Flags&AlignedBit ? Aligned : Unaligned>(0);
|
||||
__m128 b = rhs.template packet<VectorRhs::Flags&AlignedBit ? Aligned : Unaligned>(0);
|
||||
__m128 mul1=_mm_mul_ps(vec4f_swizzle1(a,1,2,0,3),vec4f_swizzle1(b,2,0,1,3));
|
||||
__m128 mul2=_mm_mul_ps(vec4f_swizzle1(a,2,0,1,3),vec4f_swizzle1(b,1,2,0,3));
|
||||
typename plain_matrix_type<VectorLhs>::type res;
|
||||
pstore(&res.x(),_mm_sub_ps(mul1,mul2));
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template<class Derived, class OtherDerived>
|
||||
struct quat_product<Architecture::SSE, Derived, OtherDerived, double, Aligned>
|
||||
{
|
||||
static inline Quaternion<double> run(const QuaternionBase<Derived>& _a, const QuaternionBase<OtherDerived>& _b)
|
||||
{
|
||||
const Packet2d mask = _mm_castsi128_pd(_mm_set_epi32(0x0,0x0,0x80000000,0x0));
|
||||
|
||||
Quaternion<double> res;
|
||||
|
||||
const double* a = _a.coeffs().data();
|
||||
Packet2d b_xy = _b.coeffs().template packet<Aligned>(0);
|
||||
Packet2d b_zw = _b.coeffs().template packet<Aligned>(2);
|
||||
Packet2d a_xx = pset1<Packet2d>(a[0]);
|
||||
Packet2d a_yy = pset1<Packet2d>(a[1]);
|
||||
Packet2d a_zz = pset1<Packet2d>(a[2]);
|
||||
Packet2d a_ww = pset1<Packet2d>(a[3]);
|
||||
|
||||
// two temporaries:
|
||||
Packet2d t1, t2;
|
||||
|
||||
/*
|
||||
* t1 = ww*xy + yy*zw
|
||||
* t2 = zz*xy - xx*zw
|
||||
* res.xy = t1 +/- swap(t2)
|
||||
*/
|
||||
t1 = padd(pmul(a_ww, b_xy), pmul(a_yy, b_zw));
|
||||
t2 = psub(pmul(a_zz, b_xy), pmul(a_xx, b_zw));
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
EIGEN_UNUSED_VARIABLE(mask)
|
||||
pstore(&res.x(), _mm_addsub_pd(t1, preverse(t2)));
|
||||
#else
|
||||
pstore(&res.x(), padd(t1, pxor(mask,preverse(t2))));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* t1 = ww*zw - yy*xy
|
||||
* t2 = zz*zw + xx*xy
|
||||
* res.zw = t1 -/+ swap(t2) = swap( swap(t1) +/- t2)
|
||||
*/
|
||||
t1 = psub(pmul(a_ww, b_zw), pmul(a_yy, b_xy));
|
||||
t2 = padd(pmul(a_zz, b_zw), pmul(a_xx, b_xy));
|
||||
#ifdef EIGEN_VECTORIZE_SSE3
|
||||
EIGEN_UNUSED_VARIABLE(mask)
|
||||
pstore(&res.z(), preverse(_mm_addsub_pd(preverse(t1), t2)));
|
||||
#else
|
||||
pstore(&res.z(), psub(t1, pxor(mask,preverse(t2))));
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace internal
|
||||
|
||||
} // end namespace Eigen
|
||||
|
||||
#endif // EIGEN_GEOMETRY_SSE_H
|
||||
Reference in New Issue
Block a user