IMP logo
IMP Reference Guide  develop.3beb078e5e,2026/08/23
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-2026 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 <IMP/algebra/VectorD.h>
14 #include "internal/utility.h"
15 #include <IMP/exception.h>
16 #include <cereal/access.hpp>
17 
18 IMPALGEBRA_BEGIN_NAMESPACE
19 
20 //! An axis-aligned bounding box.
21 /** The BoundingBoxD class provides a unified representation for bounding
22  boxes in \imp. Geometric objects should have an associated namespace
23  method like get_bounding_box() which returns the bounding boxes of objects.
24 
25  \note This class is a \ref geometricprimitives "geometric primitive".
26 */
27 template <int D>
28 class BoundingBoxD {
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 
36  public:
37  //! Create an empty bounding box
39  /* Let SWIG make uninitialized BoundingBoxKD objects (see issue #843).
40  Otherwise, any function that returns a BoundingBoxKD will fail, since
41  SWIG generates code that looks like:
42  BoundingBoxKD result;
43  ...
44  result = call_imp_function()
45  The usage check for BoundingBoxKD is moved from here to the SWIG wrapper
46  itself, so a user still can't make a default-constructed BoundingBoxKD
47  in Python.
48  */
49 #if defined(IMP_SWIG_WRAPPER)
50  if (D > 0) {
51  make_empty();
52  }
53 #else
54  IMP_USAGE_CHECK(D > 0, "The constructor cannot be used "
55  << "with a variable dimension bounding box.");
56 
57  make_empty();
58 #endif
59  }
60  //! Create an empty bounding box
61  explicit BoundingBoxD(unsigned int d) {
62  IMP_USAGE_CHECK(D == -1, "The constructor can only be used "
63  << "with a variable dimension bounding box.");
64  Floats lb(d), ub(d);
65  for (unsigned int i = 0; i < d; ++i) {
66  lb[i] = std::numeric_limits<double>::max();
67  ub[i] = -std::numeric_limits<double>::max();
68  }
69  b_[0] = VectorD<D>(lb.begin(), lb.end());
70  b_[1] = VectorD<D>(ub.begin(), ub.end());
71  }
72  //! Make from the lower and upper corners
73  BoundingBoxD(const VectorD<D> &lb, const VectorD<D> &ub) {
74  b_[0] = lb;
75  b_[1] = ub;
77  for (unsigned int i = 0; i < lb.get_dimension(); ++i) {
78  IMP_USAGE_CHECK(lb[i] <= ub[i], "Invalid bounding box");
79  }
80  }
81  }
82  //! Creating a bounding box containing one point
83  explicit BoundingBoxD(const VectorD<D> &v) {
84  b_[0] = v;
85  b_[1] = v;
86  }
87 
88  //! Creating a bounding box from a set of points
89  BoundingBoxD(const Vector<VectorD<D>> &points) {
90  make_empty();
91  for (unsigned int j = 0; j < points.size(); j++) {
92  operator+=(points[j]);
93  }
94  }
95 
96  unsigned int get_dimension() const {
97  return get_corner_0().get_dimension();
98  }
99 
100  //! Extend the current bounding box to include the other
102  for (unsigned int i = 0; i < get_dimension(); ++i) {
103  b_[0][i] = std::min(o.get_corner_0()[i], get_corner_0()[i]);
104  b_[1][i] = std::max(o.get_corner_1()[i], get_corner_1()[i]);
105  }
106  return *this;
107  }
108 
109  //! Extend the current bounding box to include the point
111  for (unsigned int i = 0; i < get_dimension(); ++i) {
112  b_[0][i] = std::min(o[i], b_[0][i]);
113  b_[1][i] = std::max(o[i], b_[1][i]);
114  }
115  return *this;
116  }
117 
118  //! Grow the bounding box by o on all sizes.
119  const BoundingBoxD<D> &operator+=(double o) {
120  for (unsigned int i = 0; i < get_dimension(); ++i) {
121  b_[0][i] = b_[0][i] - o;
122  b_[1][i] = b_[1][i] + o;
123  }
124  return *this;
125  }
126  //! Returning a bounding box containing both
127  template <class O>
128  const BoundingBoxD<D> operator+(const BoundingBoxD<D> &o) const {
129  BoundingBoxD<D> ret(*this);
130  ret += o;
131  return ret;
132  }
133  //! Return a bounding box grown by o on all sides
134  template <class O>
135  const BoundingBoxD<D> operator+(const O &o) const {
136  BoundingBoxD<D> ret(*this);
137  ret += o;
138  return ret;
139  }
140 
141  //! For 0 return lower corner and for 1, the upper corner
142  const VectorD<D> &get_corner(unsigned int i) const {
143  IMP_USAGE_CHECK(i < 2, "Can only use 0 or 1");
144  return b_[i];
145  }
146 
147  //! Get the lower corner of the box
148  /** This should be a litle faster than get_corner(0) since it skips
149  the bounds check. */
150  const VectorD<D> &get_corner_0() const {
151  return b_[0];
152  }
153 
154  //! Get the upper corner of the box
155  /** This should be a litle faster than get_corner(1) since it skips
156  the bounds check. */
157  const VectorD<D> &get_corner_1() const {
158  return b_[1];
159  }
160 
161  //! True if the point o is contained within this bounding box
162  bool get_contains(const VectorD<D> &o) const {
163  for (unsigned int i = 0; i < get_dimension(); ++i) {
164  if (o[i] < get_corner_0()[i] || o[i] > get_corner_1()[i]) {
165  return false;
166  }
167  }
168  return true;
169  }
170  //! True if the input bounding box is completely contained within this one
171  bool get_contains(const BoundingBoxD &bb) const {
172  return get_contains(bb.get_corner_0()) && get_contains(bb.get_corner_1());
173  }
174 
175  IMP_SHOWABLE_INLINE(BoundingBoxD, out << b_[0] << ": " << b_[1]);
176 
177  private:
178  VectorD<D> b_[2];
179 
180  friend class cereal::access;
181 
182  template<class Archive> void serialize(Archive &ar) {
183  ar(b_[0], b_[1]);
184  }
185 };
186 //! See BoundingBoxD
187 template <int D>
188 inline double get_volume(const BoundingBoxD<D> &bb) {
189  double v = 1;
190  for (unsigned int i = 0; i < bb.get_dimension(); ++i) {
191  v *= bb.get_corner_1()[i] - bb.get_corner_0()[i];
192  }
193  return v;
194 }
195 
196 IMP_VOLUME_GEOMETRY_METHODS_D(BoundingBox, bounding_box, IMP_UNUSED(g);
198  return (g.get_corner_1()[0] - g.get_corner_0()[0]) *
199  (g.get_corner_1()[1] - g.get_corner_0()[1]) *
200  (g.get_corner_1()[2] - g.get_corner_0()[2]),
201  return g);
202 
203 //! Box with radius one
204 /** \see BoundingBoxD */
205 template <unsigned int D>
207  return BoundingBoxD<D>(-get_ones_vector_d<D>(), get_ones_vector_d<D>());
208 }
209 
210 //! Box with radius one
211 /** \see BoundingBoxD */
212 inline BoundingBoxD<-1> get_unit_bounding_box_kd(unsigned int d) {
214 }
215 
216 //! Cube with radius of length \c radius
217 /** \see BoundingBoxD */
218 template <unsigned int D>
219 inline BoundingBoxD<D> get_cube_d(double radius) {
220  return BoundingBoxD<D>(-radius * get_ones_vector_d<D>(),
221  radius * get_ones_vector_d<D>());
222 }
223 
224 //! Cube with radius of length \c side
225 /** \see BoundingBoxD */
226 inline BoundingBoxD<-1> get_cube_kd(unsigned int d, double radius) {
227  return BoundingBoxD<-1>(-radius * get_ones_vector_kd(d),
228  radius * get_ones_vector_kd(d));
229 }
230 
231 //! Return true if they intersect
232 /** \see BoundingBoxD */
233 template <int D>
235  const BoundingBoxD<D> &b) {
236  IMP_USAGE_CHECK(a.get_dimension() == b.get_dimension(),
237  "Dimensions of bounding boxes don't match.");
238  for (unsigned int i = 0; i < a.get_dimension(); ++i) {
239  if (a.get_corner_0()[i] > b.get_corner_1()[i]) {
240  return false;
241  }
242  if (b.get_corner_0()[i] > a.get_corner_1()[i]) {
243  return false;
244  }
245  }
246  return true;
247 }
248 
249 //! Return the intersecting bounding box
250 /** \see BoundingBoxD */
251 template <int D>
253  const BoundingBoxD<D> &b) {
254  /* Make sure that for D=-1 the vectors ic[01] get the correct dimension */
255  VectorD<D> ic0 = a.get_corner_0();
256  VectorD<D> ic1 = a.get_corner_1();
257  // set low
258  for (unsigned int i = 0; i < a.get_dimension(); ++i) {
259  if (a.get_corner_0()[i] > b.get_corner_0()[i]) {
260  ic0[i] = a.get_corner_0()[i];
261  } else {
262  ic0[i] = b.get_corner_0()[i];
263  }
264  }
265  // set top
266  for (unsigned int i = 0; i < a.get_dimension(); ++i) {
267  if (a.get_corner_1()[i] < b.get_corner_1()[i]) {
268  ic1[i] = a.get_corner_1()[i];
269  } else {
270  ic1[i] = b.get_corner_1()[i];
271  }
272  }
273  return BoundingBoxD<D>(ic0, ic1);
274 }
275 
276 //! Return the union bounding box
277 /** This is the same as doing a+b.
278  \see BoundingBoxD
279 */
280 template <int D>
282  a += b;
283  return a;
284 }
285 
286 //! Return the maximum axis aligned extent
287 /** \see BoundingBoxD */
288 template <int D>
289 inline double get_maximum_length(const BoundingBoxD<D> &a) {
290  double e = a.get_corner_1()[0] - a.get_corner_0()[0];
291  for (unsigned int i = 1; i < a.get_dimension(); ++i) {
292  double ce = a.get_corner_1()[0] - a.get_corner_0()[0];
293  e = std::max(ce, e);
294  }
295  return e;
296 }
297 
298 //! Return a list of the 2^D bounding points for the bounding box
299 /** \see BoundingBoxD */
300 template <int D>
302  if (D == 1) {
303  Vector<VectorD<D>> ret(2);
304  ret[0] = bb.get_corner_0();
305  ret[1] = bb.get_corner_1();
306  return ret;
307  }
308  if (D == -1) {
310  }
312  for (int i = 0; i < D - 1; ++i) {
313  c0[i] = bb.get_corner_0()[i];
314  c1[i] = bb.get_corner_1()[i];
315  }
318  Vector<VectorD<D>> ret;
319  for (unsigned int i = 0; i < recurse.size(); ++i) {
320  VectorD<D> cur;
321  for (int j = 0; j < D - 1; ++j) {
322  cur[j] = recurse[i][j];
323  }
324  cur[D - 1] = bb.get_corner_0()[D - 1];
325  ret.push_back(cur);
326  cur[D - 1] = bb.get_corner_1()[D - 1];
327  ret.push_back(cur);
328  }
329  return ret;
330 }
331 
332 //! Return the edges of the box as indices into the vertices list
333 /** \see BoundingBoxD */
335  static const IntPair edges[12] = {
336  IntPair(0, 1), IntPair(0, 2), IntPair(0, 4), IntPair(1, 3),
337  IntPair(1, 5), IntPair(2, 3), IntPair(2, 6), IntPair(3, 7),
338  IntPair(4, 5), IntPair(4, 6), IntPair(5, 7), IntPair(6, 7)};
339  static IntPairs ret(edges, edges + 12);
340  return ret;
341 }
342 
343 IMPALGEBRA_END_NAMESPACE
344 
345 #endif /* IMPALGEBRA_BOUNDING_BOX_D_H */
const BoundingBoxD< D > & operator+=(double o)
Grow the bounding box by o on all sizes.
Definition: BoundingBoxD.h:119
A Cartesian vector in D-dimensions.
Definition: VectorD.h:38
VectorD< D > get_ones_vector_kd(unsigned int Di, double v=1)
Return a vector of ones (or another constant)
Definition: VectorD.h:295
#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 for 1, the upper corner.
Definition: BoundingBoxD.h:142
#define IMP_IF_CHECK(level)
Execute the code block if a certain level checks are on.
Definition: check_macros.h:104
const BoundingBoxD< D > operator+(const BoundingBoxD< D > &o) const
Returning a bounding box containing both.
Definition: BoundingBoxD.h:128
bool get_contains(const BoundingBoxD &bb) const
True if the input bounding box is completely contained within this one.
Definition: BoundingBoxD.h:171
const BoundingBoxD< D > operator+(const O &o) const
Return a bounding box grown by o on all sides.
Definition: BoundingBoxD.h:135
Vector< VectorD< D > > get_vertices(const BoundingBoxD< D > &bb)
Return a list of the 2^D bounding points for the bounding box.
Definition: BoundingBoxD.h:301
const VectorD< D > & get_corner_0() const
Get the lower corner of the box.
Definition: BoundingBoxD.h:150
double get_maximum_length(const BoundingBoxD< D > &a)
Return the maximum axis aligned extent.
Definition: BoundingBoxD.h:289
double get_volume(const Cone3D &g)
Definition: Cone3D.h:71
IntPairs get_edges(const BoundingBoxD< 3 > &)
Return the edges of the box as indices into the vertices list.
Definition: BoundingBoxD.h:334
BoundingBoxD< D > get_union(BoundingBoxD< D > a, const BoundingBoxD< D > &b)
Return the union bounding box.
Definition: BoundingBoxD.h:281
BoundingBoxD< D > get_cube_d(double radius)
Cube with radius of length radius.
Definition: BoundingBoxD.h:219
Exception definitions and assertions.
BoundingBoxD(unsigned int d)
Create an empty bounding box.
Definition: BoundingBoxD.h:61
const BoundingBoxD< D > & operator+=(const BoundingBoxD< D > &o)
Extend the current bounding box to include the other.
Definition: BoundingBoxD.h:101
BoundingBoxD< D > get_intersection(const BoundingBoxD< D > &a, const BoundingBoxD< D > &b)
Return the intersecting bounding box.
Definition: BoundingBoxD.h:252
const BoundingBoxD< D > & operator+=(const VectorD< D > &o)
Extend the current bounding box to include the point.
Definition: BoundingBoxD.h:110
bool get_interiors_intersect(const BoundingBoxD< D > &a, const BoundingBoxD< D > &b)
Return true if they intersect.
Definition: BoundingBoxD.h:234
BoundingBoxD()
Create an empty bounding box.
Definition: BoundingBoxD.h:38
#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.
BoundingBoxD<-1 > get_unit_bounding_box_kd(unsigned int d)
Box with radius one.
Definition: BoundingBoxD.h:212
BoundingBoxD<-1 > get_cube_kd(unsigned int d, double radius)
Cube with radius of length side.
Definition: BoundingBoxD.h:226
An axis-aligned bounding box.
Definition: BoundingBoxD.h:28
#define IMP_USAGE_CHECK(expr, message)
A runtime test for incorrect usage of a class or method.
Definition: check_macros.h:168
BoundingBoxD< D > get_unit_bounding_box_d()
Box with radius one.
Definition: BoundingBoxD.h:206
bool get_contains(const VectorD< D > &o) const
True if the point o is contained within this bounding box.
Definition: BoundingBoxD.h:162
#define IMP_NOT_IMPLEMENTED
Use this to mark that the method is not implemented yet.
Definition: check_macros.h:81
BoundingBoxD(const VectorD< D > &v)
Creating a bounding box containing one point.
Definition: BoundingBoxD.h:83
Various important macros for implementing geometry.
Simple D vector class.
const VectorD< D > & get_corner_1() const
Get the upper corner of the box.
Definition: BoundingBoxD.h:157
BoundingBoxD(const Vector< VectorD< D >> &points)
Creating a bounding box from a set of points.
Definition: BoundingBoxD.h:89
BoundingBoxD(const VectorD< D > &lb, const VectorD< D > &ub)
Make from the lower and upper corners.
Definition: BoundingBoxD.h:73