bounding_box.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // Local includes
21 #include "libmesh/bounding_box.h"
22 
23 // C++ includes
24 #include <algorithm> // std::min_element
25 #include <array>
26 
27 namespace libMesh
28 {
29 // Small helper function to make intersects() more readable.
30 bool is_between(Real min, Real check, Real max)
31 {
32  return min <= check && check <= max;
33 }
34 
35 bool BoundingBox::intersects (const BoundingBox & other_box) const
36 {
37  // Make local variables first to make things more clear in a moment
38  const Real & my_min_x = this->first(0);
39  const Real & my_max_x = this->second(0);
40  const Real & other_min_x = other_box.first(0);
41  const Real & other_max_x = other_box.second(0);
42 
43  const bool x_int = is_between(my_min_x, other_min_x, my_max_x) || is_between(my_min_x, other_max_x, my_max_x) ||
44  is_between(other_min_x, my_min_x, other_max_x) || is_between(other_min_x, my_max_x, other_max_x);
45 
46  bool intersection_true = x_int;
47 
48 #if LIBMESH_DIM > 1
49  const Real & my_min_y = this->first(1);
50  const Real & my_max_y = this->second(1);
51  const Real & other_min_y = other_box.first(1);
52  const Real & other_max_y = other_box.second(1);
53 
54  const bool y_int = is_between(my_min_y, other_min_y, my_max_y) || is_between(my_min_y, other_max_y, my_max_y) ||
55  is_between(other_min_y, my_min_y, other_max_y) || is_between(other_min_y, my_max_y, other_max_y);
56 
57  intersection_true = intersection_true && y_int;
58 #endif
59 
60 #if LIBMESH_DIM > 2
61  const Real & my_min_z = this->first(2);
62  const Real & my_max_z = this->second(2);
63  const Real & other_min_z = other_box.first(2);
64  const Real & other_max_z = other_box.second(2);
65 
66  const bool z_int = is_between(my_min_z, other_min_z, my_max_z) || is_between(my_min_z, other_max_z, my_max_z) ||
67  is_between(other_min_z, my_min_z, other_max_z) || is_between(other_min_z, my_max_z, other_max_z);
68 
69  intersection_true = intersection_true && z_int;
70 #endif
71 
72  return intersection_true;
73 }
74 
75 bool BoundingBox::intersects (const BoundingBox & other_box,
76  Real abstol) const
77 {
78  // If you want to use abstol==0, you need to call the "exact"
79  // comparison version of the intersects() function.
80  libmesh_assert(abstol > 0.);
81 
82  // Make local variables first to make things more clear in a moment
83  const Real & my_min_x = this->first(0);
84  const Real & my_max_x = this->second(0);
85  const Real & ot_min_x = other_box.first(0);
86  const Real & ot_max_x = other_box.second(0);
87 
88  const bool x_int =
89  is_between(my_min_x - abstol, ot_min_x, my_max_x + abstol) ||
90  is_between(my_min_x - abstol, ot_max_x, my_max_x + abstol) ||
91  is_between(ot_min_x - abstol, my_min_x, ot_max_x + abstol) ||
92  is_between(ot_min_x - abstol, my_max_x, ot_max_x + abstol);
93 
94  bool intersection_true = x_int;
95 
96  if (!intersection_true)
97  return false;
98 
99 #if LIBMESH_DIM > 1
100  const Real & my_min_y = this->first(1);
101  const Real & my_max_y = this->second(1);
102  const Real & ot_min_y = other_box.first(1);
103  const Real & ot_max_y = other_box.second(1);
104 
105  const bool y_int =
106  is_between(my_min_y - abstol, ot_min_y, my_max_y + abstol) ||
107  is_between(my_min_y - abstol, ot_max_y, my_max_y + abstol) ||
108  is_between(ot_min_y - abstol, my_min_y, ot_max_y + abstol) ||
109  is_between(ot_min_y - abstol, my_max_y, ot_max_y + abstol);
110 
111  intersection_true = intersection_true && y_int;
112 
113  if (!intersection_true)
114  return false;
115 #endif
116 
117 #if LIBMESH_DIM > 2
118  const Real & my_min_z = this->first(2);
119  const Real & my_max_z = this->second(2);
120  const Real & ot_min_z = other_box.first(2);
121  const Real & ot_max_z = other_box.second(2);
122 
123  const bool z_int =
124  is_between(my_min_z - abstol, ot_min_z, my_max_z + abstol) ||
125  is_between(my_min_z - abstol, ot_max_z, my_max_z + abstol) ||
126  is_between(ot_min_z - abstol, my_min_z, ot_max_z + abstol) ||
127  is_between(ot_min_z - abstol, my_max_z, ot_max_z + abstol);
128 
129  intersection_true = intersection_true && z_int;
130 #endif
131 
132  return intersection_true;
133 }
134 
135 bool BoundingBox::contains_point (const Point & p) const
136 {
137  // Make local variables first to make things more clear in a moment
138  Real my_min_x = this->first(0);
139  Real my_max_x = this->second(0);
140  bool x_int = is_between(my_min_x, p(0), my_max_x);
141 
142  bool intersection_true = x_int;
143 
144 #if LIBMESH_DIM > 1
145  Real my_min_y = this->first(1);
146  Real my_max_y = this->second(1);
147  bool y_int = is_between(my_min_y, p(1), my_max_y);
148 
149  intersection_true = intersection_true && y_int;
150 #endif
151 
152 
153 #if LIBMESH_DIM > 2
154  Real my_min_z = this->first(2);
155  Real my_max_z = this->second(2);
156  bool z_int = is_between(my_min_z, p(2), my_max_z);
157 
158  intersection_true = intersection_true && z_int;
159 #endif
160 
161  return intersection_true;
162 }
163 
164 
165 void BoundingBox::intersect_with (const BoundingBox & other_box)
166 {
167  this->first(0) = std::max(this->first(0), other_box.first(0));
168  this->second(0) = std::min(this->second(0), other_box.second(0));
169 
170 #if LIBMESH_DIM > 1
171  this->first(1) = std::max(this->first(1), other_box.first(1));
172  this->second(1) = std::min(this->second(1), other_box.second(1));
173 #endif
174 
175 #if LIBMESH_DIM > 2
176  this->first(2) = std::max(this->first(2), other_box.first(2));
177  this->second(2) = std::min(this->second(2), other_box.second(2));
178 #endif
179 }
180 
181 
182 void BoundingBox::union_with (const BoundingBox & other_box)
183 {
184  this->first(0) = std::min(this->first(0), other_box.first(0));
185  this->second(0) = std::max(this->second(0), other_box.second(0));
186 
187 #if LIBMESH_DIM > 1
188  this->first(1) = std::min(this->first(1), other_box.first(1));
189  this->second(1) = std::max(this->second(1), other_box.second(1));
190 #endif
191 
192 #if LIBMESH_DIM > 2
193  this->first(2) = std::min(this->first(2), other_box.first(2));
194  this->second(2) = std::max(this->second(2), other_box.second(2));
195 #endif
196 }
197 
198 
199 
201 {
202  if (contains_point(p))
203  {
204  // Sign convention: if Point is inside the bbox, the distance is
205  // negative. We then find the smallest distance to the different
206  // sides of the box and return that.
208 
209  for (unsigned int dir=0; dir<LIBMESH_DIM; ++dir)
210  {
211  min_dist = std::min(min_dist, std::abs(p(dir) - second(dir)));
212  min_dist = std::min(min_dist, std::abs(p(dir) - first(dir)));
213  }
214 
215  return -min_dist;
216  }
217  else // p is outside the box
218  {
219  Real dx[3] = {0., 0., 0.};
220 
221  // Compute distance "above"/"below" the box in each
222  // direction. If the point is somewhere in between the (min,
223  // max) values of the box, dx is 0.
224  for (unsigned int dir=0; dir<LIBMESH_DIM; ++dir)
225  {
226  if (p(dir) > second(dir))
227  dx[dir] = p(dir) - second(dir);
228  else if (p(dir) < first(dir))
229  dx[dir] = p(dir) - first(dir);
230  }
231 
232  return std::sqrt(dx[0]*dx[0] + dx[1]*dx[1] + dx[2]*dx[2]);
233  }
234 }
235 
236 } // namespace libMesh
double abs(double a)
bool contains_point(const Point &) const
Definition: bounding_box.C:135
void intersect_with(const BoundingBox &)
Definition: bounding_box.C:165
bool intersects(const BoundingBox &) const
Definition: bounding_box.C:35
long double max(long double a, double b)
Real signed_distance(const Point &p) const
Definition: bounding_box.C:200
bool is_between(Real min, Real check, Real max)
Definition: bounding_box.C:30
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void union_with(const Point &p)
Definition: bounding_box.h:163
long double min(long double a, double b)
A geometric point in (x,y,z) space.
Definition: point.h:38