IMP  2.0.0
The Integrative Modeling Platform
BoundingBoxD.h
Go to the documentation of this file.
1 /**
2  * \file IMP/algebra/BoundingBoxD.h \brief A bounding box in D dimensions.
3  *
4  * Copyright 2007-2013 IMP Inventors. All rights reserved.
5  *
6  */
7 
8 #ifndef IMPALGEBRA_BOUNDING_BOX_D_H
9 #define IMPALGEBRA_BOUNDING_BOX_D_H
10 
11 #include <IMP/algebra/algebra_config.h>
12 #include "VectorD.h"
13 #include "algebra_macros.h"
14 #include <IMP/base/exception.h>
15 
16 IMPALGEBRA_BEGIN_NAMESPACE
17 
18 
19 //! An axis-aligned bounding box.
20 /** The BoundingBoxD class provides a unified representation for bounding
21  boxes in \imp. Geometric objects should have an associated namespace
22  method like get_bounding_box() which returns the bounding boxes of objects.
23 
24  \note This class is a \ref geometricprimitives "geometric primitive".
25 */
26 template <int D>
28 {
29  void make_empty() {
30  for (int i=0; i< D; ++i) {
31  b_[0][i]= std::numeric_limits<double>::max();
32  b_[1][i]=-std::numeric_limits<double>::max();
33  }
34  }
35 public:
36 
37  //! Create an empty bounding box
39  IMP_USAGE_CHECK(D>0, "The constructor can not be used "
40  << "with a variable dim bounding box.");
41 
42  make_empty();
43  }
44  //! Create an empty bounding box
45  explicit BoundingBoxD(unsigned int d) {
46  IMP_USAGE_CHECK(D==-1, "The constructor can only be used "
47  << "with a variable dim bounding box.");
48  Floats lb(d), ub(d);
49  for (unsigned int i=0; i< d; ++i) {
50  lb[i]= std::numeric_limits<double>::max();
51  ub[i]=-std::numeric_limits<double>::max();
52  }
53  b_[0]= VectorD<D>(lb.begin(), lb.end());
54  b_[1]= VectorD<D>(ub.begin(), ub.end());
55  }
56  //! Make from the lower and upper corners
58  const VectorInputD<D> &ub){
59  b_[0]=lb;
60  b_[1]=ub;
62  for (unsigned int i=0; i< lb.get_dimension(); ++i) {
63  IMP_USAGE_CHECK(lb[i] <= ub[i],
64  "Invalid bounding box");
65  }
66  }
67  }
68  //! Creating a bounding box containing one point
69  explicit BoundingBoxD(const VectorInputD<D> &v) {
70  b_[0]=v; b_[1]=v;
71  }
72 
73  //! Creating a bounding box from a set of points
75  make_empty();
76  for(unsigned int j=0;j<points.size();j++) {
77  operator+=(points[j]);
78  }
79  }
80 
81  unsigned int get_dimension() const {
82  return get_corner(0).get_dimension();
83  }
84 
85  //! extend the current bounding box to include the other
87  for (unsigned int i=0; i< get_dimension(); ++i) {
88  b_[0][i]= std::min(o.get_corner(0)[i], get_corner(0)[i]);
89  b_[1][i]= std::max(o.get_corner(1)[i], get_corner(1)[i]);
90  }
91  return *this;
92  }
93 
94  //! extend the current bounding box to include the point
96  for (unsigned int i=0; i< get_dimension(); ++i) {
97  b_[0][i]= std::min(o[i], b_[0][i]);
98  b_[1][i]= std::max(o[i], b_[1][i]);
99  }
100  return *this;
101  }
102 
103  /** Grow the bounding box by o on all sizes. */
104  const BoundingBoxD<D>& operator+=(double o) {
105  for (unsigned int i=0; i< get_dimension(); ++i) {
106  b_[0][i]= b_[0][i]-o;
107  b_[1][i]= b_[1][i]+o;
108  }
109  return *this;
110  }
111  //! Returning a bounding box containing both
112  template <class O>
113  const BoundingBoxD<D> operator+(const BoundingBoxD<D> &o) const {
114  BoundingBoxD<D> ret(*this);
115  ret+= o;
116  return ret;
117  }
118  //! Return a bounding box grown by o on all sides
119  template <class O>
120  const BoundingBoxD<D> operator+(const O &o) const {
121  BoundingBoxD<D> ret(*this);
122  ret+= o;
123  return ret;
124  }
125 
126  //! For 0 return lower corner and 1 upper corner
127  const VectorD<D>& get_corner(unsigned int i) const {
128  IMP_USAGE_CHECK(i < 2, "Can only use 0 or 1");
129  return b_[i];
130  }
131 
132  //! True if the point o is contained within this bounding box
133  bool get_contains(const VectorD<D> &o) const {
134  for (unsigned int i=0; i< get_dimension(); ++i) {
135  if (o[i] < get_corner(0)[i]
136  || o[i] > get_corner(1)[i]) return false;
137  }
138  return true;
139  }
140  //! True if the input bounding box is contained within this bounding box
141  bool get_contains(const BoundingBoxD &bb) const {
142  return get_contains(bb.get_corner(0)) && get_contains(bb.get_corner(1));
143  }
144 
145  IMP_SHOWABLE_INLINE(BoundingBoxD, out << b_[0] << ": " << b_[1]);
146 
147 private:
148  VectorD<D> b_[2];
149 };
150 /** \relates BoundingBoxD */
151 template <int D>
152 inline double get_volume(const BoundingBoxD<D> &bb) {
153  double v=1;
154  for (unsigned int i=0; i< bb.get_dimension(); ++i) {
155  v*= bb.get_corner(1)[i]-bb.get_corner(0)[i];
156  }
157  return v;
158 }
159 
160 IMP_VOLUME_GEOMETRY_METHODS_D(BoundingBox, bounding_box,
162  return (g.get_corner(1)[0]- g.get_corner(0)[0])
163  *(g.get_corner(1)[1]- g.get_corner(0)[1])
164  *(g.get_corner(1)[2]- g.get_corner(0)[2]),
165  return g);
166 
167 
168 //! Box with radius one
169 /** \relates BoundingBoxD */
170 template <unsigned int D>
172  return BoundingBoxD<D>(-get_ones_vector_d<D>(), get_ones_vector_d<D>());
173 }
174 
175 //! Box with radius one
176 /** \relates BoundingBoxD */
177 inline BoundingBoxD<-1> get_unit_bounding_box_kd(unsigned int d) {
179 }
180 
181 //! Cube with radius of length \c radius
182 /** \relates BoundingBoxD */
183 template <unsigned int D>
184 inline BoundingBoxD<D> get_cube_d(double radius) {
185  return BoundingBoxD<D>(-radius*get_ones_vector_d<D>(),
186  radius*get_ones_vector_d<D>());
187 }
188 
189 //! Cube with radius of length \c side
190 /** \relates BoundingBoxD */
191 inline BoundingBoxD<-1> get_cube_kd(unsigned int d, double radius) {
192  return BoundingBoxD<-1>(-radius*get_ones_vector_kd(d),
193  radius*get_ones_vector_kd(d));
194 }
195 
196 
197 //! Return true if they intersect
198 /** \relates BoundingBoxD */
199 template <int D>
201  const BoundingBoxD<D> &b) {
202  IMP_USAGE_CHECK(a.get_dimension() == b.get_dimension(),
203  "Dimensions of bounding boxes don't match.");
204  for (unsigned int i=0; i< a.get_dimension(); ++i) {
205  if (a.get_corner(0)[i] > b.get_corner(1)[i]) return false;
206  if (b.get_corner(0)[i] > a.get_corner(1)[i]) return false;
207  }
208  return true;
209 }
210 
211 //! Return the intersecting bounding box
212 /** \relates BoundingBoxD */
213 template <int D>
215  const BoundingBoxD<D> &b) {
216  VectorD<D> ic[2];
217  //set low
218  int j=0;
219  for (unsigned int i=0; i< a.get_dimension(); ++i) {
220  if (a.get_corner(j)[i] > b.get_corner(j)[i]) {ic[j][i]=a.get_corner(j)[i];}
221  else {ic[j][i]=b.get_corner(j)[i];}
222  }
223  //set top
224  j=1;
225  for (unsigned int i=0; i< a.get_dimension(); ++i) {
226  if (a.get_corner(j)[i] < b.get_corner(j)[i]) {ic[j][i]=a.get_corner(j)[i];}
227  else {ic[j][i]=b.get_corner(j)[i];}
228  }
229  return BoundingBoxD<D>(ic[0],ic[1]);
230 }
231 
232 
233 
234 //! Return the union bounding box
235 /** This is the same as doing a+b.
236  \relates BoundingBoxD
237 */
238 template <int D>
240  const BoundingBoxD<D> &b) {
241  a+=b;
242  return a;
243 }
244 
245 //! Return the maximum axis aligned extent
246 /** \relates BoundingBoxD */
247 template <int D>
248 inline double get_maximum_length(const BoundingBoxD<D> &a) {
249  double e= a.get_corner(1)[0]-a.get_corner(0)[0];
250  for (unsigned int i=1; i< a.get_dimension(); ++i) {
251  double ce= a.get_corner(1)[0]-a.get_corner(0)[0];
252  e= std::max(ce, e);
253  }
254  return e;
255 }
256 
257 
258 //! Return a list of the 8 bounding points for the bounding box
259 /** \relates BoundingBoxD */
261  Vector3Ds ret; ret.reserve(8);
262  for (unsigned int i=0; i< 2; ++i) {
263  for (unsigned int j=0; j< 2; ++j) {
264  for (unsigned int k=0; k< 2; ++k) {
265  ret.push_back(Vector3D(bb.get_corner(i)[0],
266  bb.get_corner(j)[1],
267  bb.get_corner(k)[2]));
268  }
269  }
270  }
271  return ret;
272 }
273 
274 //! Return the edges of the box as indices into the vertices list
275 /** \relates BoundingBoxD */
277  static const IntPair edges[12]={IntPair(0,1), IntPair(0,2), IntPair(0,4),
278  IntPair(1,3), IntPair(1,5),
279  IntPair(2,3), IntPair(2,6),
280  IntPair(3,7),
281  IntPair(4,5), IntPair(4,6),
282  IntPair(5,7),
283  IntPair(6,7)};
284  static IntPairs ret(edges, edges+12);
285  return ret;
286 }
287 
288 IMPALGEBRA_END_NAMESPACE
289 
290 #endif /* IMPALGEBRA_BOUNDING_BOX_D_H */