From 8918d18e219c9a31219e2b90bbe522d344495881 Mon Sep 17 00:00:00 2001 From: Gael Guennebaud Date: Wed, 10 Feb 2010 11:40:55 +0100 Subject: [PATCH] Improved patch from Manuel Yguel: Enhance AlignedBox to accept integral types and add some usefull methods: diagonal, volume, sample. --- Eigen/src/Core/NumTraits.h | 4 +- Eigen/src/Geometry/AlignedBox.h | 218 ++++++++++++++++++++++++++------ 2 files changed, 181 insertions(+), 41 deletions(-) diff --git a/Eigen/src/Core/NumTraits.h b/Eigen/src/Core/NumTraits.h index f4036dc0c..1baf62496 100644 --- a/Eigen/src/Core/NumTraits.h +++ b/Eigen/src/Core/NumTraits.h @@ -54,8 +54,8 @@ template struct NumTraits; template struct ei_default_float_numtraits : std::numeric_limits { - inline static T higest() { return std::numeric_limits::max(); } - inline static T lowest() { return -std::numeric_limits::max(); } + inline static T highest() { return std::numeric_limits::max(); } + inline static T lowest() { return -std::numeric_limits::max(); } }; template struct ei_default_integral_numtraits diff --git a/Eigen/src/Geometry/AlignedBox.h b/Eigen/src/Geometry/AlignedBox.h index 5c1f992c6..c5510e5ad 100644 --- a/Eigen/src/Geometry/AlignedBox.h +++ b/Eigen/src/Geometry/AlignedBox.h @@ -43,37 +43,70 @@ class AlignedBox public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim) enum { AmbientDimAtCompileTime = _AmbientDim }; - typedef _Scalar Scalar; - typedef typename NumTraits::Real RealScalar; - typedef Matrix VectorType; + typedef _Scalar Scalar; + typedef NumTraits ScalarTraits; + typedef typename ScalarTraits::Real RealScalar; + typedef typename ScalarTraits::FloatingPoint FloatingPoint; + typedef Matrix 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, + + /** Added names for 2D */ + BottomLeft=0, BottomRight=1, + TopLeft=2, TopRight=3, + + /** Added names for 3D */ + BottomLeftFloor=0, BottomRightFloor=1, + TopLeftFloor=2, TopRightFloor=3, + BottomLeftCeil=4, BottomRightCeil=5, + TopLeftCeil=6, TopRightCeil=7 + }; + /** Default constructor initializing a null box. */ inline explicit AlignedBox() - { if (AmbientDimAtCompileTime!=Dynamic) setNull(); } + { if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); } /** Constructs a null box with \a _dim the dimension of the ambient space. */ inline explicit AlignedBox(int _dim) : m_min(_dim), m_max(_dim) - { setNull(); } + { setEmpty(); } /** Constructs a box with extremities \a _min and \a _max. */ - inline AlignedBox(const VectorType& _min, const VectorType& _max) : m_min(_min), m_max(_max) {} + template + inline AlignedBox(const OtherVectorType1& _min, const OtherVectorType2& _max) : m_min(_min), m_max(_max) {} /** Constructs a box containing a single point \a p. */ - inline explicit AlignedBox(const VectorType& p) : m_min(p), m_max(p) {} + template + inline explicit AlignedBox(const MatrixBase& a_p) + { + const typename ei_nested::type p(a_p.derived()); + m_min = p; + m_max = p; + } ~AlignedBox() {} /** \returns the dimension in which the box holds */ inline int dim() const { return AmbientDimAtCompileTime==Dynamic ? m_min.size()-1 : AmbientDimAtCompileTime; } - /** \returns true if the box is null, i.e, empty. */ - inline bool isNull() const { return (m_min.array() > m_max.array()).any(); } + /** \deprecated use isEmpty */ + inline bool isNull() const { return isEmpty(); } - /** Makes \c *this a null/empty box. */ - inline void setNull() + /** \deprecated use setEmpty */ + inline void setNull() { setEmpty(); } + + /** \returns true if the box is empty. */ + inline bool isEmpty() const { return (m_min.cwise() > m_max).any(); } + + /** Makes \c *this an empty box. */ + inline void setEmpty() { - m_min.setConstant( std::numeric_limits::max()); - m_max.setConstant(-std::numeric_limits::max()); + m_min.setConstant( ScalarTraits::highest() ); + m_max.setConstant( ScalarTraits::lowest() ); } /** \returns the minimal corner */ @@ -86,45 +119,135 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim) inline VectorType& max() { return m_max; } /** \returns the center of the box */ - inline VectorType center() const { return (m_min + m_max) / 2; } + inline const CwiseUnaryOp, + CwiseBinaryOp, VectorType, 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< ei_scalar_difference_op, VectorType, 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< ei_scalar_difference_op, VectorType, 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; + + int mult = 1; + for(int d=0; d() + ei_random_amplitude()) + / (Scalar(2)*ei_random_amplitude() ); + } + else + r[d] = ei_random(m_min[d], m_max[d]); + } + return r; + } /** \returns true if the point \a p is inside the box \c *this. */ - inline bool contains(const VectorType& p) const - { return (m_min.array()<=p.array()).all() && (p.array()<=m_max.array()).all(); } + template + inline bool contains(const MatrixBase& a_p) const + { + const typename ei_nested::type p(a_p.derived()); + return (m_min.array()<=p.array()).all() && (p.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(); } /** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */ - inline AlignedBox& extend(const VectorType& p) - { m_min = m_min.cwiseMin(p); m_max = m_max.cwiseMax(p); return *this; } + template + inline AlignedBox& extend(const MatrixBase& a_p) + { + const typename ei_nested::type p(a_p.derived()); + m_min = m_min.cwiseMin(p); + m_max = m_max.cwiseMax(p); + return *this; + } /** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */ inline AlignedBox& extend(const AlignedBox& b) - { m_min = m_min.cwiseMin(b.m_min); m_max = m_max.cwiseMax(b.m_max); return *this; } + { + 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. */ inline AlignedBox& clamp(const AlignedBox& b) - { m_min = m_min.cwiseMax(b.m_min); m_max = m_max.cwiseMin(b.m_max); return *this; } + { + 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 */ - inline AlignedBox intersection(const AlignedBox &b) const - { return AlignedBox(m_min.cwiseMax(b.m_min), m_max.cwiseMin(b.m_max)); } + 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 */ - inline AlignedBox merged(const AlignedBox &b) const + 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. */ - inline AlignedBox& translate(const VectorType& t) - { m_min += t; m_max += t; return *this; } + template + inline AlignedBox& translate(const MatrixBase& a_t) + { + const typename ei_nested::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() */ - inline Scalar squaredExteriorDistance(const VectorType& p) const; + template + inline Scalar squaredExteriorDistance(const MatrixBase& a_p) const; /** \returns the squared distance between the boxes \a b and \c *this, * and zero if the boxes intersect. @@ -136,15 +259,16 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim) * and zero if \a p is inside the box. * \sa squaredExteriorDistance() */ - inline Scalar exteriorDistance(const VectorType& p) const - { return ei_sqrt(squaredExteriorDistance(p)); } + template + inline FloatingPoint exteriorDistance(const MatrixBase& p) const + { return ei_sqrt(FloatingPoint(squaredExteriorDistance(p))); } /** \returns the distance between the boxes \a b and \c *this, * and zero if the boxes intersect. * \sa squaredExteriorDistance() */ - inline Scalar exteriorDistance(const AlignedBox& b) const - { return ei_sqrt(squaredExteriorDistance(b)); } + inline FloatingPoint exteriorDistance(const AlignedBox& b) const + { return ei_sqrt(FloatingPoint(squaredExteriorDistance(b))); } /** \returns \c *this with scalar type casted to \a NewScalarType * @@ -171,7 +295,7 @@ EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim) * determined by \a prec. * * \sa MatrixBase::isApprox() */ - bool isApprox(const AlignedBox& other, typename NumTraits::Real prec = NumTraits::dummy_precision()) const + bool isApprox(const AlignedBox& other, RealScalar prec = ScalarTraits::dummy_precision()) const { return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); } protected: @@ -179,32 +303,48 @@ protected: VectorType m_min, m_max; }; -template -inline Scalar AlignedBox::squaredExteriorDistance(const VectorType& p) const + + +template +template +inline Scalar AlignedBox::squaredExteriorDistance(const MatrixBase& a_p) const { + const typename ei_nested::type p(a_p.derived()); Scalar dist2 = 0.; Scalar aux; for (int k=0; k p[k] ) + { + aux = m_min[k] - p[k]; dist2 += aux*aux; - else if ( (aux = (m_max[k]-p[k])) m_max[k] ) + { + aux = p[k] - m_max[k]; dist2 += aux*aux; + } } return dist2; } -template -inline Scalar AlignedBox::squaredExteriorDistance(const AlignedBox& b) const +template +inline Scalar AlignedBox::squaredExteriorDistance(const AlignedBox& b) const { Scalar dist2 = 0.; Scalar aux; for (int k=0; k0.) + if( m_min[k] > b.m_max[k] ) + { + aux = m_min[k] - b.m_max[k]; dist2 += aux*aux; - else if ( (aux = (m_min[k]-b.m_max[k]))>0. ) + } + else if( b.m_min[k] > m_max[k] ) + { + aux = b.m_min[k] - m_max[k]; dist2 += aux*aux; + } } return dist2; }