vbl_bounding_box.h
Go to the documentation of this file.
1 // This is core/vbl/vbl_bounding_box.h
2 #ifndef vbl_bounding_box_h_
3 #define vbl_bounding_box_h_
4 //:
5 // \file
6 // \brief Contains a bounding box class
7 // \author awf@robots.ox.ac.uk
8 // \date 17 Mar 00
9 //
10 // \verbatim
11 // Modifications
12 // 970807 AWF Initial version.
13 // 07 Mar 2001 stewart@cs.rpi.edu added "inside" functions
14 // 21 Mar 2001 PDA (Manchester) Tidied up the documentation
15 // 13 Jul 2001 Peter Vanroose bug fix in inside() when box is empty
16 // \endverbatim
17 
18 #include <iosfwd>
19 #ifdef _MSC_VER
20 # include <vcl_msvc_warnings.h>
21 #endif
22 #include <cassert>
23 #include <type_traits>
24 
25 #ifndef DOXYGEN_SHOULD_SKIP_THIS
26 // Helper class for vbl_bounding_box
27 template <int DIM>
28 struct vbl_bounding_box_DIM { enum { value = DIM }; };
29 #endif // DOXYGEN_SHOULD_SKIP_THIS
30 
31 template <class T, class DIM_>
33 {
34  public:
35  //: Construct an empty bounding box.
36  inline vbl_bounding_box_base() : initialized_(false) { }
37 
38  //: Incorporate 1d point x
39  inline void update(T const& x) {
40  assert(DIM_::value == 1);
41  update(&x);
42  }
43 
44  //: Incorporate 2d point x, y
45  inline void update(T const& x, T const& y) {
46  assert(DIM_::value == 2);
47  T tmp[2] = {x,y};
48  update(tmp);
49  }
50 
51  //: Incorporate 3d point x, y, z
52  inline void update(T const& x, T const& y, T const& z) {
53  assert(DIM_::value == 3);
54  T tmp[3] = {x,y,z};
55  update(tmp);
56  }
57 
58  //: return dimension.
59  inline int dimension() const { return DIM_::value; }
60 
61  //: Incorporate DIM-d point
62  inline void update(T const* point) {
63  if (!initialized_) {
64  initialized_ = true;
65  for (int i = 0; i < dimension(); ++i)
66  min_[i] = max_[i] = point[i];
67  } else {
68  for (int i = 0; i < dimension(); ++i) {
69  if (point[i] < min_[i]) min_[i] = point[i];
70  if (point[i] > max_[i]) max_[i] = point[i];
71  }
72  }
73  }
74 
75  //: Reset to empty
76  inline void reset() { initialized_ = false; }
77 
78  //: Return initialisation status
79  inline bool empty() const { return !initialized_; }
80 
81  //: is a 2D point inside the bounding box
82  inline bool inside( const T& x, const T& y) const {
83  assert (DIM_::value == 2); //NOTE: in case of DIM_ != 2 this never occurs.
84  constexpr unsigned int xdim = 0;
85  constexpr unsigned int ydim = (DIM_::value == 2) ? 1 : 0;
86  return
87  initialized_ &&
88  min_[xdim] <= x && x <= max_[xdim] &&
89  min_[ydim] <= y && y <= max_[ydim];
90  }
91 
92  //: is a 3D point inside the bounding box
93  inline bool inside( const T& x, const T& y, const T& z) const {
94  assert (DIM_::value == 3); //NOTE: in case of DIM_ != 3 this never occurs.
95  constexpr unsigned int xdim = 0;
96  constexpr unsigned int ydim = (DIM_::value == 3) ? 1 : 0;
97  constexpr unsigned int zdim = (DIM_::value == 3) ? 2 : 0;
98  return initialized_ &&
99  min_[xdim] <= x && x <= max_[xdim] &&
100  min_[ydim] <= y && y <= max_[ydim] &&
101  min_[zdim] <= z && z <= max_[zdim];
102  }
103 
104  //: inside test for arbitrary dimension
105  inline bool inside(T const* point) const {
106  if (!initialized_) return false;
107  for ( int i=0; i<dimension(); ++i )
108  if ( point[i] < min_[i] || max_[i] < point[i] )
109  return false;
110  return true;
111  }
112 
113  //: return "volume".
114  inline T volume() const {
115  if (!initialized_) return T(0);
116  T vol = 1;
117  for (int i=0; i<dimension(); ++i)
118  vol *= max_[i] - min_[i];
119  return vol;
120  }
121 
122  std::ostream& print(std::ostream& s) const;
123 
124  inline T const* min() const { return min_; }
125  inline T const* max() const { return max_; }
126 
127  inline T * min() { return min_; }
128  inline T * max() { return max_; }
129 
130  inline T const& xmin() const { return min_[0]; }
131  inline T const& xmax() const { return max_[0]; }
132  inline T const& ymin() const { assert(DIM_::value >= 2); return (DIM_::value >= 2) ? min_[1] : min_[0]; }
133  inline T const& ymax() const { assert(DIM_::value >= 2); return (DIM_::value >= 2) ? max_[1] : max_[0]; }
134  inline T const& zmin() const { assert(DIM_::value >= 3); return (DIM_::value >= 3) ? min_[2] : min_[0]; }
135  inline T const& zmax() const { assert(DIM_::value >= 3); return (DIM_::value >= 3) ? max_[2] : max_[0]; }
136 
137  //#pragma dogma
138  // There is no need for the data members to be private to
139  // this class. After all, the STL pair<> template has its
140  // two main members first, second public without causing
141  // any problems.
142  // BUT...
143  //#pragma practically
144  // The main difference here is that min_ and max_ have to satisfy certain
145  // constraints: e.g., min_[0] must be <= max_[0]. Hence we want write access
146  // to the data members to go through update() and empty() which can enforce
147  // this. Also, the use of initialized_ is a bit tricky: it indicates whether
148  // the bounding box is empty or not. This information could have been stored
149  // in the other data members instead (e.g. by setting min_[0] > max_[0])
150  // but that was not the design choice. Hence, leaving the really private
151  // (because subject to removal) data member initialized_ freely accessible
152  // is a very bad idea...
153  // HUH???
154  //#pragma reality_check
155  // But those members are still public; they are exposed by min() and max(),
156  // except the client must use the odd "bb.min()[i]" instead of "bb.min[i]".
157  // I predict the response to this observation will be the removal of the two
158  // non-const versions.
159 
160  private:
162  T min_[DIM_::value];
163  T max_[DIM_::value];
164 };
165 
166 //: A class to hold and update a bounding box.
167 // Save valuable time not writing
168 // \code
169 // if (x > xmax).....
170 // \endcode
171 
172 template <class T, int DIM>
173 class vbl_bounding_box : public vbl_bounding_box_base<T, vbl_bounding_box_DIM<DIM> >
174 {
175  public:
176 };
177 
178 //------------------------------------------------------------
179 
180 //: this is "operator \subseteq"
181 template <class T, class DIM_>
182 inline
184 {
185  for (int i=0; i<DIM_::value; ++i)
186  if (a.min()[i] < b.min()[i] || a.max()[i] > b.max()[i])
187  return false;
188  return true;
189 }
190 
191 //: is the intersection empty?
192 template <class T, class DIM_>
193 inline
196 {
197  for (int i=0; i<DIM_::value; ++i)
198  if (a.min()[i] > b.max()[i] || a.max()[i] < b.min()[i])
199  return true;
200  return false;
201 }
202 
203 //: is the intersection nonempty?
204 template <class T, class DIM_>
205 inline
208 { return ! disjoint(a, b); }
209 
210 template <class T, class DIM_>
211 std::ostream& operator << (std::ostream& s, const vbl_bounding_box_base<T,DIM_>& bbox);
212 
213 #endif // vbl_bounding_box_h_
T volume() const
return "volume".
T const * min() const
T const & ymax() const
void update(T const &x, T const &y)
Incorporate 2d point x, y.
void reset()
Reset to empty.
bool disjoint(vbl_bounding_box_base< T, DIM_ > const &a, vbl_bounding_box_base< T, DIM_ > const &b)
is the intersection empty?.
T const & xmin() const
void update(T const *point)
Incorporate DIM-d point.
bool inside(const T &x, const T &y) const
is a 2D point inside the bounding box.
vbl_bounding_box_base()
Construct an empty bounding box.
T const * max() const
std::ostream & print(std::ostream &s) const
T const & zmax() const
A class to hold and update a bounding box.
std::ostream & operator<<(std::ostream &s, const vbl_bounding_box_base< T, DIM_ > &bbox)
T const & zmin() const
int dimension() const
return dimension.
T const & ymin() const
void update(T const &x, T const &y, T const &z)
Incorporate 3d point x, y, z.
bool inside(T const *point) const
inside test for arbitrary dimension.
bool meet(vbl_bounding_box_base< T, DIM_ > const &a, vbl_bounding_box_base< T, DIM_ > const &b)
is the intersection nonempty?.
bool inside(const T &x, const T &y, const T &z) const
is a 3D point inside the bounding box.
bool empty() const
Return initialisation status.
bool nested(vbl_bounding_box_base< T, DIM_ > const &a, vbl_bounding_box_base< T, DIM_ > const &b)
this is "operator \subseteq".
T const & xmax() const
void update(T const &x)
Incorporate 1d point x.