World Builder  1.1.0-pre
A geodynamic initial conditions generator
bounding_box.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2017 - 2021 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef WORLD_BUILDER_BOUNDING_BOX_H
17 #define WORLD_BUILDER_BOUNDING_BOX_H
18 
19 
20 #include "assert.h"
21 #include "point.h"
22 
23 #include <limits>
24 
25 
26 namespace WorldBuilder
27 {
28 
29 
96  template <unsigned int spacedim>
98  {
99  public:
105  BoundingBox();
106 
113  &boundary_points);
114 
122  template <class Container>
123  BoundingBox(const Container &points);
124 
128  std::pair<Point<spacedim>, Point<spacedim>> &get_boundary_points();
129 
133  const std::pair<Point<spacedim>, Point<spacedim>> &get_boundary_points() const;
134 
138  bool
139  operator==(const BoundingBox<spacedim> &box) const;
140 
144  bool
145  operator!=(const BoundingBox<spacedim> &box) const;
146 
152  void
153  merge_with(const BoundingBox<spacedim> &other_bbox);
154 
165  bool
166  point_inside(
167  const Point<spacedim> &p,
168  const double tolerance = std::numeric_limits<double>::epsilon()) const;
169 
180  void
181  extend(const double amount);
182 
186  double
187  volume() const;
188 
193  center() const;
194 
198  double
199  side_length(const unsigned int direction) const;
200 
204  double
205  lower_bound(const unsigned int direction) const;
206 
210  double
211  upper_bound(const unsigned int direction) const;
212 
213  private:
222  bool
224  const Point<spacedim> &p,
225  const double tolerance = std::numeric_limits<double>::epsilon()) const;
226 
227  std::pair<Point<spacedim>, Point<spacedim>> boundary_points;
228 
229  };
230 
231 
232  /*------------------------ Inline functions: BoundingBox --------------------*/
233 
234 #ifndef DOXYGEN
235 
236 
237  template <>
239  :
240  boundary_points ({{
241  -std::numeric_limits<double>::max(),
242  -std::numeric_limits<double>::max(),
243  cartesian
244  },
245  {
246  +std::numeric_limits<double>::max(),
247  +std::numeric_limits<double>::max(),
248  cartesian
249  }
250  })
251  {}
252 
253  template <>
255  :
256  boundary_points ({{
257  -std::numeric_limits<double>::max(),
258  -std::numeric_limits<double>::max(),
259  -std::numeric_limits<double>::max(),
260  cartesian
261  },
262  {
263  +std::numeric_limits<double>::max(),
264  +std::numeric_limits<double>::max(),
265  +std::numeric_limits<double>::max(),
266  cartesian
267  }
268  })
269  {}
270 
271 
272 
273  template <unsigned int spacedim>
275  const std::pair<Point<spacedim>, Point<spacedim>>
276  &boundary_points_)
277  :
278  boundary_points (boundary_points_)
279  {
280  // We check the Bounding Box is not degenerate
281  for (unsigned int i = 0; i < spacedim; ++i)
282  WBAssert(boundary_points.first[i] <= boundary_points.second[i],
283  "Bounding Box can't be created: the points' "
284  "order should be bottom left, top right!");
285  }
286 
287 
288 
289  template <unsigned int spacedim>
290  template <class Container>
291  inline BoundingBox<spacedim>::BoundingBox(const Container &points)
292  {
293  // Use the default constructor in case points is empty instead of setting
294  // things to +oo and -oo
295  if (points.size() > 0)
296  {
297  auto &min = boundary_points.first;
298  auto &max = boundary_points.second;
299  std::fill(min.begin_raw(),
300  min.end_raw(),
301  std::numeric_limits<double>::infinity());
302  std::fill(max.begin_raw(),
303  max.end_raw(),
304  -std::numeric_limits<double>::infinity());
305 
306  for (const Point<spacedim> &point : points)
307  for (unsigned int d = 0; d < spacedim; ++d)
308  {
309  min[d] = std::min(min[d], point[d]);
310  max[d] = std::max(max[d], point[d]);
311  }
312  }
313  }
314 
315 
316 
317  template <unsigned int spacedim>
318  inline std::pair<Point<spacedim>, Point<spacedim>> &BoundingBox<spacedim>::get_boundary_points()
319  {
320  return this->boundary_points;
321  }
322 
323 
324 
325  template <unsigned int spacedim>
326  inline const std::pair<Point<spacedim>, Point<spacedim>> &BoundingBox<spacedim>::get_boundary_points() const
327  {
328  return this->boundary_points;
329  }
330 
331 
332 
333  template <unsigned int spacedim>
334  inline bool
337  {
338  return boundary_points == box.boundary_points;
339  }
340 
341 
342 
343  template <unsigned int spacedim>
344  inline bool
347  {
348  return boundary_points != box.boundary_points;
349  }
350 
351 
352 
353  template <unsigned int spacedim>
354  inline void
355  BoundingBox<spacedim>::extend(const double amount)
356  {
357  for (unsigned int d = 0; d < spacedim; ++d)
358  {
359  boundary_points.first[d] -= amount;
360  boundary_points.second[d] += amount;
361  WBAssert(boundary_points.first[d] <= boundary_points.second[d],
362  "Bounding Box can't be shrunk this much: the points' "
363  "order should remain bottom left, top right.");
364  }
365  }
366 
367 
368  template <unsigned int spacedim>
369  inline
370  bool
372  const double tolerance) const
373  {
374  WBAssert(boundary_points.first.get_coordinate_system() == point.get_coordinate_system(),
375  "Cannot compare two points which represent different coordinate systems.");
376  WBAssert(boundary_points.second.get_coordinate_system() == point.get_coordinate_system(),
377  "Cannot compare two points which represent different coordinate systems.");
378 
380  {
381  Point<spacedim> other_point = point;
382  if (spacedim == 2)
383  {
384  other_point[0] += point[0] < 0 ? 2.0 * Consts::PI : -2.0 * Consts::PI;
385  }
386  else
387  {
388  // spacedim == 3 (rad,long,lat)
389  other_point[1] += point[1] < 0 ? 2.0 * Consts::PI : -2.0 * Consts::PI;
390  }
391 
392  return (point_inside_implementation(point, tolerance) ||
393  point_inside_implementation(other_point, tolerance));
394  }
395 
396  return point_inside_implementation(point, tolerance);
397 
398  }
399 
400  template <unsigned int spacedim>
401  inline
402  bool
404  const double tolerance) const
405  {
406  WBAssert(boundary_points.first.get_coordinate_system() == p.get_coordinate_system(),
407  "Cannot compare two points which represent different coordinate systems.");
408  WBAssert(boundary_points.second.get_coordinate_system() == p.get_coordinate_system(),
409  "Cannot compare two points which represent different coordinate systems.");
410 
411  for (unsigned int i = 0; i < spacedim; ++i)
412  {
413  // Bottom left-top right convention: the point is outside if it's smaller
414  // than the first or bigger than the second boundary point The bounding
415  // box is defined as a closed set
416  if ((p[i] < this->boundary_points.first[i] -
417  tolerance * std::abs(this->boundary_points.second[i] -
418  this->boundary_points.first[i])) ||
419  (p[i] > this->boundary_points.second[i] +
420  tolerance * std::abs(this->boundary_points.second[i] -
421  this->boundary_points.first[i])))
422  return false;
423  }
424  return true;
425  }
426 
427 
428 
429  template <unsigned int spacedim>
430  inline
431  void
433  const BoundingBox<spacedim> &other_bbox)
434  {
435  for (unsigned int i = 0; i < spacedim; ++i)
436  {
437  this->boundary_points.first[i] =
438  std::min(this->boundary_points.first[i],
439  other_bbox.boundary_points.first[i]);
440  this->boundary_points.second[i] =
441  std::max(this->boundary_points.second[i],
442  other_bbox.boundary_points.second[i]);
443  }
444  }
445 
446 
447 
448  template <unsigned int spacedim>
449  double
451  {
452  double vol = 1.0;
453  for (unsigned int i = 0; i < spacedim; ++i)
454  vol *= (this->boundary_points.second[i] - this->boundary_points.first[i]);
455  return vol;
456  }
457 
458 
459 
460  template <unsigned int spacedim>
461  inline
462  double
463  BoundingBox<spacedim>::lower_bound(const unsigned int direction) const
464  {
465  WBAssert(direction, spacedim);
466 
467  return boundary_points.first[direction];
468  }
469 
470 
471 
472  template <unsigned int spacedim>
473  inline
474  double
475  BoundingBox<spacedim>::upper_bound(const unsigned int direction) const
476  {
477  WBAssert(direction, spacedim);
478 
479  return boundary_points.second[direction];
480  }
481 
482 
483 
484  template <unsigned int spacedim>
487  {
488  Point<spacedim> point = boundary_points.first; // initialize to inherit coordinate system
489  for (unsigned int i = 0; i < spacedim; ++i)
490  point[i] = .5 * (boundary_points.first[i] + boundary_points.second[i]);
491 
492  return point;
493  }
494 
495 
496 
497  template <unsigned int spacedim>
498  inline
499  double
500  BoundingBox<spacedim>::side_length(const unsigned int direction) const
501  {
502  WBAssert(direction < spacedim, "Invalid index");
503 
504  return boundary_points.second[direction] - boundary_points.first[direction];
505  }
506 
507 
508 #endif // DOXYGEN
509 
510 }
511 
512 
513 #endif
double lower_bound(const unsigned int direction) const
Definition: bounding_box.h:463
double side_length(const unsigned int direction) const
Definition: bounding_box.h:500
double upper_bound(const unsigned int direction) const
Definition: bounding_box.h:475
CoordinateSystem get_coordinate_system() const
Definition: point.h:403
std::pair< Point< spacedim >, Point< spacedim > > boundary_points
Definition: bounding_box.h:227
std::pair< Point< spacedim >, Point< spacedim > > & get_boundary_points()
Definition: bounding_box.h:318
void extend(const double amount)
Definition: bounding_box.h:355
#define WBAssert(condition, message)
Definition: assert.h:27
Point< spacedim > center() const
Definition: bounding_box.h:486
bool operator!=(const BoundingBox< spacedim > &box) const
Definition: bounding_box.h:346
bool operator==(const BoundingBox< spacedim > &box) const
Definition: bounding_box.h:336
bool point_inside_implementation(const Point< spacedim > &p, const double tolerance=std::numeric_limits< double >::epsilon()) const
Definition: bounding_box.h:403
constexpr double PI
Definition: consts.h:30
void merge_with(const BoundingBox< spacedim > &other_bbox)
Definition: bounding_box.h:432
bool point_inside(const Point< spacedim > &p, const double tolerance=std::numeric_limits< double >::epsilon()) const
Definition: bounding_box.h:371