Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
AlignedBox.h
00001 // This file is part of Eigen, a lightweight C++ template library 00002 // for linear algebra. 00003 // 00004 // Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr> 00005 // 00006 // This Source Code Form is subject to the terms of the Mozilla 00007 // Public License v. 2.0. If a copy of the MPL was not distributed 00008 // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 00009 00010 #ifndef EIGEN_ALIGNEDBOX_H 00011 #define EIGEN_ALIGNEDBOX_H 00012 00013 namespace Eigen { 00014 00015 /** \geometry_module \ingroup Geometry_Module 00016 * 00017 * 00018 * \class AlignedBox 00019 * 00020 * \brief An axis aligned box 00021 * 00022 * \tparam _Scalar the type of the scalar coefficients 00023 * \tparam _AmbientDim the dimension of the ambient space, can be a compile time value or Dynamic. 00024 * 00025 * This class represents an axis aligned box as a pair of the minimal and maximal corners. 00026 * \warning The result of most methods is undefined when applied to an empty box. You can check for empty boxes using isEmpty(). 00027 * \sa alignedboxtypedefs 00028 */ 00029 template <typename _Scalar, int _AmbientDim> 00030 class AlignedBox 00031 { 00032 public: 00033 EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF_VECTORIZABLE_FIXED_SIZE(_Scalar,_AmbientDim) 00034 enum { AmbientDimAtCompileTime = _AmbientDim }; 00035 typedef _Scalar Scalar; 00036 typedef NumTraits<Scalar> ScalarTraits; 00037 typedef DenseIndex Index; 00038 typedef typename ScalarTraits::Real RealScalar; 00039 typedef typename ScalarTraits::NonInteger NonInteger; 00040 typedef Matrix<Scalar,AmbientDimAtCompileTime,1> VectorType ; 00041 00042 /** Define constants to name the corners of a 1D, 2D or 3D axis aligned bounding box */ 00043 enum CornerType 00044 { 00045 /** 1D names @{ */ 00046 Min=0, Max=1, 00047 /** @} */ 00048 00049 /** Identifier for 2D corner @{ */ 00050 BottomLeft=0, BottomRight=1, 00051 TopLeft=2, TopRight=3, 00052 /** @} */ 00053 00054 /** Identifier for 3D corner @{ */ 00055 BottomLeftFloor=0, BottomRightFloor=1, 00056 TopLeftFloor=2, TopRightFloor=3, 00057 BottomLeftCeil=4, BottomRightCeil=5, 00058 TopLeftCeil=6, TopRightCeil=7 00059 /** @} */ 00060 }; 00061 00062 00063 /** Default constructor initializing a null box. */ 00064 inline AlignedBox() 00065 { if (AmbientDimAtCompileTime!=Dynamic) setEmpty(); } 00066 00067 /** Constructs a null box with \a _dim the dimension of the ambient space. */ 00068 inline explicit AlignedBox(Index _dim) : m_min(_dim), m_max(_dim) 00069 { setEmpty(); } 00070 00071 /** Constructs a box with extremities \a _min and \a _max. 00072 * \warning If either component of \a _min is larger than the same component of \a _max, the constructed box is empty. */ 00073 template<typename OtherVectorType1, typename OtherVectorType2> 00074 inline AlignedBox(const OtherVectorType1& _min, const OtherVectorType2& _max) : m_min(_min), m_max(_max) {} 00075 00076 /** Constructs a box containing a single point \a p. */ 00077 template<typename Derived> 00078 inline explicit AlignedBox(const MatrixBase<Derived>& p) : m_min(p), m_max(m_min) 00079 { } 00080 00081 ~AlignedBox () {} 00082 00083 /** \returns the dimension in which the box holds */ 00084 inline Index dim () const { return AmbientDimAtCompileTime==Dynamic ? m_min.size() : Index(AmbientDimAtCompileTime); } 00085 00086 /** \deprecated use isEmpty() */ 00087 inline bool isNull () const { return isEmpty (); } 00088 00089 /** \deprecated use setEmpty() */ 00090 inline void setNull () { setEmpty(); } 00091 00092 /** \returns true if the box is empty. 00093 * \sa setEmpty */ 00094 inline bool isEmpty () const { return (m_min.array() > m_max.array()).any(); } 00095 00096 /** Makes \c *this an empty box. 00097 * \sa isEmpty */ 00098 inline void setEmpty() 00099 { 00100 m_min.setConstant( ScalarTraits::highest() ); 00101 m_max.setConstant( ScalarTraits::lowest() ); 00102 } 00103 00104 /** \returns the minimal corner */ 00105 inline const VectorType & (min )() const { return m_min; } 00106 /** \returns a non const reference to the minimal corner */ 00107 inline VectorType & (min )() { return m_min; } 00108 /** \returns the maximal corner */ 00109 inline const VectorType & (max )() const { return m_max; } 00110 /** \returns a non const reference to the maximal corner */ 00111 inline VectorType & (max )() { return m_max; } 00112 00113 /** \returns the center of the box */ 00114 inline const CwiseUnaryOp<internal::scalar_quotient1_op<Scalar>, 00115 const CwiseBinaryOp<internal::scalar_sum_op<Scalar>, const VectorType, const VectorType> > 00116 center () const 00117 { return (m_min+m_max)/2; } 00118 00119 /** \returns the lengths of the sides of the bounding box. 00120 * Note that this function does not get the same 00121 * result for integral or floating scalar types: see 00122 */ 00123 inline const CwiseBinaryOp< internal::scalar_difference_op<Scalar>, const VectorType , const VectorType > sizes () const 00124 { return m_max - m_min; } 00125 00126 /** \returns the volume of the bounding box */ 00127 inline Scalar volume () const 00128 { return sizes ().prod(); } 00129 00130 /** \returns an expression for the bounding box diagonal vector 00131 * if the length of the diagonal is needed: diagonal().norm() 00132 * will provide it. 00133 */ 00134 inline CwiseBinaryOp< internal::scalar_difference_op<Scalar>, const VectorType , const VectorType > diagonal () const 00135 { return sizes (); } 00136 00137 /** \returns the vertex of the bounding box at the corner defined by 00138 * the corner-id corner. It works only for a 1D, 2D or 3D bounding box. 00139 * For 1D bounding boxes corners are named by 2 enum constants: 00140 * BottomLeft and BottomRight. 00141 * For 2D bounding boxes, corners are named by 4 enum constants: 00142 * BottomLeft, BottomRight, TopLeft, TopRight. 00143 * For 3D bounding boxes, the following names are added: 00144 * BottomLeftCeil, BottomRightCeil, TopLeftCeil, TopRightCeil. 00145 */ 00146 inline VectorType corner (CornerType corner ) const 00147 { 00148 EIGEN_STATIC_ASSERT(_AmbientDim <= 3, THIS_METHOD_IS_ONLY_FOR_VECTORS_OF_A_SPECIFIC_SIZE); 00149 00150 VectorType res; 00151 00152 Index mult = 1; 00153 for(Index d=0; d<dim (); ++d) 00154 { 00155 if( mult & corner ) res[d] = m_max[d]; 00156 else res[d] = m_min[d]; 00157 mult *= 2; 00158 } 00159 return res; 00160 } 00161 00162 /** \returns a random point inside the bounding box sampled with 00163 * a uniform distribution */ 00164 inline VectorType sample () const 00165 { 00166 VectorType r(dim ()); 00167 for(Index d=0; d<dim (); ++d) 00168 { 00169 if(!ScalarTraits::IsInteger) 00170 { 00171 r[d] = m_min[d] + (m_max[d]-m_min[d]) 00172 * internal::random<Scalar>(Scalar(0), Scalar(1)); 00173 } 00174 else 00175 r[d] = internal::random(m_min[d], m_max[d]); 00176 } 00177 return r; 00178 } 00179 00180 /** \returns true if the point \a p is inside the box \c *this. */ 00181 template<typename Derived> 00182 inline bool contains (const MatrixBase<Derived>& p) const 00183 { 00184 typename internal::nested<Derived,2>::type p_n(p.derived()); 00185 return (m_min.array()<=p_n.array()).all() && (p_n.array()<=m_max.array()).all(); 00186 } 00187 00188 /** \returns true if the box \a b is entirely inside the box \c *this. */ 00189 inline bool contains (const AlignedBox & b) const 00190 { return (m_min.array()<=(b.min )().array()).all() && ((b.max )().array()<=m_max.array()).all(); } 00191 00192 /** \returns true if the box \a b is intersecting the box \c *this. 00193 * \sa intersection, clamp */ 00194 inline bool intersects (const AlignedBox & b) const 00195 { return (m_min.array()<=(b.max )().array()).all() && ((b.min )().array()<=m_max.array()).all(); } 00196 00197 /** Extends \c *this such that it contains the point \a p and returns a reference to \c *this. 00198 * \sa extend(const AlignedBox&) */ 00199 template<typename Derived> 00200 inline AlignedBox & extend(const MatrixBase<Derived>& p) 00201 { 00202 typename internal::nested<Derived,2>::type p_n(p.derived()); 00203 m_min = m_min.cwiseMin(p_n); 00204 m_max = m_max.cwiseMax(p_n); 00205 return *this; 00206 } 00207 00208 /** Extends \c *this such that it contains the box \a b and returns a reference to \c *this. 00209 * \sa merged, extend(const MatrixBase&) */ 00210 inline AlignedBox & extend(const AlignedBox & b) 00211 { 00212 m_min = m_min.cwiseMin(b.m_min); 00213 m_max = m_max.cwiseMax(b.m_max); 00214 return *this; 00215 } 00216 00217 /** Clamps \c *this by the box \a b and returns a reference to \c *this. 00218 * \note If the boxes don't intersect, the resulting box is empty. 00219 * \sa intersection(), intersects() */ 00220 inline AlignedBox & clamp(const AlignedBox & b) 00221 { 00222 m_min = m_min.cwiseMax(b.m_min); 00223 m_max = m_max.cwiseMin(b.m_max); 00224 return *this; 00225 } 00226 00227 /** Returns an AlignedBox that is the intersection of \a b and \c *this 00228 * \note If the boxes don't intersect, the resulting box is empty. 00229 * \sa intersects(), clamp, contains() */ 00230 inline AlignedBox intersection(const AlignedBox & b) const 00231 {return AlignedBox(m_min.cwiseMax(b.m_min), m_max.cwiseMin(b.m_max)); } 00232 00233 /** Returns an AlignedBox that is the union of \a b and \c *this. 00234 * \note Merging with an empty box may result in a box bigger than \c *this. 00235 * \sa extend(const AlignedBox&) */ 00236 inline AlignedBox merged(const AlignedBox & b) const 00237 { return AlignedBox(m_min.cwiseMin(b.m_min), m_max.cwiseMax(b.m_max)); } 00238 00239 /** Translate \c *this by the vector \a t and returns a reference to \c *this. */ 00240 template<typename Derived> 00241 inline AlignedBox & translate(const MatrixBase<Derived>& a_t) 00242 { 00243 const typename internal::nested<Derived,2>::type t(a_t.derived()); 00244 m_min += t; 00245 m_max += t; 00246 return *this; 00247 } 00248 00249 /** \returns the squared distance between the point \a p and the box \c *this, 00250 * and zero if \a p is inside the box. 00251 * \sa exteriorDistance(const MatrixBase&), squaredExteriorDistance(const AlignedBox&) 00252 */ 00253 template<typename Derived> 00254 inline Scalar squaredExteriorDistance (const MatrixBase<Derived>& p) const; 00255 00256 /** \returns the squared distance between the boxes \a b and \c *this, 00257 * and zero if the boxes intersect. 00258 * \sa exteriorDistance(const AlignedBox&), squaredExteriorDistance(const MatrixBase&) 00259 */ 00260 inline Scalar squaredExteriorDistance (const AlignedBox & b) const; 00261 00262 /** \returns the distance between the point \a p and the box \c *this, 00263 * and zero if \a p is inside the box. 00264 * \sa squaredExteriorDistance(const MatrixBase&), exteriorDistance(const AlignedBox&) 00265 */ 00266 template<typename Derived> 00267 inline NonInteger exteriorDistance (const MatrixBase<Derived>& p) const 00268 { using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance (p))); } 00269 00270 /** \returns the distance between the boxes \a b and \c *this, 00271 * and zero if the boxes intersect. 00272 * \sa squaredExteriorDistance(const AlignedBox&), exteriorDistance(const MatrixBase&) 00273 */ 00274 inline NonInteger exteriorDistance (const AlignedBox & b) const 00275 { using std::sqrt; return sqrt(NonInteger(squaredExteriorDistance (b))); } 00276 00277 /** \returns \c *this with scalar type casted to \a NewScalarType 00278 * 00279 * Note that if \a NewScalarType is equal to the current scalar type of \c *this 00280 * then this function smartly returns a const reference to \c *this. 00281 */ 00282 template<typename NewScalarType> 00283 inline typename internal::cast_return_type<AlignedBox, 00284 AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type cast () const 00285 { 00286 return typename internal::cast_return_type<AlignedBox, 00287 AlignedBox<NewScalarType,AmbientDimAtCompileTime> >::type(*this); 00288 } 00289 00290 /** Copy constructor with scalar type conversion */ 00291 template<typename OtherScalarType> 00292 inline explicit AlignedBox(const AlignedBox<OtherScalarType,AmbientDimAtCompileTime> & other) 00293 { 00294 m_min = (other.min )().template cast<Scalar>(); 00295 m_max = (other.max )().template cast<Scalar>(); 00296 } 00297 00298 /** \returns \c true if \c *this is approximately equal to \a other, within the precision 00299 * determined by \a prec. 00300 * 00301 * \sa MatrixBase::isApprox() */ 00302 bool isApprox (const AlignedBox & other, const RealScalar& prec = ScalarTraits::dummy_precision()) const 00303 { return m_min.isApprox(other.m_min, prec) && m_max.isApprox(other.m_max, prec); } 00304 00305 protected: 00306 00307 VectorType m_min, m_max; 00308 }; 00309 00310 00311 00312 template<typename Scalar,int AmbientDim> 00313 template<typename Derived> 00314 inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance (const MatrixBase<Derived>& a_p) const 00315 { 00316 typename internal::nested<Derived,2*AmbientDim>::type p(a_p.derived()); 00317 Scalar dist2(0); 00318 Scalar aux; 00319 for (Index k=0; k<dim(); ++k) 00320 { 00321 if( m_min[k] > p[k] ) 00322 { 00323 aux = m_min[k] - p[k]; 00324 dist2 += aux*aux; 00325 } 00326 else if( p[k] > m_max[k] ) 00327 { 00328 aux = p[k] - m_max[k]; 00329 dist2 += aux*aux; 00330 } 00331 } 00332 return dist2; 00333 } 00334 00335 template<typename Scalar,int AmbientDim> 00336 inline Scalar AlignedBox<Scalar,AmbientDim>::squaredExteriorDistance (const AlignedBox & b) const 00337 { 00338 Scalar dist2(0); 00339 Scalar aux; 00340 for (Index k=0; k<dim(); ++k) 00341 { 00342 if( m_min[k] > b.m_max[k] ) 00343 { 00344 aux = m_min[k] - b.m_max[k]; 00345 dist2 += aux*aux; 00346 } 00347 else if( b.m_min[k] > m_max[k] ) 00348 { 00349 aux = b.m_min[k] - m_max[k]; 00350 dist2 += aux*aux; 00351 } 00352 } 00353 return dist2; 00354 } 00355 00356 /** \defgroup alignedboxtypedefs Global aligned box typedefs 00357 * 00358 * \ingroup Geometry_Module 00359 * 00360 * Eigen defines several typedef shortcuts for most common aligned box types. 00361 * 00362 * The general patterns are the following: 00363 * 00364 * \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, 00365 * and where \c Type can be \c i for integer, \c f for float, \c d for double. 00366 * 00367 * 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. 00368 * 00369 * \sa class AlignedBox 00370 */ 00371 00372 #define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \ 00373 /** \ingroup alignedboxtypedefs */ \ 00374 typedef AlignedBox<Type, Size> AlignedBox##SizeSuffix##TypeSuffix; 00375 00376 #define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \ 00377 EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 1, 1) \ 00378 EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \ 00379 EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \ 00380 EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \ 00381 EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Dynamic, X) 00382 00383 EIGEN_MAKE_TYPEDEFS_ALL_SIZES(int, i) 00384 EIGEN_MAKE_TYPEDEFS_ALL_SIZES(float, f) 00385 EIGEN_MAKE_TYPEDEFS_ALL_SIZES(double, d) 00386 00387 #undef EIGEN_MAKE_TYPEDEFS_ALL_SIZES 00388 #undef EIGEN_MAKE_TYPEDEFS 00389 00390 } // end namespace Eigen 00391 00392 #endif // EIGEN_ALIGNEDBOX_H
Generated on Thu Nov 17 2022 22:01:27 by
1.7.2