find_affected_cells.cpp
2 #include "geometry.hpp"
3 #include "boost/foreach.hpp"
4 #include "../misc/utils.hpp"
5 #include <cmath>
6 
7 namespace
8 {
9  bool periodic_duplicate_before(std::vector<Vector2D> const& toadd, Vector2D const& tocheck,Vector2D const& ll,Vector2D const& ur)
10  {
11  size_t N = toadd.size();
12  if (N == 0)
13  return false;
14  if (tocheck.x > ur.x || tocheck.x<ll.x || tocheck.y>ur.y || tocheck.y < ll.y)
15  return true;
16  double dx = 1e-20;
17  for (size_t i = 0; i < N; ++i)
18  dx = std::max(dx, fastabs(toadd[i]));
19  for (size_t i = 0; i < N; ++i)
20  {
21  double dV = fastabs(toadd[i] - tocheck);
22  if (dV < dx*1e-6)
23  {
24  return true;
25  }
26  }
27  return false;
28  }
29 
30  bool contains(const vector<int>& v, const int n)
31  {
32  for (size_t i = 0; i < v.size(); ++i)
33  {
34  if (n == v[i])
35  return true;
36  }
37  return false;
38  }
39 
40  bool contains(const vector<int>& v, const std::vector<Vector2D> & added,Vector2D const& toadd, const int n,
41  Vector2D const&ll, Vector2D const& ur)
42  {
43  if (fabs(toadd.x) > (1.01*(ur.x - ll.x)) || fabs(toadd.y) > (1.01*(ur.y - ll.y)))
44  return true;
45  for (size_t i = 0; i < v.size(); ++i)
46  {
47  if (n == v[i])
48  {
49  if(fastabs(added[i]-toadd)<1e-6*std::max(1e-20,std::max(fastabs(toadd),fastabs(added[i]))))
50  return true;
51  }
52  }
53  return false;
54  }
55 
56  /*double bracket(double low, double num, double high)
57  {
58  return std::max(std::min(num, high), low);
59  }*/
60 }
61 
63 (const Edge& edge,
64  const Circle& circle)
65 {
66  Vector2D norm = normalize(edge.vertices.second - edge.vertices.first);
67  Vector2D tocenter = circle.getCenter() - edge.vertices.first;
68  Vector2D perpindicular = tocenter - ScalarProd(norm, tocenter) * norm;
69  return ScalarProd(perpindicular, perpindicular) < circle.getRadius() * circle.getRadius();
70 }
71 
72 namespace {
73  bool cell_circle_intersect(const Tessellation& tess,
74  int index,
75  const Circle& circle)
76  {
77  BOOST_FOREACH(int ei, tess.GetCellEdges(index))
78  {
79  if (edge_circle_intersect(tess.GetEdge(ei), circle))
80  return true;
81  }
82  return false;
83  }
84 
85  void find_affected_cells2(const Tessellation& tess, int index, Circle circle,
86  vector<int> &res, vector<int>& visited, std::vector<Vector2D> &added, bool periodic, Vector2D const& toaddsingle,
87  std::vector<Vector2D>& visited_add,Vector2D const& ll,Vector2D const& ur)
88  {
89  if (periodic)
90  {
91  if (contains(visited, visited_add, toaddsingle, index,ll,ur))
92  return;
93  }
94  else
95  if (contains(visited, index))
96  return;
97  visited.push_back(index);
98  visited_add.push_back(toaddsingle);
99  if (!cell_circle_intersect(tess, tess.GetOriginalIndex(index), circle))
100  return;
101  else
102  {
103  res.push_back(index);
104  if (periodic)
105  added.push_back(toaddsingle);
106  vector<int> vtemp = tess.GetNeighbors(index);
107  size_t NN = vtemp.size();
108  Vector2D llperiodic = 2.1 * ll - 1.1*ur;
109  Vector2D urperiodic = 2.1 * ur - 1.1*ll;
110  for (size_t j = 0; j < NN; ++j)
111  {
112  if (vtemp[j] < tess.GetPointNo())
113  find_affected_cells2(tess, vtemp[j], circle, res, visited, added, periodic, toaddsingle,visited_add,ll,ur);
114  else
115  if (periodic)
116  {
117  Vector2D toadd = tess.GetMeshPoint(tess.GetOriginalIndex(vtemp[j])) -
118  tess.GetMeshPoint(vtemp[j]);
119  // Make sure not heading back in duplicate space
120  if (!periodic_duplicate_before(added, toadd,llperiodic,urperiodic))
121  {
122  Vector2D oldcenter = circle.getCenter();
123  circle.setCenter(toadd + oldcenter);
124  toadd += toaddsingle;
125  find_affected_cells2(tess, tess.GetOriginalIndex(vtemp[j]), circle, res, visited, added, periodic,
126  toadd,visited_add,ll,ur);
127  circle.setCenter(oldcenter);
128  }
129  }
130  }
131  return;
132  }
133  }
134 }
135 
136 vector<int> find_affected_cells(const Tessellation& tess, int index, Circle& circle, vector<int> &vtemp, bool periodic,
137  std::vector<Vector2D> &periodic_add)
138 {
139  periodic_add.clear();
140  vector<int> res;
141  vtemp = tess.GetNeighbors(index);
142  size_t N = vtemp.size();
143  for (size_t i = 0; i < N; ++i)
144  {
145 
146  if (vtemp[i] < tess.GetPointNo())
147  {
148  if (cell_circle_intersect(tess, vtemp[i], circle))
149  {
150  res.push_back(vtemp[i]);
151  if (periodic)
152  periodic_add.push_back(Vector2D());
153  }
154  }
155  else
156  {
157  if (periodic)
158  {
159  int real_neigh = tess.GetOriginalIndex(vtemp[i]);
160  Vector2D toadd = tess.GetMeshPoint(real_neigh) - tess.GetMeshPoint(vtemp[i]) ;
161  circle.setCenter(circle.getCenter() + toadd);
162  if (cell_circle_intersect(tess, real_neigh, circle))
163  {
164  res.push_back(real_neigh);
165  periodic_add.push_back(toadd);
166  }
167  circle.setCenter(circle.getCenter() - toadd);
168  }
169  }
170  }
171  return res;
172 }
173 
174 void find_affected_cells_recursive(const Tessellation& tess, int index, const Circle& circle,
175  vector<int> &res, std::vector<Vector2D> &added, bool periodic,Vector2D const& ll,Vector2D const& ur)
176 {
177  vector<int> visited;
178  std::vector<Vector2D> visited_add;
179  added.clear();
180  Vector2D toaddsingle;
181  find_affected_cells2(tess, index, circle, res, visited, added, periodic, toaddsingle, visited_add,ll,ur);
182 }
Geometrical calculations.
Abstract class for tessellation.
virtual int GetPointNo(void) const =0
Get Total number of mesh generating points.
virtual int GetOriginalIndex(int point) const
Returns the original index of the duplicated point.
Definition: tessellation.cpp:5
void setCenter(Vector2D const &center)
Sets a new center to the circle.
Definition: shape_2d.cpp:21
Interface between two cells.
Definition: Edge.hpp:13
virtual Vector2D GetMeshPoint(int index) const =0
Returns Position of mesh generating point.
double max(vector< double > const &v)
returns the maximal term in a vector
Definition: utils.cpp:52
double y
Component in the y direction.
Definition: geometry.hpp:48
virtual Edge const & GetEdge(int index) const =0
Returns edge (interface between cells)
double ScalarProd(Vector3D const &v1, Vector3D const &v2)
Scalar product of two vectors.
Definition: Vector3D.cpp:185
A circle.
Definition: shape_2d.hpp:27
std::pair< Vector2D, Vector2D > vertices
Points at the ends of the edge.
Definition: Edge.hpp:18
vector< int > find_affected_cells(const Tessellation &tess, int index, Circle &circle, vector< int > &vtemp, bool periodic, std::vector< Vector2D > &periodic_add)
Non recursive version of find affected cells. Only searches one degree of separation.
Vector2D normalize(const Vector2D &v)
Normalized a vector.
Definition: geometry.cpp:158
double getRadius(void) const
Returns the radius of the circle.
Definition: shape_2d.cpp:16
void find_affected_cells_recursive(const Tessellation &tess, int index, const Circle &circle, vector< int > &res, std::vector< Vector2D > &added, bool periodic, Vector2D const &ll, Vector2D const &ur)
Recursively finds all cells that intersect a circle.
bool edge_circle_intersect(const Edge &edge, const Circle &circle)
Determines if an edge and a circle intersect.
virtual vector< int > const & GetCellEdges(int index) const =0
Returns the indexes of a cell&#39;s edges.
Determines which cells might be affected by boundary conditions.
2D Mathematical vector
Definition: geometry.hpp:15
virtual vector< int > GetNeighbors(int index) const =0
Returns the indeces of the neighbors.
double fastabs(Vector2D const &v)
Norm of a vector, less accurate.
Definition: geometry.cpp:24
double x
Component in the x direction.
Definition: geometry.hpp:45
const Vector2D & getCenter(void) const
Returns the center of the circle.
Definition: shape_2d.cpp:11