gmsh-TingyuanDoc  0.1
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
HilbertCurve.cpp
Go to the documentation of this file.
1 // Gmsh - Copyright (C) 1997-2022 C. Geuzaine, J.-F. Remacle
2 //
3 // See the LICENSE.txt file in the Gmsh root directory for license information.
4 // Please report all issues on https://gitlab.onelab.info/gmsh/gmsh/issues.
5 
6 #include "SBoundingBox3d.h"
7 #include "MVertex.h"
8 
9 struct HilbertSort {
10  // The code for generating table transgc
11  // from: http://graphics.stanford.edu/~seander/bithacks.html.
12  int transgc[8][3][8];
13  int tsb1mod3[8];
14  int maxDepth;
15  int Limit;
17  void ComputeGrayCode(int n);
18  int Split(MVertex **vertices, int arraysize, int GrayCode0, int GrayCode1,
19  double BoundingBoxXmin, double BoundingBoxXmax,
20  double BoundingBoxYmin, double BoundingBoxYmax,
21  double BoundingBoxZmin, double BoundingBoxZmax);
22  void Sort(MVertex **vertices, int arraysize, int e, int d,
23  double BoundingBoxXmin, double BoundingBoxXmax,
24  double BoundingBoxYmin, double BoundingBoxYmax,
25  double BoundingBoxZmin, double BoundingBoxZmax, int depth);
26  HilbertSort(int m = 0, int l = 2) : maxDepth(m), Limit(l)
27  {
28  ComputeGrayCode(3);
29  }
30  void MultiscaleSortHilbert(MVertex **vertices, int arraysize, int threshold,
31  double ratio, int *depth)
32  {
33  int middle;
34 
35  middle = 0;
36  if(arraysize >= threshold) {
37  (*depth)++;
38  middle = (int)(arraysize * ratio);
39  MultiscaleSortHilbert(vertices, middle, threshold, ratio, depth);
40  }
41  Sort(&(vertices[middle]), arraysize - middle, 0, 0, bbox.min().x(),
42  bbox.max().x(), bbox.min().y(), bbox.max().y(), bbox.min().z(),
43  bbox.max().z(), 0);
44  }
45  void Apply(std::vector<MVertex *> &v)
46  {
47  for(size_t i = 0; i < v.size(); i++) {
48  MVertex *pv = v[i];
49  bbox += SPoint3(pv->x(), pv->y(), pv->z());
50  }
51  bbox *= 1.01;
52  MVertex **pv = &v[0];
53  int depth = 0;
54  MultiscaleSortHilbert(pv, (int)v.size(), 10, 0.125, &depth);
55  }
56 };
57 
59 {
60  int gc[8], N, mask, travel_bit;
61  int e, d, f, k, g;
62  int v, c;
63  int i;
64 
65  N = (n == 2) ? 4 : 8;
66  mask = (n == 2) ? 3 : 7;
67 
68  // Generate the Gray code sequence.
69  for(i = 0; i < N; i++) { gc[i] = i ^ (i >> 1); }
70 
71  for(e = 0; e < N; e++) {
72  for(d = 0; d < n; d++) {
73  // Calculate the end point (f).
74  f = e ^ (1 << d); // Toggle the d-th bit of 'e'.
75  // travel_bit = 2**p, the bit we want to travel.
76  travel_bit = e ^ f;
77  for(i = 0; i < N; i++) {
78  // // Rotate gc[i] left by (p + 1) % n bits.
79  k = gc[i] * (travel_bit * 2);
80  g = ((k | (k / N)) & mask);
81  // Calculate the permuted Gray code by xor with the start point (e).
82  transgc[e][d][i] = (g ^ e);
83  }
84  // assert(transgc[e][d][0] == e);
85  // assert(transgc[e][d][N - 1] == f);
86  } // d
87  } // e
88 
89  // Count the consecutive '1' bits (trailing) on the right.
90  tsb1mod3[0] = 0;
91  for(i = 1; i < N; i++) {
92  v = ~i; // Count the 0s.
93  v = (v ^ (v - 1)) >> 1; // Set v's trailing 0s to 1s and zero rest
94  for(c = 0; v; c++) { v >>= 1; }
95  tsb1mod3[i] = c % n;
96  }
97 }
98 
99 int HilbertSort::Split(MVertex **vertices, int arraysize, int GrayCode0,
100  int GrayCode1, double BoundingBoxXmin,
101  double BoundingBoxXmax, double BoundingBoxYmin,
102  double BoundingBoxYmax, double BoundingBoxZmin,
103  double BoundingBoxZmax)
104 {
105  MVertex *swapvert;
106  int axis, d;
107  double split;
108  int i, j;
109 
110  // Find the current splitting axis. 'axis' is a value 0, or 1, or 2, which
111  // correspoding to x-, or y- or z-axis.
112  axis = (GrayCode0 ^ GrayCode1) >> 1;
113 
114  // Calulate the split position along the axis.
115  if(axis == 0) { split = 0.5 * (BoundingBoxXmin + BoundingBoxXmax); }
116  else if(axis == 1) {
117  split = 0.5 * (BoundingBoxYmin + BoundingBoxYmax);
118  }
119  else { // == 2
120  split = 0.5 * (BoundingBoxZmin + BoundingBoxZmax);
121  }
122 
123  // Find the direction (+1 or -1) of the axis. If 'd' is +1, the direction
124  // of the axis is to the positive of the axis, otherwise, it is -1.
125  d = ((GrayCode0 & (1 << axis)) == 0) ? 1 : -1;
126 
127  // Partition the vertices into left- and right-arrays such that left points
128  // have Hilbert indices lower than the right points.
129  i = 0;
130  j = arraysize - 1;
131 
132  // Partition the vertices into left- and right-arrays.
133  if(d > 0) {
134  do {
135  for(; i < arraysize; i++) {
136  if(vertices[i]->point()[axis] >= split) break;
137  }
138  for(; j >= 0; j--) {
139  if(vertices[j]->point()[axis] < split) break;
140  }
141  // Is the partition finished?
142  if(i >= (j + 1)) break;
143  // Swap i-th and j-th vertices.
144  swapvert = vertices[i];
145  vertices[i] = vertices[j];
146  vertices[j] = swapvert;
147  // Continue patitioning the array;
148  } while(true);
149  }
150  else {
151  do {
152  for(; i < arraysize; i++) {
153  if(vertices[i]->point()[axis] <= split) break;
154  }
155  for(; j >= 0; j--) {
156  if(vertices[j]->point()[axis] > split) break;
157  }
158  // Is the partition finished?
159  if(i >= (j + 1)) break;
160  // Swap i-th and j-th vertices.
161  swapvert = vertices[i];
162  vertices[i] = vertices[j];
163  vertices[j] = swapvert;
164  // Continue patitioning the array;
165  } while(true);
166  }
167 
168  return i;
169 }
170 
171 // The sorting code is inspired by Tetgen 1.5
172 
173 void HilbertSort::Sort(MVertex **vertices, int arraysize, int e, int d,
174  double BoundingBoxXmin, double BoundingBoxXmax,
175  double BoundingBoxYmin, double BoundingBoxYmax,
176  double BoundingBoxZmin, double BoundingBoxZmax,
177  int depth)
178 {
179  double x1, x2, y1, y2, z1, z2;
180  int p[9], w, e_w, d_w, k, ei, di;
181  int n = 3, mask = 7;
182 
183  p[0] = 0;
184  p[8] = arraysize;
185 
186  p[4] = Split(vertices, p[8], transgc[e][d][3], transgc[e][d][4],
187  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin,
188  BoundingBoxYmax, BoundingBoxZmin, BoundingBoxZmax);
189  p[2] = Split(vertices, p[4], transgc[e][d][1], transgc[e][d][2],
190  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin,
191  BoundingBoxYmax, BoundingBoxZmin, BoundingBoxZmax);
192  p[1] = Split(vertices, p[2], transgc[e][d][0], transgc[e][d][1],
193  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin,
194  BoundingBoxYmax, BoundingBoxZmin, BoundingBoxZmax);
195  p[3] =
196  Split(&(vertices[p[2]]), p[4] - p[2], transgc[e][d][2], transgc[e][d][3],
197  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
198  BoundingBoxZmin, BoundingBoxZmax) +
199  p[2];
200  p[6] =
201  Split(&(vertices[p[4]]), p[8] - p[4], transgc[e][d][5], transgc[e][d][6],
202  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
203  BoundingBoxZmin, BoundingBoxZmax) +
204  p[4];
205  p[5] =
206  Split(&(vertices[p[4]]), p[6] - p[4], transgc[e][d][4], transgc[e][d][5],
207  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
208  BoundingBoxZmin, BoundingBoxZmax) +
209  p[4];
210  p[7] =
211  Split(&(vertices[p[6]]), p[8] - p[6], transgc[e][d][6], transgc[e][d][7],
212  BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
213  BoundingBoxZmin, BoundingBoxZmax) +
214  p[6];
215 
216  if(maxDepth > 0) {
217  if((depth + 1) == maxDepth) { return; }
218  }
219 
220  // Recursively sort the points in sub-boxes.
221  for(w = 0; w < 8; w++) {
222  if((p[w + 1] - p[w]) > Limit) {
223  if(w == 0) { e_w = 0; }
224  else {
225  k = 2 * ((w - 1) / 2);
226  e_w = k ^ (k >> 1);
227  }
228  k = e_w;
229  e_w = ((k << (d + 1)) & mask) | ((k >> (n - d - 1)) & mask);
230  ei = e ^ e_w;
231  if(w == 0) { d_w = 0; }
232  else {
233  d_w = ((w % 2) == 0) ? tsb1mod3[w - 1] : tsb1mod3[w];
234  }
235  di = (d + d_w + 1) % n;
236  if(transgc[e][d][w] & 1) {
237  x1 = 0.5 * (BoundingBoxXmin + BoundingBoxXmax);
238  x2 = BoundingBoxXmax;
239  }
240  else {
241  x1 = BoundingBoxXmin;
242  x2 = 0.5 * (BoundingBoxXmin + BoundingBoxXmax);
243  }
244  if(transgc[e][d][w] & 2) { // y-axis
245  y1 = 0.5 * (BoundingBoxYmin + BoundingBoxYmax);
246  y2 = BoundingBoxYmax;
247  }
248  else {
249  y1 = BoundingBoxYmin;
250  y2 = 0.5 * (BoundingBoxYmin + BoundingBoxYmax);
251  }
252  if(transgc[e][d][w] & 4) { // z-axis
253  z1 = 0.5 * (BoundingBoxZmin + BoundingBoxZmax);
254  z2 = BoundingBoxZmax;
255  }
256  else {
257  z1 = BoundingBoxZmin;
258  z2 = 0.5 * (BoundingBoxZmin + BoundingBoxZmax);
259  }
260  Sort(&(vertices[p[w]]), p[w + 1] - p[w], ei, di, x1, x2, y1, y2, z1, z2,
261  depth + 1);
262  }
263  }
264 }
265 
266 void SortHilbert(std::vector<MVertex *> &v)
267 {
268  HilbertSort h(1000);
269  // HilbertSort h;
270  h.Apply(v);
271 }
HilbertSort::bbox
SBoundingBox3d bbox
Definition: HilbertCurve.cpp:16
c
static double c(int i, int j, fullMatrix< double > &CA, const std::vector< SPoint3 > &P, const std::vector< SPoint3 > &Q)
Definition: discreteFrechetDistance.cpp:15
MVertex
Definition: MVertex.h:24
MVertex::z
double z() const
Definition: MVertex.h:62
SPoint3
Definition: SPoint3.h:14
LegendrePolynomials::f
void f(int n, double u, double *val)
Definition: orthogonalBasis.cpp:77
SBoundingBox3d::min
SPoint3 min() const
Definition: SBoundingBox3d.h:90
HilbertSort::transgc
int transgc[8][3][8]
Definition: HilbertCurve.cpp:12
HilbertSort::Sort
void Sort(MVertex **vertices, int arraysize, int e, int d, double BoundingBoxXmin, double BoundingBoxXmax, double BoundingBoxYmin, double BoundingBoxYmax, double BoundingBoxZmin, double BoundingBoxZmax, int depth)
Definition: HilbertCurve.cpp:173
SPoint3::x
double x(void) const
Definition: SPoint3.h:125
HilbertSort::ComputeGrayCode
void ComputeGrayCode(int n)
Definition: HilbertCurve.cpp:58
SBoundingBox3d.h
MVertex.h
SPoint3::y
double y(void) const
Definition: SPoint3.h:127
HilbertSort::Apply
void Apply(std::vector< MVertex * > &v)
Definition: HilbertCurve.cpp:45
HilbertSort::HilbertSort
HilbertSort(int m=0, int l=2)
Definition: HilbertCurve.cpp:26
HilbertSort::Split
int Split(MVertex **vertices, int arraysize, int GrayCode0, int GrayCode1, double BoundingBoxXmin, double BoundingBoxXmax, double BoundingBoxYmin, double BoundingBoxYmax, double BoundingBoxZmin, double BoundingBoxZmax)
Definition: HilbertCurve.cpp:99
HilbertSort::Limit
int Limit
Definition: HilbertCurve.cpp:15
HilbertSort
Definition: HilbertCurve.cpp:9
SPoint3::z
double z(void) const
Definition: SPoint3.h:129
SortHilbert
void SortHilbert(std::vector< MVertex * > &v)
Definition: HilbertCurve.cpp:266
MVertex::y
double y() const
Definition: MVertex.h:61
SBoundingBox3d::max
SPoint3 max() const
Definition: SBoundingBox3d.h:91
SBoundingBox3d
Definition: SBoundingBox3d.h:21
HilbertSort::maxDepth
int maxDepth
Definition: HilbertCurve.cpp:14
HilbertSort::tsb1mod3
int tsb1mod3[8]
Definition: HilbertCurve.cpp:13
HilbertSort::MultiscaleSortHilbert
void MultiscaleSortHilbert(MVertex **vertices, int arraysize, int threshold, double ratio, int *depth)
Definition: HilbertCurve.cpp:30
MVertex::x
double x() const
Definition: MVertex.h:60