Flow123d  release_3.0.0-506-g34af125
bounding_box.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file bounding_box.hh
15  * @brief
16  */
17 
18 #ifndef BOX_ELEMENT_HH_
19 #define BOX_ELEMENT_HH_
20 
21 #include <string.h> // for memcpy
22 #include <algorithm> // for max, min
23 #include <boost/exception/detail/error_info_impl.hpp> // for error_info
24 #include <boost/exception/info.hpp> // for operator<<
25 #include <new> // for operator new[]
26 #include <ostream> // for operator<<
27 #include <string> // for basic_string
28 #include <vector> // for vector
29 #include <armadillo>
30 #include "mesh/point.hh" // for Space, Space<>...
31 #include "system/exc_common.hh" // for ExcAssertMsg
32 #include "system/exceptions.hh" // for ExcStream, ope...
33 #include "system/global_defs.h" // for msg, rank, ss
34 
35 using namespace std;
36 
37 /**
38  * @brief Bounding box in 3d ambient space.
39  *
40  * Primary intention is usage in BIHTree and various speedups of non-compatible
41  * intersections.
42  *
43  * Copy constructor and assignment are default provided by compiler.
44  * These can be used to set bounds latter on without particular method
45  * to this end:
46  *
47  * @code
48  * BoundingBox box; // non-initialized box
49  * box=BoundingBox( arma::vec3("0 1 2"), arma::vec3("4 5 6") );
50  * @endcode
51  *
52  * Don;t worry about performance, all is inlined.
53  */
54 class BoundingBox {
55 public:
56  TYPEDEF_ERR_INFO( EI_split_point, double);
57  TYPEDEF_ERR_INFO( EI_interval_left, double);
58  TYPEDEF_ERR_INFO( EI_interval_right, double);
59  DECLARE_EXCEPTION(ExcSplitting, << "Split point " << EI_split_point::val
60  << "out of bounds: <" << EI_interval_left::val
61  << ", " << EI_interval_right::val << ">\n");
62 
63  /// Currently we set dimension to 3.
64  static const unsigned int dimension = 3;
65  /// stabilization parameter
66  static const double epsilon;
67  /// Currently we assume
69 
70 
71  /**
72  * Default constructor.
73  * No initialization of vertices. Be very careful using this.
74  * One necessary usage is vector of BoundigBox.
75  */
77 
78  /**
79  * Constructor for point box.
80  */
81  BoundingBox(const Point &min)
82  : min_vertex_(min), max_vertex_(min)
83  {};
84 
85  /**
86  * Constructor.
87  *
88  * From given minimal and maximal vertex.
89  */
90  BoundingBox(const Point &min, const Point &max)
91  : min_vertex_(min), max_vertex_(max)
92  {
93  OLD_ASSERT( arma::min( min <= max ) , "Wrong coordinates in constructor.");
94  };
95 
96  /**
97  * Constructor.
98  *
99  * Make bounding box for set of points.
100  */
101  BoundingBox(const vector<Point> &points);
102 
103  /**
104  * Set maximum in given axis.
105  */
106  void set_max(unsigned int axis, double max) {
107  ASSERT_LT( axis , dimension);
108  ASSERT_LE( min(axis) , max);
109  max_vertex_[axis] = max;
110  }
111 
112  /**
113  * Set minimum on given axis.
114  */
115  void set_min(unsigned int axis, double min) {
116  ASSERT_LT(axis, dimension);
117  ASSERT_LE(min , max(axis));
118  min_vertex_[axis] = min;
119  }
120 
121  /**
122  * Return minimal vertex of the bounding box.
123  */
124  const Point &min() const {
125  return min_vertex_;
126  }
127 
128  /**
129  * Return maximal vertex of the bounding box.
130  */
131  const Point &max() const {
132  return max_vertex_;
133  }
134 
135  /**
136  * Return minimal value on given axis.
137  */
138  double min(unsigned int axis) const {
139  return min()[axis];
140  }
141 
142  /**
143  * Return maximal value on given axis.
144  */
145  double max(unsigned int axis) const {
146  return max()[axis];
147  }
148 
149 
150  /**
151  * Return size of the box in given axis.
152  */
153  double size(unsigned int axis) const {
154  return max()[axis] - min()[axis];
155  }
156 
157 
158  /**
159  * Return center of the bounding box.
160  */
161  Point center() const {
162  return (max_vertex_ + min_vertex_) / 2.0;
163  }
164 
165  /**
166  * Return center of projection of the bounding box to given @p axis.
167  * Axis coding is: 0 - axis x, 1 - axis y, 2 - axis z.
168  */
169  double projection_center(unsigned int axis) const {
170  ASSERT_LT(axis, dimension);
171  return (max_vertex_[axis] + min_vertex_[axis])/2;
172  }
173 
174  /**
175  * Returns true is the box element contains @p point
176  *
177  * @param point Testing point
178  * @return True if box element contains point
179  */
180  bool contains_point(const Point &point) const
181  {
182  for (unsigned int i=0; i<dimension; i++) {
183  if ((point(i) + epsilon < min_vertex_(i)) ||
184  (point(i) > epsilon + max_vertex_(i))) return false;
185  }
186  return true;
187  }
188 
189  /**
190  * Returns true if two bounding boxes have intersection.
191  *
192  * This serves as an estimate of intersection of elements.
193  * To make it safe (do not exclude possible intersection) for
194  * 1d and 2d elements aligned with axes, we use some tolerance.
195  * Since this tolerance is fixed, there could be problem with
196  * highly refined meshes (get false positive result).
197  */
198  bool intersect(const BoundingBox &b2) const
199  {
200  for (unsigned int i=0; i<dimension; i++) {
201  if ( (min_vertex_(i) > b2.max_vertex_(i) + epsilon) ||
202  (b2.min_vertex_(i) > max_vertex_(i) + epsilon ) ) return false;
203  }
204  return true;
205  }
206 
207  /**
208  * Returns true if projection of the box to @p axis is an interval
209  * less then (with tolerance) to given @p value.
210  */
211  bool projection_lt(unsigned int axis, double value) const
212  {
213  return max_vertex_(axis) + epsilon < value;
214  }
215 
216  /**
217  * Returns true if projection of the box to @p axis is an interval
218  * greater then (with tolerance) to given @p value.
219  */
220  bool projection_gt(unsigned int axis, double value) const
221  {
222  return min_vertex_(axis) - epsilon > value;
223  }
224 
225  /**
226  * Split box into two boxes along @p axis by the
227  * plane going through @p splitting_point on the axis.
228  */
229  void split(unsigned int axis, double splitting_point,
230  BoundingBox &left, BoundingBox &right ) const
231  {
232  ASSERT_LT(axis , dimension);
233  if (min_vertex_[axis] <= splitting_point && splitting_point <= max_vertex_[axis] ) {
234  left = *this;
235  right = *this;
236  left.max_vertex_[axis] = splitting_point;
237  right.min_vertex_[axis] = splitting_point;
238  } else {
239  THROW( ExcSplitting() << EI_interval_left(min_vertex_[axis])
240  << EI_interval_right(max_vertex_[axis])
241  << EI_split_point(splitting_point) );
242  }
243  }
244 
245  /**
246  * Expand bounding box to contain also given @p point.
247  */
248  void expand(const Point &point) {
249  for(unsigned int j=0; j<dimension; j++) {
250  min_vertex_(j) = std::min( min_vertex_[j], point[j] );
251  max_vertex_(j) = std::max( max_vertex_[j], point[j] );
252  }
253  }
254 
255  /**
256  * Expand bounding box to contain also given @p box.
257  */
258  void expand(const BoundingBox &box) {
259  for(unsigned int j=0; j<dimension; j++) {
260  min_vertex_[j] = std::min( min_vertex_[j], box.min_vertex_[j] );
261  max_vertex_[j] = std::max( max_vertex_[j], box.max_vertex_[j] );
262  }
263  }
264 
265  /**
266  * Return index of the axis in which the box has longest projection.
267  */
268  unsigned char longest_axis() const {
269  auto diff=max_vertex_ - min_vertex_;
270  return (diff[1] > diff[0])
271  ? ( diff[2] > diff[1] ? 2 : 1 )
272  : ( diff[2] > diff[0] ? 2 : 0 );
273  }
274 
275  /**
276  * Project point to bounding box.
277  *
278  * If point is in bounding box, returns its.
279  */
280  Point project_point(const Point &point) const {
281  Point projected_point;
282  for (unsigned int i=0; i<dimension; ++i) {
283  if ( projection_gt(i, point[i]) ) projected_point[i] = min_vertex_(i);
284  else if ( projection_lt(i, point[i]) ) projected_point[i] = max_vertex_(i);
285  else projected_point[i] = point[i];
286  }
287 
288  return projected_point;
289  }
290 
291 
292 private:
293  /// minimal coordinates of bounding box
294  Point min_vertex_;
295  /// maximal coordinates of bounding box
296  Point max_vertex_;
297 };
298 
299 /// Overloads output operator for box.
300 inline ostream &operator<<(ostream &stream, const BoundingBox &box) {
301  stream << "Box("
302  << box.min(0) << " "
303  << box.min(1) << " "
304  << box.min(2) << "; "
305  << box.max(0) << " "
306  << box.max(1) << " "
307  << box.max(2) << ")";
308  return stream;
309 }
310 
311 #endif /* BOX_ELEMENT_HH_ */
void set_max(unsigned int axis, double max)
Bounding box in 3d ambient space.
Definition: bounding_box.hh:54
void split(unsigned int axis, double splitting_point, BoundingBox &left, BoundingBox &right) const
unsigned char longest_axis() const
Space< dimension >::Point Point
Currently we assume.
Definition: bounding_box.hh:68
#define DECLARE_EXCEPTION(ExcName, Format)
Macro for simple definition of exceptions.
Definition: exceptions.hh:158
double max(unsigned int axis) const
double min(unsigned int axis) const
Point min_vertex_
minimal coordinates of bounding box
void expand(const Point &point)
#define ASSERT_LE(a, b)
Definition of comparative assert macro (Less or Equal)
Definition: asserts.hh:303
static const double epsilon
stabilization parameter
Definition: bounding_box.hh:66
Point max_vertex_
maximal coordinates of bounding box
bool intersect(const BoundingBox &b2) const
static constexpr bool value
Definition: json.hpp:87
BoundingBox(const Point &min, const Point &max)
Definition: bounding_box.hh:90
ostream & operator<<(ostream &stream, const BoundingBox &box)
Overloads output operator for box.
void expand(const BoundingBox &box)
#define OLD_ASSERT(...)
Definition: global_defs.h:131
Global macros to enhance readability and debugging, general constants.
bool contains_point(const Point &point) const
bool projection_lt(unsigned int axis, double value) const
const Point & max() const
bool projection_gt(unsigned int axis, double value) const
Point center() const
#define TYPEDEF_ERR_INFO(EI_Type, Type)
Macro to simplify declaration of error_info types.
Definition: exceptions.hh:194
double size(unsigned int axis) const
#define ASSERT_LT(a, b)
Definition of comparative assert macro (Less Than)
Definition: asserts.hh:295
void set_min(unsigned int axis, double min)
Point project_point(const Point &point) const
const Point & min() const
Definition: point.hh:40
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
double projection_center(unsigned int axis) const
BoundingBox(const Point &min)
Definition: bounding_box.hh:81