IMP  2.1.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 //! An axis-aligned bounding box.
19 /** The BoundingBoxD class provides a unified representation for bounding
20  boxes in \imp. Geometric objects should have an associated namespace
21  method like get_bounding_box() which returns the bounding boxes of objects.
22 
23  \note This class is a \ref geometricprimitives "geometric primitive".
24 */
25 template <int D>
26 class BoundingBoxD {
27  void make_empty() {
28  for (int i = 0; i < D; ++i) {
29  b_[0][i] = std::numeric_limits<double>::max();
30  b_[1][i] = -std::numeric_limits<double>::max();
31  }
32  }
33 
34  public:
35 
36  //! Create an empty bounding box
38  IMP_USAGE_CHECK(D > 0, "The constructor can not be used "
39  << "with a variable dim bounding box.");
40 
41  make_empty();
42  }
43  //! Create an empty bounding box
44  explicit BoundingBoxD(unsigned int d) {
45  IMP_USAGE_CHECK(D == -1, "The constructor can only be used "
46  << "with a variable dim bounding box.");
47  Floats lb(d), ub(d);
48  for (unsigned int i = 0; i < d; ++i) {
49  lb[i] = std::numeric_limits<double>::max();
50  ub[i] = -std::numeric_limits<double>::max();
51  }
52  b_[0] = VectorD<D>(lb.begin(), lb.end());
53  b_[1] = VectorD<D>(ub.begin(), ub.end());
54  }
55  //! Make from the lower and upper corners
57  b_[0] = lb;
58  b_[1] = ub;
60  for (unsigned int i = 0; i < lb.get_dimension(); ++i) {
61  IMP_USAGE_CHECK(lb[i] <= ub[i], "Invalid bounding box");
62  }
63  }
64  }
65  //! Creating a bounding box containing one point
66  explicit BoundingBoxD(const VectorInputD<D> &v) {
67  b_[0] = v;
68  b_[1] = v;
69  }
70 
71  //! Creating a bounding box from a set of points
73  make_empty();
74  for (unsigned int j = 0; j < points.size(); j++) {
75  operator+=(points[j]);
76  }
77  }
78 
79  unsigned int get_dimension() const { return get_corner(0).get_dimension(); }
80 
81  //! extend the current bounding box to include the other
83  for (unsigned int i = 0; i < get_dimension(); ++i) {
84  b_[0][i] = std::min(o.get_corner(0)[i], get_corner(0)[i]);
85  b_[1][i] = std::max(o.get_corner(1)[i], get_corner(1)[i]);
86  }
87  return *this;
88  }
89 
90  //! extend the current bounding box to include the point
92  for (unsigned int i = 0; i < get_dimension(); ++i) {
93  b_[0][i] = std::min(o[i], b_[0][i]);
94  b_[1][i] = std::max(o[i], b_[1][i]);
95  }
96  return *this;
97  }
98 
99  /** Grow the bounding box by o on all sizes. */
100  const BoundingBoxD<D> &operator+=(double o) {
101  for (unsigned int i = 0; i < get_dimension(); ++i) {
102  b_[0][i] = b_[0][i] - o;
103  b_[1][i] = b_[1][i] + o;
104  }
105  return *this;
106  }
107  //! Returning a bounding box containing both
108  template <class O>
109  const BoundingBoxD<D> operator+(const BoundingBoxD<D> &o) const {
110  BoundingBoxD<D> ret(*this);
111  ret += o;
112  return ret;
113  }
114  //! Return a bounding box grown by o on all sides
115  template <class O>
116  const BoundingBoxD<D> operator+(const O &o) const {
117  BoundingBoxD<D> ret(*this);
118  ret += o;
119  return ret;
120  }
121 
122  //! For 0 return lower corner and 1 upper corner
123  const VectorD<D> &get_corner(unsigned int i) const {
124  IMP_USAGE_CHECK(i < 2, "Can only use 0 or 1");
125  return b_[i];
126  }
127 
128  //! True if the point o is contained within this bounding box
129  bool get_contains(const VectorD<D> &o) const {
130  for (unsigned int i = 0; i < get_dimension(); ++i) {
131  if (o[i] < get_corner(0)[i] || o[i] > get_corner(1)[i]) return false;
132  }
133  return true;
134  }
135  //! True if the input bounding box is contained within this bounding box
136  bool get_contains(const BoundingBoxD &bb) const {
137  return get_contains(bb.get_corner(0)) && get_contains(bb.get_corner(1));
138  }
139 
140  IMP_SHOWABLE_INLINE(BoundingBoxD, out << b_[0] << ": " << b_[1]);
141 
142  private:
143  VectorD<D> b_[2];
144 };
145 /** See BoundingBoxD */
146 template <int D>
147 inline double get_volume(const BoundingBoxD<D> &bb) {
148  double v = 1;
149  for (unsigned int i = 0; i < bb.get_dimension(); ++i) {
150  v *= bb.get_corner(1)[i] - bb.get_corner(0)[i];
151  }
152  return v;
153 }
154 
155 IMP_VOLUME_GEOMETRY_METHODS_D(BoundingBox, bounding_box, IMP_UNUSED(g);
157  return (g.get_corner(1)[0] - g.get_corner(0)[0]) *
158  (g.get_corner(1)[1] - g.get_corner(0)[1]) *
159  (g.get_corner(1)[2] - g.get_corner(0)[2]),
160  return g);
161 
162 //! Box with radius one
163 /** See BoundingBoxD */
164 template <unsigned int D>
166  return BoundingBoxD<D>(-get_ones_vector_d<D>(), get_ones_vector_d<D>());
167 }
168 
169 //! Box with radius one
170 /** See BoundingBoxD */
171 inline BoundingBoxD<-1> get_unit_bounding_box_kd(unsigned int d) {
173 }
174 
175 //! Cube with radius of length \c radius
176 /** See BoundingBoxD */
177 template <unsigned int D>
178 inline BoundingBoxD<D> get_cube_d(double radius) {
179  return BoundingBoxD<D>(-radius * get_ones_vector_d<D>(),
180  radius * get_ones_vector_d<D>());
181 }
182 
183 //! Cube with radius of length \c side
184 /** See BoundingBoxD */
185 inline BoundingBoxD<-1> get_cube_kd(unsigned int d, double radius) {
186  return BoundingBoxD<-1>(-radius * get_ones_vector_kd(d),
187  radius * get_ones_vector_kd(d));
188 }
189 
190 //! Return true if they intersect
191 /** See BoundingBoxD */
192 template <int D>
194  const BoundingBoxD<D> &b) {
195  IMP_USAGE_CHECK(a.get_dimension() == b.get_dimension(),
196  "Dimensions of bounding boxes don't match.");
197  for (unsigned int i = 0; i < a.get_dimension(); ++i) {
198  if (a.get_corner(0)[i] > b.get_corner(1)[i]) return false;
199  if (b.get_corner(0)[i] > a.get_corner(1)[i]) return false;
200  }
201  return true;
202 }
203 
204 //! Return the intersecting bounding box
205 /** See BoundingBoxD */
206 template <int D>
208  const BoundingBoxD<D> &b) {
209  VectorD<D> ic[2];
210  // set low
211  int j = 0;
212  for (unsigned int i = 0; i < a.get_dimension(); ++i) {
213  if (a.get_corner(j)[i] > b.get_corner(j)[i]) {
214  ic[j][i] = a.get_corner(j)[i];
215  } else {
216  ic[j][i] = b.get_corner(j)[i];
217  }
218  }
219  // set top
220  j = 1;
221  for (unsigned int i = 0; i < a.get_dimension(); ++i) {
222  if (a.get_corner(j)[i] < b.get_corner(j)[i]) {
223  ic[j][i] = a.get_corner(j)[i];
224  } else {
225  ic[j][i] = b.get_corner(j)[i];
226  }
227  }
228  return BoundingBoxD<D>(ic[0], ic[1]);
229 }
230 
231 //! Return the union bounding box
232 /** This is the same as doing a+b.
233  See BoundingBoxD
234 */
235 template <int D>
237  a += b;
238  return a;
239 }
240 
241 //! Return the maximum axis aligned extent
242 /** See BoundingBoxD */
243 template <int D>
244 inline double get_maximum_length(const BoundingBoxD<D> &a) {
245  double e = a.get_corner(1)[0] - a.get_corner(0)[0];
246  for (unsigned int i = 1; i < a.get_dimension(); ++i) {
247  double ce = a.get_corner(1)[0] - a.get_corner(0)[0];
248  e = std::max(ce, e);
249  }
250  return e;
251 }
252 
253 //! Return a list of the 8 bounding points for the bounding box
254 /** See BoundingBoxD */
256  Vector3Ds ret;
257  ret.reserve(8);
258  for (unsigned int i = 0; i < 2; ++i) {
259  for (unsigned int j = 0; j < 2; ++j) {
260  for (unsigned int k = 0; k < 2; ++k) {
261  ret.push_back(Vector3D(bb.get_corner(i)[0], bb.get_corner(j)[1],
262  bb.get_corner(k)[2]));
263  }
264  }
265  }
266  return ret;
267 }
268 
269 //! Return the edges of the box as indices into the vertices list
270 /** See BoundingBoxD */
272  static const IntPair edges[12] = {
273  IntPair(0, 1), IntPair(0, 2), IntPair(0, 4), IntPair(1, 3),
274  IntPair(1, 5), IntPair(2, 3), IntPair(2, 6), IntPair(3, 7),
275  IntPair(4, 5), IntPair(4, 6), IntPair(5, 7), IntPair(6, 7)};
276  static IntPairs ret(edges, edges + 12);
277  return ret;
278 }
279 
280 IMPALGEBRA_END_NAMESPACE
281 
282 #endif /* IMPALGEBRA_BOUNDING_BOX_D_H */
const BoundingBoxD< D > & operator+=(double o)
Definition: BoundingBoxD.h:100
const VectorD< D > & get_corner(unsigned int i) const
For 0 return lower corner and 1 upper corner.
Definition: BoundingBoxD.h:123
#define IMP_NOT_IMPLEMENTED
Use this to make that the method is not implemented yet.
const BoundingBoxD< D > operator+(const BoundingBoxD< D > &o) const
Returning a bounding box containing both.
Definition: BoundingBoxD.h:109
bool get_contains(const BoundingBoxD &bb) const
True if the input bounding box is contained within this bounding box.
Definition: BoundingBoxD.h:136
const BoundingBoxD< D > operator+(const O &o) const
Return a bounding box grown by o on all sides.
Definition: BoundingBoxD.h:116
double get_maximum_length(const BoundingBoxD< D > &a)
Return the maximum axis aligned extent.
Definition: BoundingBoxD.h:244
IntPairs get_edges(const BoundingBoxD< 3 > &)
Return the edges of the box as indices into the vertices list.
Definition: BoundingBoxD.h:271
BoundingBoxD< D > get_union(BoundingBoxD< D > a, const BoundingBoxD< D > &b)
Return the union bounding box.
Definition: BoundingBoxD.h:236
#define IMP_UNUSED(variable)
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
BoundingBoxD< D > get_cube_d(double radius)
Cube with radius of length radius.
Definition: BoundingBoxD.h:178
Vector3Ds get_vertices(const BoundingBoxD< 3 > &bb)
Return a list of the 8 bounding points for the bounding box.
Definition: BoundingBoxD.h:255
BoundingBoxD(unsigned int d)
Create an empty bounding box.
Definition: BoundingBoxD.h:44
const BoundingBoxD< D > & operator+=(const BoundingBoxD< D > &o)
extend the current bounding box to include the other
Definition: BoundingBoxD.h:82
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
VectorD< D > get_ones_vector_kd(unsigned int Di, double v=1)
Return a vector of ones (or another constant)
Definition: VectorD.h:481
BoundingBoxD< D > get_intersection(const BoundingBoxD< D > &a, const BoundingBoxD< D > &b)
Return the intersecting bounding box.
Definition: BoundingBoxD.h:207
double get_volume(const BoundingBoxD< D > &bb)
Definition: BoundingBoxD.h:147
const BoundingBoxD< D > & operator+=(const VectorD< D > &o)
extend the current bounding box to include the point
Definition: BoundingBoxD.h:91
bool get_interiors_intersect(const BoundingBoxD< D > &a, const BoundingBoxD< D > &b)
Return true if they intersect.
Definition: BoundingBoxD.h:193
A Cartesian vector in D-dimensions.
Definition: VectorD.h:48
BoundingBoxD()
Create an empty bounding box.
Definition: BoundingBoxD.h:37
BoundingBoxD(const VectorInputD< D > &lb, const VectorInputD< D > &ub)
Make from the lower and upper corners.
Definition: BoundingBoxD.h:56
#define IMP_VOLUME_GEOMETRY_METHODS_D(Name, name, area, volume, bounding_box)
implement the needed namespace methods for a geometry type
Simple D vector class.
BoundingBoxD<-1 > get_unit_bounding_box_kd(unsigned int d)
Box with radius one.
Definition: BoundingBoxD.h:171
BoundingBoxD(const base::Vector< VectorD< D > > &points)
Creating a bounding box from a set of points.
Definition: BoundingBoxD.h:72
#define IMP_IF_CHECK(level)
Execute the code block if a certain level checks are on.
BoundingBoxD<-1 > get_cube_kd(unsigned int d, double radius)
Cube with radius of length side.
Definition: BoundingBoxD.h:185
An axis-aligned bounding box.
Definition: BoundingBoxD.h:26
Exception definitions and assertions.
BoundingBoxD(const VectorInputD< D > &v)
Creating a bounding box containing one point.
Definition: BoundingBoxD.h:66
VectorD< 3 > Vector3D
Definition: VectorD.h:587
BoundingBoxD< D > get_unit_bounding_box_d()
Box with radius one.
Definition: BoundingBoxD.h:165
bool get_contains(const VectorD< D > &o) const
True if the point o is contained within this bounding box.
Definition: BoundingBoxD.h:129
Various important macros for implementing geometry.