Reference documentation for deal.II version 9.0.0
bounding_box.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2017 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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 #include <deal.II/base/bounding_box.h>
16 
17 DEAL_II_NAMESPACE_OPEN
18 
19 template <int spacedim, typename Number>
21 {
22  for (unsigned int i=0; i < spacedim; ++i)
23  {
24  //Bottom left-top right convention: the point is outside if it's smaller than the
25  //first or bigger than the second boundary point
26  //The bounding box is defined as a closed set
27  if ( std::numeric_limits<Number>::epsilon()*(std::abs( this->boundary_points.first[i] + p[i]) )
28  < this->boundary_points.first[i] - p[i]
29  || std::numeric_limits<Number>::epsilon()*(std::abs( this->boundary_points.second[i] + p[i]) ) <
30  p[i] - this->boundary_points.second[i] )
31  return false;
32  }
33  return true;
34 }
35 
36 template <int spacedim, typename Number>
38 {
39  for (unsigned int i=0; i < spacedim; ++i)
40  {
41  this->boundary_points.first[i] = std::min( this->boundary_points.first[i], other_bbox.boundary_points.first[i] );
42  this->boundary_points.second[i] = std::max( this->boundary_points.second[i], other_bbox.boundary_points.second[i] );
43  }
44 }
45 
46 template <int spacedim, typename Number>
48 {
49  if (spacedim == 1)
50  {
51  // In dimension 1 if the two bounding box are neighbors
52  // we can merge them
53  if ( this->point_inside(other_bbox.boundary_points.first)
54  || this->point_inside(other_bbox.boundary_points.second) )
55  return NeighborType::mergeable_neighbors;
56  return NeighborType::not_neighbors;
57  }
58  else
59  {
60  std::vector< Point<spacedim,Number> > bbox1;
61  bbox1.push_back(this->get_boundary_points().first);
62  bbox1.push_back(this->get_boundary_points().second);
63  std::vector< Point<spacedim,Number> > bbox2;
64  bbox2.push_back(other_bbox.get_boundary_points().first);
65  bbox2.push_back(other_bbox.get_boundary_points().second);
66 
67  // Step 1: testing if the boxes are close enough to intersect
68  for ( unsigned int d=0 ; d<spacedim; ++d )
69  if ( bbox1[0][d] * ( 1 - std::numeric_limits<Number>::epsilon() ) > bbox2[1][d]
70  || bbox2[0][d] * (1 - std::numeric_limits<Number>::epsilon() ) > bbox1[1][d] )
71  return NeighborType::not_neighbors;
72 
73  // The boxes intersect: we need to understand now how they intersect.
74  // We begin by computing the intersection:
75  std::vector<double> intersect_bbox_min;
76  std::vector<double> intersect_bbox_max;
77  for (unsigned int d=0; d < spacedim ; ++d)
78  {
79  intersect_bbox_min.push_back(std::max(bbox1[0][d],bbox2[0][d]));
80  intersect_bbox_max.push_back(std::min(bbox1[1][d],bbox2[1][d]));
81  }
82 
83  // Finding the intersection's dimension
84 
85  unsigned int intersect_dim = spacedim;
86  for (unsigned int d=0; d < spacedim; ++d)
87  if ( std::abs( intersect_bbox_min[d] - intersect_bbox_max[d] ) <=
88  std::numeric_limits<Number>::epsilon() * (std::abs( intersect_bbox_min[d]) + std::abs(intersect_bbox_max[d] )) )
89  --intersect_dim;
90 
91  if ( intersect_dim == 0 || intersect_dim + 2 == spacedim )
92  return NeighborType::simple_neighbors;
93 
94  // Checking the two mergeable cases: first if the boxes are aligned so that they can be merged
95  unsigned int not_align_1 = 0, not_align_2 = 0;
96  bool same_direction = true;
97  for (unsigned int d = 0; d < spacedim; ++d)
98  {
99  if (std::abs(bbox2[0][d] - bbox1[0][d]) >
100  std::numeric_limits<double>::epsilon() * (std::abs( bbox2[0][d]) + std::abs(bbox1[0][d] )) )
101  ++not_align_1;
102  if (std::abs(bbox1[1][d] - bbox2[1][d]) >
103  std::numeric_limits<double>::epsilon() * (std::abs( bbox1[1][d]) + std::abs( bbox2[1][d] )) )
104  ++not_align_2;
105  if (not_align_1 != not_align_2)
106  {
107  same_direction = false;
108  break;
109  }
110  }
111 
112  if ( not_align_1 <= 1 && not_align_2 <= 1 && same_direction)
113  return NeighborType::mergeable_neighbors;
114 
115  // Second: one box is contained/equal to the other
116  if ( (this->point_inside(bbox2[0]) && this->point_inside(bbox2[1]) )
117  || (other_bbox.point_inside(bbox1[0]) && other_bbox.point_inside(bbox1[1]) ) )
118  return NeighborType::mergeable_neighbors;
119 
120  // Degenerate and mergeable cases have been found, it remains:
121  return NeighborType::attached_neighbors;
122  }
123 
124 }
125 
126 template <int spacedim, typename Number>
127 const std::pair<Point<spacedim,Number>,Point<spacedim,Number>> &BoundingBox<spacedim,Number>::get_boundary_points () const
128 {
129  return this->boundary_points;
130 }
131 
132 template <int spacedim, typename Number>
134 {
135  double vol = 1.0;
136  for (unsigned int i=0; i < spacedim; ++i)
137  vol *= ( this->boundary_points.second[i] - this->boundary_points.first[i] );
138  return vol;
139 }
140 
141 #include "bounding_box.inst"
142 DEAL_II_NAMESPACE_CLOSE
void merge_with(const BoundingBox< spacedim, Number > &other_bbox)
Definition: bounding_box.cc:37
Definition: point.h:104
bool point_inside(const Point< spacedim, Number > &p) const
Definition: bounding_box.cc:20
double volume() const
const std::pair< Point< spacedim, Number >, Point< spacedim, Number > > & get_boundary_points() const