libMesh
Loading...
Searching...
No Matches
bounding_box.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
27namespace libMesh
28{
29// Small helper function to make contains_point() more readable.
30inline bool is_between(Real min, Real check, Real max)
31{
32 return min <= check && check <= max;
33}
34
35bool 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
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
140void 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
195void 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
212void BoundingBox::print(std::ostream & os) const
213{
214 os << "(min=" << this->min() << ", max=" << this->max() << ")";
215}
216
217} // namespace libMesh
unsigned int dim
Defines a Cartesian bounding box by the two corner extremum.
Real signed_distance(const Point &p) const
Computes the signed distance, d, from a given Point p to this BoundingBox.
Real max_size() const
Returns the maximum size of a finite box extent.
const Point & max() const
void scale(const Real factor)
Scales each dimension of the bounding box by factor.
const Point & min() const
bool contains_point(const Point &) const
void union_with(const Point &p)
Enlarges this bounding box to include the given point.
void intersect_with(const BoundingBox &)
Sets this bounding box to be the intersection with the other bounding box.
void print(std::ostream &os=libMesh::out) const
Formatted print, by default to libMesh::out.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
The libMesh namespace provides an interface to certain functionality in the library.
bool libmesh_isinf(T x)
bool is_between(Real min, Real check, Real max)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real