Reference documentation for deal.II version GIT 85a786e179 2022-11-27 23:15:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
bounding_box.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2017 - 2021 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
18 
19 #include <limits>
20 
22 
23 template <int spacedim, typename Number>
24 bool
26  const double tolerance) const
27 {
28  for (unsigned int i = 0; i < spacedim; ++i)
29  {
30  // Bottom left-top right convention: the point is outside if it's smaller
31  // than the first or bigger than the second boundary point The bounding
32  // box is defined as a closed set
33  if ((p[i] < this->boundary_points.first[i] -
34  tolerance * std::abs(this->boundary_points.second[i] -
35  this->boundary_points.first[i])) ||
36  (p[i] > this->boundary_points.second[i] +
37  tolerance * std::abs(this->boundary_points.second[i] -
38  this->boundary_points.first[i])))
39  return false;
40  }
41  return true;
42 }
43 
44 
45 
46 template <int spacedim, typename Number>
47 void
49  const BoundingBox<spacedim, Number> &other_bbox)
50 {
51  for (unsigned int i = 0; i < spacedim; ++i)
52  {
53  this->boundary_points.first[i] =
54  std::min(this->boundary_points.first[i],
55  other_bbox.boundary_points.first[i]);
56  this->boundary_points.second[i] =
57  std::max(this->boundary_points.second[i],
58  other_bbox.boundary_points.second[i]);
59  }
60 }
61 
62 
63 
64 template <int spacedim, typename Number>
67  const BoundingBox<spacedim, Number> &other_bbox,
68  const double tolerance) const
69 {
70  if (spacedim == 1)
71  {
72  // In dimension 1 if the two bounding box are neighbors
73  // we can merge them
74  if (this->point_inside(other_bbox.boundary_points.first, tolerance) ||
75  this->point_inside(other_bbox.boundary_points.second, tolerance))
78  }
79  else
80  {
81  const std::array<Point<spacedim, Number>, 2> bbox1 = {
82  {this->get_boundary_points().first,
83  this->get_boundary_points().second}};
84  const std::array<Point<spacedim, Number>, 2> bbox2 = {
85  {other_bbox.get_boundary_points().first,
86  other_bbox.get_boundary_points().second}};
87 
88  // Step 1: testing if the boxes are close enough to intersect
89  for (unsigned int d = 0; d < spacedim; ++d)
90  if (bbox1[0][d] * (1 - tolerance) > bbox2[1][d] ||
91  bbox2[0][d] * (1 - tolerance) > bbox1[1][d])
93 
94  // The boxes intersect: we need to understand now how they intersect.
95  // We begin by computing the intersection:
96  std::array<double, spacedim> intersect_bbox_min;
97  std::array<double, spacedim> intersect_bbox_max;
98  for (unsigned int d = 0; d < spacedim; ++d)
99  {
100  intersect_bbox_min[d] = std::max(bbox1[0][d], bbox2[0][d]);
101  intersect_bbox_max[d] = std::min(bbox1[1][d], bbox2[1][d]);
102  }
103 
104  // Finding the intersection's dimension
105  int intersect_dim = spacedim;
106  for (unsigned int d = 0; d < spacedim; ++d)
107  if (std::abs(intersect_bbox_min[d] - intersect_bbox_max[d]) <=
108  tolerance * (std::abs(intersect_bbox_min[d]) +
109  std::abs(intersect_bbox_max[d])))
110  --intersect_dim;
111 
112  if (intersect_dim == 0 || intersect_dim == spacedim - 2)
114 
115  // Checking the two mergeable cases: first if the boxes are aligned so
116  // that they can be merged
117  unsigned int not_align_1 = 0, not_align_2 = 0;
118  bool same_direction = true;
119  for (unsigned int d = 0; d < spacedim; ++d)
120  {
121  if (std::abs(bbox2[0][d] - bbox1[0][d]) >
122  tolerance * (std::abs(bbox2[0][d]) + std::abs(bbox1[0][d])))
123  ++not_align_1;
124  if (std::abs(bbox1[1][d] - bbox2[1][d]) >
125  tolerance * (std::abs(bbox1[1][d]) + std::abs(bbox2[1][d])))
126  ++not_align_2;
127  if (not_align_1 != not_align_2)
128  {
129  same_direction = false;
130  break;
131  }
132  }
133 
134  if (not_align_1 <= 1 && not_align_2 <= 1 && same_direction)
136 
137  // Second: one box is contained/equal to the other
138  if ((this->point_inside(bbox2[0]) && this->point_inside(bbox2[1])) ||
139  (other_bbox.point_inside(bbox1[0], tolerance) &&
140  other_bbox.point_inside(bbox1[1], tolerance)))
142 
143  // Degenerate and mergeable cases have been found, it remains:
145  }
146 }
147 
148 
149 
150 template <int spacedim, typename Number>
151 double
153 {
154  double vol = 1.0;
155  for (unsigned int i = 0; i < spacedim; ++i)
156  vol *= (this->boundary_points.second[i] - this->boundary_points.first[i]);
157  return vol;
158 }
159 
160 
161 
162 template <int spacedim, typename Number>
163 Number
164 BoundingBox<spacedim, Number>::lower_bound(const unsigned int direction) const
165 {
166  AssertIndexRange(direction, spacedim);
167 
168  return boundary_points.first[direction];
169 }
170 
171 
172 
173 template <int spacedim, typename Number>
174 Number
175 BoundingBox<spacedim, Number>::upper_bound(const unsigned int direction) const
176 {
177  AssertIndexRange(direction, spacedim);
178 
179  return boundary_points.second[direction];
180 }
181 
182 
183 
184 template <int spacedim, typename Number>
187 {
189  for (unsigned int i = 0; i < spacedim; ++i)
190  point[i] = .5 * (boundary_points.first[i] + boundary_points.second[i]);
191 
192  return point;
193 }
194 
195 
196 
197 template <int spacedim, typename Number>
199 BoundingBox<spacedim, Number>::bounds(const unsigned int direction) const
200 {
201  AssertIndexRange(direction, spacedim);
202 
203  std::pair<Point<1, Number>, Point<1, Number>> lower_upper_bounds;
204  lower_upper_bounds.first[0] = lower_bound(direction);
205  lower_upper_bounds.second[0] = upper_bound(direction);
206 
207  return BoundingBox<1, Number>(lower_upper_bounds);
208 }
209 
210 
211 
212 template <int spacedim, typename Number>
213 Number
214 BoundingBox<spacedim, Number>::side_length(const unsigned int direction) const
215 {
216  AssertIndexRange(direction, spacedim);
217 
218  return boundary_points.second[direction] - boundary_points.first[direction];
219 }
220 
221 
222 
223 template <int spacedim, typename Number>
225 BoundingBox<spacedim, Number>::vertex(const unsigned int index) const
226 {
228 
229  const Point<spacedim> unit_cell_vertex =
231 
233  for (unsigned int i = 0; i < spacedim; ++i)
234  point[i] = boundary_points.first[i] + side_length(i) * unit_cell_vertex[i];
235 
236  return point;
237 }
238 
239 
240 
241 template <int spacedim, typename Number>
243 BoundingBox<spacedim, Number>::child(const unsigned int index) const
244 {
246 
247  // Vertex closest to child.
248  const Point<spacedim, Number> parent_vertex = vertex(index);
249  const Point<spacedim, Number> parent_center = center();
250 
251  const Point<spacedim> upper_corner_unit_cell =
254 
255  const Point<spacedim> lower_corner_unit_cell =
257 
258  std::pair<Point<spacedim, Number>, Point<spacedim, Number>>
259  child_lower_upper_corner;
260  for (unsigned int i = 0; i < spacedim; ++i)
261  {
262  const double child_side_length = side_length(i) / 2;
263 
264  const double child_center = (parent_center[i] + parent_vertex[i]) / 2;
265 
266  child_lower_upper_corner.first[i] =
267  child_center + child_side_length * (lower_corner_unit_cell[i] - .5);
268  child_lower_upper_corner.second[i] =
269  child_center + child_side_length * (upper_corner_unit_cell[i] - .5);
270  }
271 
272  return BoundingBox<spacedim, Number>(child_lower_upper_corner);
273 }
274 
275 
276 
277 template <int spacedim, typename Number>
278 BoundingBox<spacedim - 1, Number>
279 BoundingBox<spacedim, Number>::cross_section(const unsigned int direction) const
280 {
281  AssertIndexRange(direction, spacedim);
282 
283  std::pair<Point<spacedim - 1, Number>, Point<spacedim - 1, Number>>
284  cross_section_lower_upper_corner;
285  for (unsigned int d = 0; d < spacedim - 1; ++d)
286  {
287  const int index_to_write_from =
288  internal::coordinate_to_one_dim_higher<spacedim - 1>(direction, d);
289 
290  cross_section_lower_upper_corner.first[d] =
291  boundary_points.first[index_to_write_from];
292 
293  cross_section_lower_upper_corner.second[d] =
294  boundary_points.second[index_to_write_from];
295  }
296 
297  return BoundingBox<spacedim - 1, Number>(cross_section_lower_upper_corner);
298 }
299 
300 
301 
302 template <int spacedim, typename Number>
305  const Point<spacedim, Number> &point) const
306 {
307  auto unit = point;
308  const auto diag = boundary_points.second - boundary_points.first;
309  unit -= boundary_points.first;
310  for (unsigned int d = 0; d < spacedim; ++d)
311  unit[d] /= diag[d];
312  return unit;
313 }
314 
315 
316 
317 template <int spacedim, typename Number>
320  const Point<spacedim, Number> &point) const
321 {
322  auto real = boundary_points.first;
323  const auto diag = boundary_points.second - boundary_points.first;
324  for (unsigned int d = 0; d < spacedim; ++d)
325  real[d] += diag[d] * point[d];
326  return real;
327 }
328 
329 
330 
331 template <int dim, typename Number>
334 {
335  std::pair<Point<dim, Number>, Point<dim, Number>> lower_upper_corner;
336  for (unsigned int i = 0; i < dim; ++i)
337  {
338  lower_upper_corner.second[i] = 1;
339  }
340  return BoundingBox<dim, Number>(lower_upper_corner);
341 }
342 
343 
344 #include "bounding_box.inst"
NeighborType
Definition: bounding_box.h:34
std::pair< Point< spacedim, Number >, Point< spacedim, Number > > boundary_points
Definition: bounding_box.h:318
BoundingBox< 1, Number > bounds(const unsigned int direction) const
BoundingBox< dim, Number > create_unit_bounding_box()
Point< spacedim, Number > center() const
Number lower_bound(const unsigned int direction) const
void merge_with(const BoundingBox< spacedim, Number > &other_bbox)
Definition: bounding_box.cc:48
bool point_inside(const Point< spacedim, Number > &p, const double tolerance=std::numeric_limits< Number >::epsilon()) const
Definition: bounding_box.cc:25
double volume() const
Point< spacedim, Number > real_to_unit(const Point< spacedim, Number > &point) const
Number side_length(const unsigned int direction) const
BoundingBox< spacedim, Number > child(const unsigned int index) const
NeighborType get_neighbor_type(const BoundingBox< spacedim, Number > &other_bbox, const double tolerance=std::numeric_limits< Number >::epsilon()) const
Definition: bounding_box.cc:66
Point< spacedim, Number > vertex(const unsigned int index) const
std::pair< Point< spacedim, Number >, Point< spacedim, Number > > & get_boundary_points()
BoundingBox< spacedim - 1, Number > cross_section(const unsigned int direction) const
Number upper_bound(const unsigned int direction) const
Point< spacedim, Number > unit_to_real(const Point< spacedim, Number > &point) const
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:458
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:459
Point< 3 > center
#define AssertIndexRange(index, range)
Definition: exceptions.h:1760
Point< spacedim > point(const gp_Pnt &p, const double tolerance=1e-10)
Definition: utilities.cc:189
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:999
static Point< dim > unit_cell_vertex(const unsigned int vertex)