AlignedBox.h 6.05 KB
Newer Older
LM's avatar
LM committed
1
// This file is part of Eigen, a lightweight C++ template library
Don Gagne's avatar
Don Gagne committed
2
// for linear algebra.
LM's avatar
LM committed
3 4 5
//
// Copyright (C) 2008 Gael Guennebaud <g.gael@free.fr>
//
Don Gagne's avatar
Don Gagne committed
6 7 8
// 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/.
LM's avatar
LM committed
9 10 11

// no include guard, we'll include this twice from All.h from Eigen2Support, and it's internal anyway

Don Gagne's avatar
Don Gagne committed
12 13
namespace Eigen { 

LM's avatar
LM committed
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/** \geometry_module \ingroup Geometry_Module
  * \nonstableyet
  *
  * \class AlignedBox
  *
  * \brief An axis aligned box
  *
  * \param _Scalar the type of the scalar coefficients
  * \param _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.
  */
template <typename _Scalar, int _AmbientDim>
class AlignedBox
{
public:
EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim==Dynamic ? Dynamic : _AmbientDim+1)
  enum { AmbientDimAtCompileTime = _AmbientDim };
  typedef _Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType;

  /** Default constructor initializing a null box. */
Don Gagne's avatar
Don Gagne committed
37
  inline AlignedBox()
LM's avatar
LM committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
  { if (AmbientDimAtCompileTime!=Dynamic) setNull(); }

  /** 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(); }

  /** Constructs a box with extremities \a _min and \a _max. */
  inline AlignedBox(const VectorType& _min, const VectorType& _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) {}

  ~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.cwise() > m_max).any(); }

  /** Makes \c *this a null/empty box. */
  inline void setNull()
  {
Don Gagne's avatar
Don Gagne committed
61 62
    m_min.setConstant( (std::numeric_limits<Scalar>::max)());
    m_max.setConstant(-(std::numeric_limits<Scalar>::max)());
LM's avatar
LM committed
63 64 65
  }

  /** \returns the minimal corner */
Don Gagne's avatar
Don Gagne committed
66
  inline const VectorType& (min)() const { return m_min; }
LM's avatar
LM committed
67
  /** \returns a non const reference to the minimal corner */
Don Gagne's avatar
Don Gagne committed
68
  inline VectorType& (min)() { return m_min; }
LM's avatar
LM committed
69
  /** \returns the maximal corner */
Don Gagne's avatar
Don Gagne committed
70
  inline const VectorType& (max)() const { return m_max; }
LM's avatar
LM committed
71
  /** \returns a non const reference to the maximal corner */
Don Gagne's avatar
Don Gagne committed
72
  inline VectorType& (max)() { return m_max; }
LM's avatar
LM committed
73 74 75 76 77 78 79

  /** \returns true if the point \a p is inside the box \c *this. */
  inline bool contains(const VectorType& p) const
  { return (m_min.cwise()<=p).all() && (p.cwise()<=m_max).all(); }

  /** \returns true if the box \a b is entirely inside the box \c *this. */
  inline bool contains(const AlignedBox& b) const
Don Gagne's avatar
Don Gagne committed
80
  { return (m_min.cwise()<=(b.min)()).all() && ((b.max)().cwise()<=m_max).all(); }
LM's avatar
LM committed
81 82 83

  /** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. */
  inline AlignedBox& extend(const VectorType& p)
Don Gagne's avatar
Don Gagne committed
84
  { m_min = (m_min.cwise().min)(p); m_max = (m_max.cwise().max)(p); return *this; }
LM's avatar
LM committed
85 86 87

  /** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. */
  inline AlignedBox& extend(const AlignedBox& b)
Don Gagne's avatar
Don Gagne committed
88
  { m_min = (m_min.cwise().min)(b.m_min); m_max = (m_max.cwise().max)(b.m_max); return *this; }
LM's avatar
LM committed
89 90 91

  /** Clamps \c *this by the box \a b and returns a reference to \c *this. */
  inline AlignedBox& clamp(const AlignedBox& b)
Don Gagne's avatar
Don Gagne committed
92
  { m_min = (m_min.cwise().max)(b.m_min); m_max = (m_max.cwise().min)(b.m_max); return *this; }
LM's avatar
LM committed
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

  /** 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; }

  /** \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;

  /** \returns the distance between the point \a p and the box \c *this,
    * and zero if \a p is inside the box.
    * \sa squaredExteriorDistance()
    */
  inline Scalar exteriorDistance(const VectorType& p) const
  { return ei_sqrt(squaredExteriorDistance(p)); }

  /** \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)
  {
Don Gagne's avatar
Don Gagne committed
128 129
    m_min = (other.min)().template cast<Scalar>();
    m_max = (other.max)().template cast<Scalar>();
LM's avatar
LM committed
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
  }

  /** \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, typename NumTraits<Scalar>::Real prec = precision<Scalar>()) 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 AmbiantDim>
inline Scalar AlignedBox<Scalar,AmbiantDim>::squaredExteriorDistance(const VectorType& p) const
{
Don Gagne's avatar
Don Gagne committed
147
  Scalar dist2(0);
LM's avatar
LM committed
148 149 150
  Scalar aux;
  for (int k=0; k<dim(); ++k)
  {
Don Gagne's avatar
Don Gagne committed
151
    if ((aux = (p[k]-m_min[k]))<Scalar(0))
LM's avatar
LM committed
152
      dist2 += aux*aux;
Don Gagne's avatar
Don Gagne committed
153
    else if ( (aux = (m_max[k]-p[k]))<Scalar(0))
LM's avatar
LM committed
154 155 156 157
      dist2 += aux*aux;
  }
  return dist2;
}
Don Gagne's avatar
Don Gagne committed
158 159

} // end namespace Eigen