Flow123d  jenkins-Flow123d-linux-release-multijob-282
bounding_box.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2007 Technical University of Liberec. All rights reserved.
4  *
5  * Please make a following refer to Flow123d on your project site if you use the program for any purpose,
6  * especially for academic research:
7  * Flow123d, Research Centre: Advanced Remedial Technologies, Technical University of Liberec, Czech Republic
8  *
9  * This program is free software; you can redistribute it and/or modify it under the terms
10  * of the GNU General Public License version 3 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  * See the GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along with this program; if not,
17  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 021110-1307, USA.
18  *
19  *
20  * $Id: bounding_box.hh 1567 2012-02-28 13:24:58Z jan.brezina $
21  * $Revision: 1567 $
22  * $LastChangedBy: jan.brezina $
23  * $LastChangedDate: 2012-02-28 14:24:58 +0100 (Tue, 28 Feb 2012) $
24  *
25  *
26  */
27 
28 #ifndef BOX_ELEMENT_HH_
29 #define BOX_ELEMENT_HH_
30 
31 #include "system/system.hh"
32 #include "system/global_defs.h"
33 #include "mesh/point.hh"
34 
35 #include <vector>
36 #include <armadillo>
37 
38 /**
39  * @brief Bounding box in 3d ambient space.
40  *
41  * Primary intention is usage in BIHTree and various speedups of non-compatible
42  * intersections.
43  *
44  * Copy constructor and assignment are default provided by compiler.
45  * These can be used to set bounds latter on without particular method
46  * to this end:
47  *
48  * @code
49  * BoundingBox box; // non-initialized box
50  * box=BoundingBox( arma::vec3("0 1 2"), arma::vec3("4 5 6") );
51  * @endcode
52  *
53  * Don;t worry about performance, all is inlined.
54  */
55 class BoundingBox {
56 public:
57  TYPEDEF_ERR_INFO( EI_split_point, double);
58  TYPEDEF_ERR_INFO( EI_interval_left, double);
59  TYPEDEF_ERR_INFO( EI_interval_right, double);
60  DECLARE_EXCEPTION(ExcSplitting, << "Split point " << EI_split_point::val
61  << "out of bounds: <" << EI_interval_left::val
62  << ", " << EI_interval_right::val << ">\n");
63 
64  /// Currently we set dimension to 3.
65  static const unsigned int dimension = 3;
66  /// Currently we assume
68 
69  /**
70  * Default constructor.
71  * No initialization of vertices. Be very careful using this.
72  * One necessary usage is vector of BoundigBox.
73  */
75 
76  /**
77  * Constructor for point box.
78  */
80  : min_vertex_(min), max_vertex_(min)
81  {};
82 
83  /**
84  * Constructor.
85  *
86  * From given minimal and maximal vertex.
87  */
88  BoundingBox(const Point &min, const Point &max)
89  : min_vertex_(min), max_vertex_(max)
90  {
91  ASSERT( arma::min( min <= max ) , "Wrong coordinates in constructor.");
92  };
93 
94  /**
95  * Constructor.
96  *
97  * Make bounding box for set of points.
98  */
99  BoundingBox(const vector<Point> &points);
100 
101  /**
102  * Set maximum in given axis.
103  */
104  void set_max(unsigned int axis, double max) {
105  ASSERT_LESS(axis , dimension);
106  ASSERT_LE( min(axis) , max);
107  max_vertex_[axis] = max;
108  }
109 
110  /**
111  * Set minimum on given axis.
112  */
113  void set_min(unsigned int axis, double min) {
114  ASSERT_LESS(axis, dimension);
115  ASSERT_LE(min , max(axis));
116  min_vertex_[axis] = min;
117  }
118 
119  /**
120  * Return minimal vertex of the bounding box.
121  */
122  const Point &min() const {
123  return min_vertex_;
124  }
125 
126  /**
127  * Return maximal vertex of the bounding box.
128  */
129  const Point &max() const {
130  return max_vertex_;
131  }
132 
133  /**
134  * Return minimal value on given axis.
135  */
136  double min(unsigned int axis) const {
137  return min()[axis];
138  }
139 
140  /**
141  * Return maximal value on given axis.
142  */
143  double max(unsigned int axis) const {
144  return max()[axis];
145  }
146 
147 
148  /**
149  * Return size of the box in given axis.
150  */
151  double size(unsigned int axis) const {
152  return max()[axis] - min()[axis];
153  }
154 
155 
156  /**
157  * Return center of the bounding box.
158  */
159  Point center() const {
160  return (max_vertex_ + min_vertex_) / 2.0;
161  }
162 
163  /**
164  * Return center of projection of the bounding box to given @p axis.
165  * Axis coding is: 0 - axis x, 1 - axis y, 2 - axis z.
166  */
167  double projection_center(unsigned int axis) const {
168  ASSERT_LESS(axis, dimension);
169  return (max_vertex_[axis] + min_vertex_[axis])/2;
170  }
171 
172  /**
173  * Returns true is the box element contains @p point
174  *
175  * @param point Testing point
176  * @return True if box element contains point
177  */
178  bool contains_point(const Point &point) const
179  {
180  for (unsigned int i=0; i<dimension; i++) {
181  if ((point(i) + epsilon < min_vertex_(i)) ||
182  (point(i) > epsilon + max_vertex_(i))) return false;
183  }
184  return true;
185  }
186 
187  /**
188  * Returns true if two bounding boxes have intersection.
189  *
190  * This serves as an estimate of intersection of elements.
191  * To make it safe (do not exclude possible intersection) for
192  * 1d and 2d elements aligned with axes, we use some tolerance.
193  * Since this tolerance is fixed, there could be problem with
194  * highly refined meshes (get false positive result).
195  */
196  bool intersect(const BoundingBox &b2) const
197  {
198  for (unsigned int i=0; i<dimension; i++) {
199  if ( (min_vertex_(i) > b2.max_vertex_(i) + epsilon) ||
200  (b2.min_vertex_(i) > max_vertex_(i) + epsilon ) ) return false;
201  }
202  return true;
203  }
204 
205  /**
206  * Returns true if projection of the box to @p axis is an interval
207  * less then (with tolerance) to given @p value.
208  */
209  bool projection_lt(unsigned int axis, double value) const
210  {
211  return max_vertex_(axis) + epsilon < value;
212  }
213 
214  /**
215  * Returns true if projection of the box to @p axis is an interval
216  * greater then (with tolerance) to given @p value.
217  */
218  bool projection_gt(unsigned int axis, double value) const
219  {
220  return min_vertex_(axis) - epsilon > value;
221  }
222 
223  /**
224  * Split box into two boxes along @p axis by the
225  * plane going through @p splitting_point on the axis.
226  */
227  void split(unsigned int axis, double splitting_point,
228  BoundingBox &left, BoundingBox &right ) const
229  {
230  ASSERT_LESS(axis , dimension);
231  if (min_vertex_[axis] <= splitting_point && splitting_point <= max_vertex_[axis] ) {
232  left = *this;
233  right = *this;
234  left.max_vertex_[axis] = splitting_point;
235  right.min_vertex_[axis] = splitting_point;
236  } else {
237  THROW( ExcSplitting() << EI_interval_left(min_vertex_[axis])
238  << EI_interval_right(max_vertex_[axis])
239  << EI_split_point(splitting_point) );
240  }
241  }
242 
243  /**
244  * Expand bounding box to contain also given @p point.
245  */
246  void expand(const Point &point) {
247  for(unsigned int j=0; j<dimension; j++) {
248  min_vertex_(j) = std::min( min_vertex_[j], point[j] );
249  max_vertex_(j) = std::max( max_vertex_[j], point[j] );
250  }
251  }
252 
253  /**
254  * Return index of the axis in which the box has longest projection.
255  */
256  unsigned char longest_axis() const {
257  auto diff=max_vertex_ - min_vertex_;
258  return (diff[1] > diff[0])
259  ? ( diff[2] > diff[1] ? 2 : 1 )
260  : ( diff[2] > diff[0] ? 2 : 0 );
261  }
262 
263 private:
264  /// stabilization parameter
265  static const double epsilon;
266  /// minimal coordinates of bounding box
268  /// maximal coordinates of bounding box
270 };
271 
272 /// Overloads output operator for box.
273 inline ostream &operator<<(ostream &stream, const BoundingBox &box) {
274  stream << "Box("
275  << box.min(0) << " "
276  << box.min(1) << " "
277  << box.min(2) << "; "
278  << box.max(0) << " "
279  << box.max(1) << " "
280  << box.max(2) << ")";
281  return stream;
282 }
283 
284 #endif /* BOX_ELEMENT_HH_ */
void set_max(unsigned int axis, double max)
Bounding box in 3d ambient space.
Definition: bounding_box.hh:55
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:67
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:88
TYPEDEF_ERR_INFO(EI_split_point, double)
Global macros to enhance readability and debugging, general constants.
#define ASSERT(...)
Definition: global_defs.h:121
bool contains_point(const Point &point) const
static const unsigned int dimension
Currently we set dimension to 3.
Definition: bounding_box.hh:65
bool projection_lt(unsigned int axis, double value) const
#define ASSERT_LESS(a, b)
Definition: global_defs.h:164
const Point & max() const
bool projection_gt(unsigned int axis, double value) const
Point center() const
double size(unsigned int axis) const
STREAM & operator<<(STREAM &s, UpdateFlags u)
#define ASSERT_LE(a, b)
Definition: global_defs.h:165
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")
Definition: point.hh:21
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:34
double projection_center(unsigned int axis) const
BoundingBox(const Point &min)
Definition: bounding_box.hh:79