libMesh
bounding_box.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 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 contains_point() more readable.
30 inline bool is_between(Real min, Real check, Real max)
31 {
32  return min <= check && check <= max;
33 }
34 
35 bool BoundingBox::contains_point (const Point & p) const
36 {
37  // Make local variables first to make things more clear in a moment
38  Real my_min_x = this->first(0);
39  Real my_max_x = this->second(0);
40  bool x_int = is_between(my_min_x, p(0), my_max_x);
41 
42  bool intersection_true = x_int;
43 
44 #if LIBMESH_DIM > 1
45  Real my_min_y = this->first(1);
46  Real my_max_y = this->second(1);
47  bool y_int = is_between(my_min_y, p(1), my_max_y);
48 
49  intersection_true = intersection_true && y_int;
50 #endif
51 
52 
53 #if LIBMESH_DIM > 2
54  Real my_min_z = this->first(2);
55  Real my_max_z = this->second(2);
56  bool z_int = is_between(my_min_z, p(2), my_max_z);
57 
58  intersection_true = intersection_true && z_int;
59 #endif
60 
61  return intersection_true;
62 }
63 
64 
65 
67 {
68  Real size = 0;
69  for (unsigned int d = 0; d != LIBMESH_DIM; ++d)
70  {
71  Real sized = this->second(d) - this->first(d);
72  if (!libmesh_isinf(sized) &&
73  this->second(d) != std::numeric_limits<Real>::max() &&
74  this->first(d) != -std::numeric_limits<Real>::max())
75  size = std::max(size, sized);
76  }
77  return size;
78 }
79 
80 
81 
83  (const Point & p, Real abs_tol, Real rel_tol) const
84 {
85  libmesh_assert_greater_equal(abs_tol, Real(0));
86  libmesh_assert_greater_equal(rel_tol, Real(0));
87 
88  // Just use the other contains_point overload
89  libmesh_assert_greater(rel_tol+abs_tol, Real(0));
90 
91  // Find absolute tolerance from relative tolerance
92  const Real tol = std::max(abs_tol, this->max_size()*rel_tol);
93 
94  // Make local variables first to make things more clear in a moment
95  const Real my_min_x = this->first(0) - tol;
96  const Real my_max_x = this->second(0) + tol;
97  const bool x_int = is_between(my_min_x, p(0), my_max_x);
98 
99  bool intersection_true = x_int;
100 
101 #if LIBMESH_DIM > 1
102  const Real my_min_y = this->first(1) - tol;
103  const Real my_max_y = this->second(1) + tol;
104  const bool y_int = is_between(my_min_y, p(1), my_max_y);
105 
106  intersection_true = intersection_true && y_int;
107 #endif
108 
109 
110 #if LIBMESH_DIM > 2
111  const Real my_min_z = this->first(2) - tol;
112  const Real my_max_z = this->second(2) + tol;
113  const bool z_int = is_between(my_min_z, p(2), my_max_z);
114 
115  intersection_true = intersection_true && z_int;
116 #endif
117 
118  return intersection_true;
119 }
120 
121 
122 
123 void BoundingBox::intersect_with (const BoundingBox & other_box)
124 {
125  this->first(0) = std::max(this->first(0), other_box.first(0));
126  this->second(0) = std::min(this->second(0), other_box.second(0));
127 
128 #if LIBMESH_DIM > 1
129  this->first(1) = std::max(this->first(1), other_box.first(1));
130  this->second(1) = std::min(this->second(1), other_box.second(1));
131 #endif
132 
133 #if LIBMESH_DIM > 2
134  this->first(2) = std::max(this->first(2), other_box.first(2));
135  this->second(2) = std::min(this->second(2), other_box.second(2));
136 #endif
137 }
138 
139 
140 void BoundingBox::union_with (const BoundingBox & other_box)
141 {
142  this->first(0) = std::min(this->first(0), other_box.first(0));
143  this->second(0) = std::max(this->second(0), other_box.second(0));
144 
145 #if LIBMESH_DIM > 1
146  this->first(1) = std::min(this->first(1), other_box.first(1));
147  this->second(1) = std::max(this->second(1), other_box.second(1));
148 #endif
149 
150 #if LIBMESH_DIM > 2
151  this->first(2) = std::min(this->first(2), other_box.first(2));
152  this->second(2) = std::max(this->second(2), other_box.second(2));
153 #endif
154 }
155 
156 
157 
159 {
160  if (contains_point(p))
161  {
162  // Sign convention: if Point is inside the bbox, the distance is
163  // negative. We then find the smallest distance to the different
164  // sides of the box and return that.
165  Real min_dist = std::numeric_limits<Real>::max();
166 
167  for (unsigned int dir=0; dir<LIBMESH_DIM; ++dir)
168  {
169  min_dist = std::min(min_dist, std::abs(p(dir) - second(dir)));
170  min_dist = std::min(min_dist, std::abs(p(dir) - first(dir)));
171  }
172 
173  return -min_dist;
174  }
175  else // p is outside the box
176  {
177  Real dx[3] = {0., 0., 0.};
178 
179  // Compute distance "above"/"below" the box in each
180  // direction. If the point is somewhere in between the (min,
181  // max) values of the box, dx is 0.
182  for (unsigned int dir=0; dir<LIBMESH_DIM; ++dir)
183  {
184  if (p(dir) > second(dir))
185  dx[dir] = p(dir) - second(dir);
186  else if (p(dir) < first(dir))
187  dx[dir] = p(dir) - first(dir);
188  }
189 
190  return std::sqrt(dx[0]*dx[0] + dx[1]*dx[1] + dx[2]*dx[2]);
191  }
192 }
193 
194 
195 void BoundingBox::scale(const Real factor)
196 {
197  Real append;
198  for (unsigned int dim = 0; dim != LIBMESH_DIM; ++dim)
199  {
200  if (this->first(dim) != std::numeric_limits<Real>::max() &&
201  this->second(dim) != -std::numeric_limits<Real>::max())
202  {
203  libmesh_assert_greater_equal(this->second(dim), this->first(dim));
204  append = (this->second(dim) - this->first(dim)) * factor;
205  this->first(dim) -= append;
206  this->second(dim) += append;
207  }
208  }
209 }
210 
211 
212 void BoundingBox::print(std::ostream & os) const
213 {
214  os << "(min=" << this->min() << ", max=" << this->max() << ")";
215 }
216 
217 } // namespace libMesh
bool contains_point(const Point &) const
Definition: bounding_box.C:35
unsigned int dim
void intersect_with(const BoundingBox &)
Sets this bounding box to be the intersection with the other bounding box.
Definition: bounding_box.C:123
The libMesh namespace provides an interface to certain functionality in the library.
bool libmesh_isinf(T x)
Real signed_distance(const Point &p) const
Computes the signed distance, d, from a given Point p to this BoundingBox.
Definition: bounding_box.C:158
const Point & min() const
Definition: bounding_box.h:77
Real max_size() const
Returns the maximum size of a finite box extent.
Definition: bounding_box.C:66
bool is_between(Real min, Real check, Real max)
Definition: bounding_box.C:30
void print(std::ostream &os=libMesh::out) const
Formatted print, by default to libMesh::out.
Definition: bounding_box.C:212
Defines a Cartesian bounding box by the two corner extremum.
Definition: bounding_box.h:40
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void union_with(const Point &p)
Enlarges this bounding box to include the given point.
Definition: bounding_box.h:286
const Point & max() const
Definition: bounding_box.h:86
void scale(const Real factor)
Scales each dimension of the bounding box by factor.
Definition: bounding_box.C:195
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39