IMP  2.3.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-2014 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 "internal/utility.h"
14 #include "algebra_macros.h"
15 #include <IMP/base/exception.h>
16 
17 IMPALGEBRA_BEGIN_NAMESPACE
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>
27 class BoundingBoxD {
28  void make_empty() {
29  for (int i = 0; i < D; ++i) {
30  b_[0][i] = std::numeric_limits<double>::max();
31  b_[1][i] = -std::numeric_limits<double>::max();
32  }
33  }
34 
35  public:
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
56  BoundingBoxD(const VectorD<D> &lb, const VectorD<D> &ub) {
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 VectorD<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 */
255 template <int D>
257  if (D == 1) {
258  base::Vector<VectorD<D> > ret(2);
259  ret[0] = bb.get_corner(0);
260  ret[1] = bb.get_corner(1);
261  return ret;
262  }
263  if (D == -1) {
265  }
267  for (int i = 0; i < D - 1; ++i) {
268  c0[i] = bb.get_corner(0)[i];
269  c1[i] = bb.get_corner(1)[i];
270  }
274  for (unsigned int i = 0; i < recurse.size(); ++i) {
275  VectorD<D> cur;
276  for (int j = 0; j < D - 1; ++j) {
277  cur[j] = recurse[i][j];
278  }
279  cur[D - 1] = bb.get_corner(0)[D - 1];
280  ret.push_back(cur);
281  cur[D - 1] = bb.get_corner(1)[D - 1];
282  ret.push_back(cur);
283  }
284  return ret;
285 }
286 
287 //! Return the edges of the box as indices into the vertices list
288 /** \see BoundingBoxD */
290  static const IntPair edges[12] = {
291  IntPair(0, 1), IntPair(0, 2), IntPair(0, 4), IntPair(1, 3),
292  IntPair(1, 5), IntPair(2, 3), IntPair(2, 6), IntPair(3, 7),
293  IntPair(4, 5), IntPair(4, 6), IntPair(5, 7), IntPair(6, 7)};
294  static IntPairs ret(edges, edges + 12);
295  return ret;
296 }
297 
298 IMPALGEBRA_END_NAMESPACE
299 
300 #endif /* IMPALGEBRA_BOUNDING_BOX_D_H */
const BoundingBoxD< D > & operator+=(double o)
Definition: BoundingBoxD.h:100
#define IMP_SHOWABLE_INLINE(Name, how_to_show)
Declare the methods needed by an object that can be printed.
const VectorD< D > & get_corner(unsigned int i) const
For 0 return lower corner and 1 upper corner.
Definition: BoundingBoxD.h:123
#define IMP_IF_CHECK(level)
Execute the code block if a certain level checks are on.
Definition: check_macros.h:106
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
double get_volume(const Cone3D &g)
Definition: Cone3D.h:64
IntPairs get_edges(const BoundingBoxD< 3 > &)
Return the edges of the box as indices into the vertices list.
Definition: BoundingBoxD.h:289
BoundingBoxD< D > get_union(BoundingBoxD< D > a, const BoundingBoxD< D > &b)
Return the union bounding box.
Definition: BoundingBoxD.h:236
BoundingBoxD< D > get_cube_d(double radius)
Cube with radius of length radius.
Definition: BoundingBoxD.h:178
Exception definitions and assertions.
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
VectorD< D > get_ones_vector_kd(unsigned int Di, double v=1)
Return a vector of ones (or another constant)
Definition: VectorD.h:289
BoundingBoxD< D > get_intersection(const BoundingBoxD< D > &a, const BoundingBoxD< D > &b)
Return the intersecting bounding box.
Definition: BoundingBoxD.h:207
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:52
BoundingBoxD()
Create an empty bounding box.
Definition: BoundingBoxD.h:37
#define IMP_UNUSED(variable)
#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
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:27
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:170
base::Vector< VectorD< D > > get_vertices(const BoundingBoxD< D > &bb)
Return a list of the 8 bounding points for the bounding box.
Definition: BoundingBoxD.h:256
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
#define IMP_NOT_IMPLEMENTED
Use this to mark that the method is not implemented yet.
Definition: check_macros.h:83
BoundingBoxD(const VectorD< D > &v)
Creating a bounding box containing one point.
Definition: BoundingBoxD.h:66
Various important macros for implementing geometry.
BoundingBoxD(const VectorD< D > &lb, const VectorD< D > &ub)
Make from the lower and upper corners.
Definition: BoundingBoxD.h:56