Flow123d  release_2.2.0-914-gf1a3a4f
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  /// stabilization parameter
57  static const double epsilon;
58  /// Currently we assume
60 
61 
62  /**
63  * Default constructor.
64  * No initialization of vertices. Be very careful using this.
65  * One necessary usage is vector of BoundigBox.
66  */
68 
69  /**
70  * Constructor for point box.
71  */
72  BoundingBox(const Point &min)
73  : min_vertex_(min), max_vertex_(min)
74  {};
75 
76  /**
77  * Constructor.
78  *
79  * From given minimal and maximal vertex.
80  */
81  BoundingBox(const Point &min, const Point &max)
82  : min_vertex_(min), max_vertex_(max)
83  {
84  OLD_ASSERT( arma::min( min <= max ) , "Wrong coordinates in constructor.");
85  };
86 
87  /**
88  * Constructor.
89  *
90  * Make bounding box for set of points.
91  */
92  BoundingBox(const vector<Point> &points);
93 
94  /**
95  * Set maximum in given axis.
96  */
97  void set_max(unsigned int axis, double max) {
98  OLD_ASSERT_LESS(axis , dimension);
99  OLD_ASSERT_LE( min(axis) , max);
100  max_vertex_[axis] = max;
101  }
102 
103  /**
104  * Set minimum on given axis.
105  */
106  void set_min(unsigned int axis, double min) {
107  OLD_ASSERT_LESS(axis, dimension);
108  OLD_ASSERT_LE(min , max(axis));
109  min_vertex_[axis] = min;
110  }
111 
112  /**
113  * Return minimal vertex of the bounding box.
114  */
115  const Point &min() const {
116  return min_vertex_;
117  }
118 
119  /**
120  * Return maximal vertex of the bounding box.
121  */
122  const Point &max() const {
123  return max_vertex_;
124  }
125 
126  /**
127  * Return minimal value on given axis.
128  */
129  double min(unsigned int axis) const {
130  return min()[axis];
131  }
132 
133  /**
134  * Return maximal value on given axis.
135  */
136  double max(unsigned int axis) const {
137  return max()[axis];
138  }
139 
140 
141  /**
142  * Return size of the box in given axis.
143  */
144  double size(unsigned int axis) const {
145  return max()[axis] - min()[axis];
146  }
147 
148 
149  /**
150  * Return center of the bounding box.
151  */
152  Point center() const {
153  return (max_vertex_ + min_vertex_) / 2.0;
154  }
155 
156  /**
157  * Return center of projection of the bounding box to given @p axis.
158  * Axis coding is: 0 - axis x, 1 - axis y, 2 - axis z.
159  */
160  double projection_center(unsigned int axis) const {
161  OLD_ASSERT_LESS(axis, dimension);
162  return (max_vertex_[axis] + min_vertex_[axis])/2;
163  }
164 
165  /**
166  * Returns true is the box element contains @p point
167  *
168  * @param point Testing point
169  * @return True if box element contains point
170  */
171  bool contains_point(const Point &point) const
172  {
173  for (unsigned int i=0; i<dimension; i++) {
174  if ((point(i) + epsilon < min_vertex_(i)) ||
175  (point(i) > epsilon + max_vertex_(i))) return false;
176  }
177  return true;
178  }
179 
180  /**
181  * Returns true if two bounding boxes have intersection.
182  *
183  * This serves as an estimate of intersection of elements.
184  * To make it safe (do not exclude possible intersection) for
185  * 1d and 2d elements aligned with axes, we use some tolerance.
186  * Since this tolerance is fixed, there could be problem with
187  * highly refined meshes (get false positive result).
188  */
189  bool intersect(const BoundingBox &b2) const
190  {
191  for (unsigned int i=0; i<dimension; i++) {
192  if ( (min_vertex_(i) > b2.max_vertex_(i) + epsilon) ||
193  (b2.min_vertex_(i) > max_vertex_(i) + epsilon ) ) return false;
194  }
195  return true;
196  }
197 
198  /**
199  * Returns true if projection of the box to @p axis is an interval
200  * less then (with tolerance) to given @p value.
201  */
202  bool projection_lt(unsigned int axis, double value) const
203  {
204  return max_vertex_(axis) + epsilon < value;
205  }
206 
207  /**
208  * Returns true if projection of the box to @p axis is an interval
209  * greater then (with tolerance) to given @p value.
210  */
211  bool projection_gt(unsigned int axis, double value) const
212  {
213  return min_vertex_(axis) - epsilon > value;
214  }
215 
216  /**
217  * Split box into two boxes along @p axis by the
218  * plane going through @p splitting_point on the axis.
219  */
220  void split(unsigned int axis, double splitting_point,
221  BoundingBox &left, BoundingBox &right ) const
222  {
223  OLD_ASSERT_LESS(axis , dimension);
224  if (min_vertex_[axis] <= splitting_point && splitting_point <= max_vertex_[axis] ) {
225  left = *this;
226  right = *this;
227  left.max_vertex_[axis] = splitting_point;
228  right.min_vertex_[axis] = splitting_point;
229  } else {
230  THROW( ExcSplitting() << EI_interval_left(min_vertex_[axis])
231  << EI_interval_right(max_vertex_[axis])
232  << EI_split_point(splitting_point) );
233  }
234  }
235 
236  /**
237  * Expand bounding box to contain also given @p point.
238  */
239  void expand(const Point &point) {
240  for(unsigned int j=0; j<dimension; j++) {
241  min_vertex_(j) = std::min( min_vertex_[j], point[j] );
242  max_vertex_(j) = std::max( max_vertex_[j], point[j] );
243  }
244  }
245 
246  /**
247  * Return index of the axis in which the box has longest projection.
248  */
249  unsigned char longest_axis() const {
250  auto diff=max_vertex_ - min_vertex_;
251  return (diff[1] > diff[0])
252  ? ( diff[2] > diff[1] ? 2 : 1 )
253  : ( diff[2] > diff[0] ? 2 : 0 );
254  }
255 
256  /**
257  * Project point to bounding box.
258  *
259  * If point is in bounding box, returns its.
260  */
261  Point project_point(const Point &point) const {
262  Point projected_point;
263  for (unsigned int i=0; i<dimension; ++i) {
264  if ( projection_gt(i, point[i]) ) projected_point[i] = min_vertex_(i);
265  else if ( projection_lt(i, point[i]) ) projected_point[i] = max_vertex_(i);
266  else projected_point[i] = point[i];
267  }
268 
269  return projected_point;
270  }
271 
272 
273 private:
274  /// minimal coordinates of bounding box
275  Point min_vertex_;
276  /// maximal coordinates of bounding box
277  Point max_vertex_;
278 };
279 
280 /// Overloads output operator for box.
281 inline ostream &operator<<(ostream &stream, const BoundingBox &box) {
282  stream << "Box("
283  << box.min(0) << " "
284  << box.min(1) << " "
285  << box.min(2) << "; "
286  << box.max(0) << " "
287  << box.max(1) << " "
288  << box.max(2) << ")";
289  return stream;
290 }
291 
292 #endif /* BOX_ELEMENT_HH_ */
void set_max(unsigned int axis, double max)
Definition: bounding_box.hh:97
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:59
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
Definition: bounding_box.hh:57
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:81
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)
Point project_point(const Point &point) const
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:53
double projection_center(unsigned int axis) const
BoundingBox(const Point &min)
Definition: bounding_box.hh:72