Flow123d  last_with_con_2.0.0-4-g42e6930
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 "system/system.hh"
22 #include "system/global_defs.h"
23 #include "mesh/point.hh"
24 
25 #include <vector>
26 #include <armadillo>
27 
28 /**
29  * @brief Bounding box in 3d ambient space.
30  *
31  * Primary intention is usage in BIHTree and various speedups of non-compatible
32  * intersections.
33  *
34  * Copy constructor and assignment are default provided by compiler.
35  * These can be used to set bounds latter on without particular method
36  * to this end:
37  *
38  * @code
39  * BoundingBox box; // non-initialized box
40  * box=BoundingBox( arma::vec3("0 1 2"), arma::vec3("4 5 6") );
41  * @endcode
42  *
43  * Don;t worry about performance, all is inlined.
44  */
45 class BoundingBox {
46 public:
47  TYPEDEF_ERR_INFO( EI_split_point, double);
48  TYPEDEF_ERR_INFO( EI_interval_left, double);
49  TYPEDEF_ERR_INFO( EI_interval_right, double);
50  DECLARE_EXCEPTION(ExcSplitting, << "Split point " << EI_split_point::val
51  << "out of bounds: <" << EI_interval_left::val
52  << ", " << EI_interval_right::val << ">\n");
53 
54  /// Currently we set dimension to 3.
55  static const unsigned int dimension = 3;
56  /// Currently we assume
58 
59  /**
60  * Default constructor.
61  * No initialization of vertices. Be very careful using this.
62  * One necessary usage is vector of BoundigBox.
63  */
65 
66  /**
67  * Constructor for point box.
68  */
69  BoundingBox(const Point &min)
70  : min_vertex_(min), max_vertex_(min)
71  {};
72 
73  /**
74  * Constructor.
75  *
76  * From given minimal and maximal vertex.
77  */
78  BoundingBox(const Point &min, const Point &max)
79  : min_vertex_(min), max_vertex_(max)
80  {
81  OLD_ASSERT( arma::min( min <= max ) , "Wrong coordinates in constructor.");
82  };
83 
84  /**
85  * Constructor.
86  *
87  * Make bounding box for set of points.
88  */
89  BoundingBox(const vector<Point> &points);
90 
91  /**
92  * Set maximum in given axis.
93  */
94  void set_max(unsigned int axis, double max) {
95  OLD_ASSERT_LESS(axis , dimension);
96  OLD_ASSERT_LE( min(axis) , max);
97  max_vertex_[axis] = max;
98  }
99 
100  /**
101  * Set minimum on given axis.
102  */
103  void set_min(unsigned int axis, double min) {
104  OLD_ASSERT_LESS(axis, dimension);
105  OLD_ASSERT_LE(min , max(axis));
106  min_vertex_[axis] = min;
107  }
108 
109  /**
110  * Return minimal vertex of the bounding box.
111  */
112  const Point &min() const {
113  return min_vertex_;
114  }
115 
116  /**
117  * Return maximal vertex of the bounding box.
118  */
119  const Point &max() const {
120  return max_vertex_;
121  }
122 
123  /**
124  * Return minimal value on given axis.
125  */
126  double min(unsigned int axis) const {
127  return min()[axis];
128  }
129 
130  /**
131  * Return maximal value on given axis.
132  */
133  double max(unsigned int axis) const {
134  return max()[axis];
135  }
136 
137 
138  /**
139  * Return size of the box in given axis.
140  */
141  double size(unsigned int axis) const {
142  return max()[axis] - min()[axis];
143  }
144 
145 
146  /**
147  * Return center of the bounding box.
148  */
149  Point center() const {
150  return (max_vertex_ + min_vertex_) / 2.0;
151  }
152 
153  /**
154  * Return center of projection of the bounding box to given @p axis.
155  * Axis coding is: 0 - axis x, 1 - axis y, 2 - axis z.
156  */
157  double projection_center(unsigned int axis) const {
158  OLD_ASSERT_LESS(axis, dimension);
159  return (max_vertex_[axis] + min_vertex_[axis])/2;
160  }
161 
162  /**
163  * Returns true is the box element contains @p point
164  *
165  * @param point Testing point
166  * @return True if box element contains point
167  */
168  bool contains_point(const Point &point) const
169  {
170  for (unsigned int i=0; i<dimension; i++) {
171  if ((point(i) + epsilon < min_vertex_(i)) ||
172  (point(i) > epsilon + max_vertex_(i))) return false;
173  }
174  return true;
175  }
176 
177  /**
178  * Returns true if two bounding boxes have intersection.
179  *
180  * This serves as an estimate of intersection of elements.
181  * To make it safe (do not exclude possible intersection) for
182  * 1d and 2d elements aligned with axes, we use some tolerance.
183  * Since this tolerance is fixed, there could be problem with
184  * highly refined meshes (get false positive result).
185  */
186  bool intersect(const BoundingBox &b2) const
187  {
188  for (unsigned int i=0; i<dimension; i++) {
189  if ( (min_vertex_(i) > b2.max_vertex_(i) + epsilon) ||
190  (b2.min_vertex_(i) > max_vertex_(i) + epsilon ) ) return false;
191  }
192  return true;
193  }
194 
195  /**
196  * Returns true if projection of the box to @p axis is an interval
197  * less then (with tolerance) to given @p value.
198  */
199  bool projection_lt(unsigned int axis, double value) const
200  {
201  return max_vertex_(axis) + epsilon < value;
202  }
203 
204  /**
205  * Returns true if projection of the box to @p axis is an interval
206  * greater then (with tolerance) to given @p value.
207  */
208  bool projection_gt(unsigned int axis, double value) const
209  {
210  return min_vertex_(axis) - epsilon > value;
211  }
212 
213  /**
214  * Split box into two boxes along @p axis by the
215  * plane going through @p splitting_point on the axis.
216  */
217  void split(unsigned int axis, double splitting_point,
218  BoundingBox &left, BoundingBox &right ) const
219  {
220  OLD_ASSERT_LESS(axis , dimension);
221  if (min_vertex_[axis] <= splitting_point && splitting_point <= max_vertex_[axis] ) {
222  left = *this;
223  right = *this;
224  left.max_vertex_[axis] = splitting_point;
225  right.min_vertex_[axis] = splitting_point;
226  } else {
227  THROW( ExcSplitting() << EI_interval_left(min_vertex_[axis])
228  << EI_interval_right(max_vertex_[axis])
229  << EI_split_point(splitting_point) );
230  }
231  }
232 
233  /**
234  * Expand bounding box to contain also given @p point.
235  */
236  void expand(const Point &point) {
237  for(unsigned int j=0; j<dimension; j++) {
238  min_vertex_(j) = std::min( min_vertex_[j], point[j] );
239  max_vertex_(j) = std::max( max_vertex_[j], point[j] );
240  }
241  }
242 
243  /**
244  * Return index of the axis in which the box has longest projection.
245  */
246  unsigned char longest_axis() const {
247  auto diff=max_vertex_ - min_vertex_;
248  return (diff[1] > diff[0])
249  ? ( diff[2] > diff[1] ? 2 : 1 )
250  : ( diff[2] > diff[0] ? 2 : 0 );
251  }
252 
253 private:
254  /// stabilization parameter
255  static const double epsilon;
256  /// minimal coordinates of bounding box
257  Point min_vertex_;
258  /// maximal coordinates of bounding box
259  Point max_vertex_;
260 };
261 
262 /// Overloads output operator for box.
263 inline ostream &operator<<(ostream &stream, const BoundingBox &box) {
264  stream << "Box("
265  << box.min(0) << " "
266  << box.min(1) << " "
267  << box.min(2) << "; "
268  << box.max(0) << " "
269  << box.max(1) << " "
270  << box.max(2) << ")";
271  return stream;
272 }
273 
274 #endif /* BOX_ELEMENT_HH_ */
void set_max(unsigned int axis, double max)
Definition: bounding_box.hh:94
Bounding box in 3d ambient space.
Definition: bounding_box.hh:45
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:57
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)
static const double epsilon
stabilization parameter
Point max_vertex_
maximal coordinates of bounding box
bool intersect(const BoundingBox &b2) const
BoundingBox(const Point &min, const Point &max)
Definition: bounding_box.hh:78
ostream & operator<<(ostream &stream, const BoundingBox &box)
Overloads output operator for box.
TYPEDEF_ERR_INFO(EI_split_point, double)
#define OLD_ASSERT(...)
Definition: global_defs.h:131
Global macros to enhance readability and debugging, general constants.
bool contains_point(const Point &point) const
static const unsigned int dimension
Currently we set dimension to 3.
Definition: bounding_box.hh:55
bool projection_lt(unsigned int axis, double value) const
#define OLD_ASSERT_LESS(a, b)
Definition: global_defs.h:134
const Point & max() const
bool projection_gt(unsigned int axis, double value) const
Point center() const
double size(unsigned int axis) const
void set_min(unsigned int axis, double min)
const Point & min() const
DECLARE_EXCEPTION(ExcSplitting,<< "Split point "<< EI_split_point::val<< "out of bounds: <"<< EI_interval_left::val<< ", "<< EI_interval_right::val<< ">\n")
#define OLD_ASSERT_LE(a, b)
Definition: global_defs.h:135
Definition: point.hh:31
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:45
double projection_center(unsigned int axis) const
BoundingBox(const Point &min)
Definition: bounding_box.hh:69