HilbertOrder.cpp
1 #include "HilbertOrder.hpp"
2 
3 namespace
4 {
5  class AllLocalData
6  {
7  public:
8 
9  AllLocalData(vector<int> *vin,int iN,int inn,int ipow2):
10  IndexTable(vin), N(iN), n(inn), pow2(ipow2) {}
11 
12  AllLocalData(const AllLocalData &other):
13  IndexTable(other.IndexTable),
14  N(other.N),
15  n(other.n),
16  pow2(other.pow2) {}
17 
18  vector<int> *IndexTable;
19  int N;
20  int n;
21  int pow2;
22 
23  private:
24  AllLocalData& operator=(const AllLocalData& other);
25  };
26 
27  class Context
28  {
29  public:
30  Context (vector<int>* par,AllLocalData const& local_data,int i):
31  _params(par), _data(local_data), _i(i) {}
32 
33  vector<int>* _params;
34  AllLocalData _data;
35  int _i;
36  };
37 
38  bool point_compare_x(Vector2D const& p1,Vector2D const& p2)
39  {
40  return p1.x<p2.x;
41  }
42 
43  bool point_compare_y(Vector2D const& p1,Vector2D const& p2)
44  {
45  return p1.y<p2.y;
46  }
47 
48  pair<int,int> rot(int n, pair<int,int> const& origin, pair<int,int> const& r)
49  {
50  pair<int,int> res = origin;
51  if(r.second==0){
52  if(r.first==1)
53  res = pair<int,int>(n-1-res.first,n-1-res.second);
54  return pair<int,int>(res.second,res.first);
55  }
56  else
57  return res;
58  }
59 
60  //convert (x,y) to d
61  int xy2d (int n, int x, int y) {
62  int d=0;
63  pair<int,int> temp(x,y);
64  for (int s=n/2; s>0; s/=2) {
65  const pair<int,int> r((x&s)>0,(y&s)>0);
66  d += s * s * ((3 * r.first) ^ r.second);
67  temp = rot(s, temp, r);
68  }
69  return d;
70  }
71 }
72 
73 namespace {
74  vector<int> range(int n)
75  {
76  vector<int> res(static_cast<size_t>(n));
77  for(size_t i=0;i<res.size();++i)
78  res[i] = static_cast<int>(i);
79  return res;
80  }
81 
82  template<class T> void zero_pad_start(vector<T>& v,int n)
83  {
84  const vector<int> temp(static_cast<size_t>(n));
85  v.insert(v.begin(),temp.begin(),temp.end());
86  }
87 
88  int calc_d(pair<double, double> const& dxdy,
89  pair<double, double> const& xminymin,
90  Vector2D const& cor,
91  int pow2)
92  {
93  if(dxdy.first<=0&&dxdy.second<=0)
94  return 0;
95 
96  const pair<int, int> index
97  (dxdy.first <=0 ? 0 : static_cast<int>((cor.x-xminymin.first)/dxdy.first),
98  dxdy.second <=0 ? 0 : static_cast<int>((cor.y-xminymin.second)/dxdy.second));
99  return xy2d(pow2,index.first,index.second);
100  }
101 }
102 
103 vector<int> HilbertOrder(vector<Vector2D> const& cor,int num,int innernum)
104 {
105  if(cor.empty())
106  return vector<int> ();
107  const int N=num-innernum;
108  vector<int> insert_order;
109 
110  insert_order.reserve(static_cast<size_t>(N));
111  stack<Context*> context_list;
112  stack<vector<int>*> IndexTableStack;
113  const int temp_n=max(static_cast<int>(sqrt(static_cast<double>(N))),2);
114  const int temp_pow2=max(static_cast<int>(pow(2.0,static_cast<int>(log(1.0*temp_n)/log(2.0)))),2);
115  AllLocalData d_local_data(0,N,temp_n,temp_pow2);
116  vector<int> p = range(N);
117  vector<int>* param = &p;
118  Context *context=new Context(param,d_local_data,0);
119  context_list.push(context);
120  bool expand;
121  const vector<Vector2D> cortemp(cor.begin()+innernum,
122  cor.begin()+num);
123  while(!context_list.empty())
124  {
125  context=context_list.top();
126  AllLocalData local_data=context->_data;
127  param=context->_params;
128  int i=context->_i;
129  context_list.pop();
130  delete context;
131  if(static_cast<int>(context_list.size())>N)
132  {
133  UniversalError eo("Error in creating the hilbert order, probably two points are identical");
134  throw eo;
135  }
136  if(i==0)
137  {
138  vector<Vector2D> p_cor(static_cast<size_t>(local_data.N));
139  for(size_t j=0;j<static_cast<size_t>(local_data.N);++j)
140  p_cor[j] = cortemp[static_cast<size_t>(param->at(j))];
141  const double xmin=(*min_element(p_cor.begin(),
142  p_cor.end(),
143  point_compare_x)).x;
144  const double xmax=(*max_element(p_cor.begin(),
145  p_cor.end(),
146  point_compare_x)).x;
147  const double ymin=(*min_element(p_cor.begin(),
148  p_cor.end(),
149  point_compare_y)).y;
150  const double ymax=(*max_element(p_cor.begin(),
151  p_cor.end(),
152  point_compare_y)).y;
153  const double dx=static_cast<double>(xmax-xmin)/(local_data.pow2-1);
154  const double dy=static_cast<double>(ymax-ymin)/(local_data.pow2-1);
155  local_data.IndexTable=new vector<int>[local_data.pow2*local_data.pow2];
156  for(int j=0;j<local_data.N;j++){
157  const int d = calc_d
158  (pair<double,double>(dx,dy),
159  pair<double,double>(xmin,ymin),
160  p_cor[static_cast<size_t>(j)],local_data.pow2);
161  local_data.IndexTable[d].push_back(param->at(static_cast<size_t>(j)));
162  }
163  }
164  if(i<(local_data.pow2*local_data.pow2-1))
165  {
166  context = new Context(param, local_data,i+1); // i+1 is the for loop increment
167  context_list.push(context);
168  }
169  if(local_data.IndexTable[i].size()<2)
170  {
171  expand=false;
172  for(size_t k=0;k<local_data.IndexTable[i].size();k++)
173  insert_order.push_back(local_data.IndexTable[i][k]);
174  }
175  else
176  {
177  expand=true;
178  int temp_n2=max(static_cast<int>(sqrt(double(local_data.IndexTable[i].size()))),2);
179  context=new Context
180  (&local_data.IndexTable[i],
181  AllLocalData
182  (0,
183  static_cast<int>(local_data.IndexTable[i].size()),
184  temp_n2,
185  max(static_cast<int>(pow(2.0,static_cast<int>(log(1.0*temp_n2)/log(2.0)))),2)), 0);
186  context_list.push(context);
187  }
188  if(i==(local_data.pow2*local_data.pow2-1))
189  {
190  for(size_t l=0;l<IndexTableStack.size();++l)
191  {
192  delete [] IndexTableStack.top();
193  IndexTableStack.pop();
194  }
195  if(!expand)
196  delete [] local_data.IndexTable;
197  else
198  IndexTableStack.push(local_data.IndexTable);
199  }
200  }
201  if(innernum>0)
202  {
203  zero_pad_start(insert_order,innernum);
204  for(int i=0;i<num;++i)
205  {
206  if(i<innernum)
207  insert_order[static_cast<size_t>(i)]=i;
208  else
209  insert_order[static_cast<size_t>(i)]+=innernum;
210  }
211  }
212  return insert_order;
213 }
Container for error reports.
Hilbert space filling curve.
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
vector< int > HilbertOrder(vector< Vector2D > const &cor, int num, int innernum=0)
Returns the Hilber curve ordering.
2D Mathematical vector
Definition: geometry.hpp:15
double x
Component in the x direction.
Definition: geometry.hpp:45