HilbertOrder3D_Utils.cpp
1 #include <cmath>
3 
4 int EstimateHilbertIterationNum(vector<Vector3D> const& cor)
5 {
6  return static_cast<int>(ceil(log(pow(static_cast<double>(cor.size()), (1.0 / 3.0))) / log(2.0)));
7 }
8 
9 namespace {
10  bool approx_equal(double a, double b, double thres=1e-9)
11  {
12  return thres>std::abs(a-b);
13  }
14 }
15 
16 
17 // Adjust the vector of points so all coordinate values will be in the range [0,1]
18 void AdjustPoints(vector<Vector3D> const & vPointsIn, vector<Vector3D> & vPointsOut)
19 {
20  // The output vector:
21  vPointsOut.resize(vPointsIn.size());
22  // Vectors holding the X,Y,Z coordinates:
23  vector<double> vPointsX, vPointsY, vPointsZ;
24 
25  Split(vPointsIn, vPointsX, vPointsY, vPointsZ);
26 
27  // TOOD - what if all points have the same x (or y, or z) values?
28 
29  double dbMinX = *min_element(vPointsX.begin(), vPointsX.end());
30  double dbMinY = *min_element(vPointsY.begin(), vPointsY.end());
31  double dbMinZ = *min_element(vPointsZ.begin(), vPointsZ.end());
32 
33  double dbMaxX = *max_element(vPointsX.begin(), vPointsX.end());
34  double dbMaxY = *max_element(vPointsY.begin(), vPointsY.end());
35  double dbMaxZ = *max_element(vPointsZ.begin(), vPointsZ.end());
36  // The scale factor:
37  double dbScaleX = dbMaxX - dbMinX;
38  double dbScaleY = dbMaxY - dbMinY;
39  double dbScaleZ = dbMaxZ - dbMinZ;
40  // To prevent division by zero (very unlikely - double precision!)
41  bool bFlagX = approx_equal(dbScaleX,0); // dbScaleX == 0;
42  bool bFlagY = approx_equal(dbScaleY,0); // dbScaleY == 0;
43  bool bFlagZ = approx_equal(dbScaleZ,0); // dbScaleZ == 0;
44 
45  // X coordinate:
46  if (!bFlagX)
47  {
48  for (size_t ii = 0; ii < vPointsIn.size(); ++ii)
49  {
50  // Scale the X coordinate:
51  vPointsX[ii] -= dbMinX;
52  vPointsX[ii] /= dbScaleX;
53  }
54  }
55  else
56  {
57  fill(vPointsX.begin(), vPointsX.end(), 0);
58  }
59  // Y coordinate:
60  if (!bFlagY)
61  {
62  for (size_t ii = 0; ii < vPointsIn.size(); ++ii)
63  {
64  // Scale the X coordinate:
65  vPointsY[ii] -= dbMinY;
66  vPointsY[ii] /= dbScaleY;
67  }
68  }
69  else
70  {
71  fill(vPointsY.begin(), vPointsY.end(), 0);
72  }
73  // Z coordinate:
74  if (!bFlagZ)
75  {
76  for (size_t ii = 0; ii < vPointsIn.size(); ++ii)
77  {
78  vPointsZ[ii] -= dbMinZ;
79  vPointsZ[ii] /= dbScaleZ;
80  }
81  }
82  else
83  {
84  fill(vPointsZ.begin(), vPointsZ.end(), 0);
85  }
86 
87  // Store back the coordiantes in a single output vector:
88  for (size_t ii = 0; ii < vPointsIn.size(); ++ii)
89  {
90  vPointsOut[ii].x = vPointsX[ii];
91  vPointsOut[ii].y = vPointsY[ii];
92  vPointsOut[ii].z = vPointsZ[ii];
93  }
94 
95  return;
96 }
97 
98 void FindEqualIndices(vector<size_t> const & vD_sorted, vector<vector<size_t> > & vOut)
99 {
100  vector<size_t> vD_sorted_cpy = vD_sorted;
101  vector<size_t> vD_sorted_unq = vD_sorted;
102 
103  vector<size_t>::iterator it1, itPrev, itCur;
104  it1 = unique(vD_sorted_unq.begin(), vD_sorted_unq.end());
105 
106  vD_sorted_unq.resize(static_cast<size_t>(distance(vD_sorted_unq.begin(), it1)));
107 
108  if (vD_sorted.size() == vD_sorted_unq.size())
109  {
110  return;
111  }
112 
113  vOut.reserve(vD_sorted.size() - vD_sorted_unq.size());
114 
115  int iCurPrevDist = 0;
116 
117  itPrev = vD_sorted_cpy.begin();
118  for (it1 = vD_sorted_unq.begin()+1; it1 != vD_sorted_unq.end(); ++it1)
119  {
120  if (distance( it1 , vD_sorted_unq.end() ) == 0)
121  {
122  itCur = vD_sorted_cpy.end();
123  }
124  else
125  {
126  itCur = find(itPrev, vD_sorted_cpy.end(), *it1);
127  }
128 
129  iCurPrevDist = static_cast<int>(distance(itPrev, itCur));
130  if (1 < iCurPrevDist)
131  {
132  int iBase = static_cast<int>(distance(vD_sorted_cpy.begin(), itPrev));
133  vector<size_t> vInd(static_cast<size_t>(iCurPrevDist));
134  // C++11
135  // iota(vInd.begin(), vInd.end(), iBase);
136  for (int ii = 0; ii < iCurPrevDist; ++ii)
137  {
138  vInd[static_cast<size_t>(ii)] = static_cast<size_t>(iBase + ii);
139  }
140  vOut.push_back(vInd);
141  }
142 
143  itPrev = itCur;
144  }
145 
146  iCurPrevDist = static_cast<int>(distance(itPrev, vD_sorted_cpy.end()));
147  if (1 < iCurPrevDist )
148  {
149  int iBase = static_cast<int>(distance(vD_sorted_cpy.begin(), itPrev));
150 
151  vector<size_t> vInd(static_cast<size_t>(iCurPrevDist));
152  for (int ii = 0; ii < iCurPrevDist; ++ii)
153  {
154  vInd[static_cast<size_t>(ii)] = static_cast<size_t>(iBase + ii);
155  }
156  vOut.push_back(vInd);
157  }
158 
159  // int x = 0;
160 
161  return;
162 }
vector< T > unique(vector< T > const &v)
Returns a vector containing only unique elements.
Definition: utils.hpp:376
void FindEqualIndices(vector< size_t > const &vD_sorted, vector< vector< size_t > > &vOut)
Scale a vector of 3D points to the unit-cube.
void AdjustPoints(vector< Vector3D > const &vPointsIn, vector< Vector3D > &vPointsOut)
Scale a vector of 3D points to the unit-cube.
Hilbert 3D Order - Utility functions.
void Split(vector< Vector3D > const &vIn, vector< double > &vX, vector< double > &vY, vector< double > &vZ)
Splits a vector of 3D points to components.
Definition: Vector3D.cpp:222
double abs(Vector3D const &v)
Norm of a vector.
Definition: Vector3D.cpp:44
int EstimateHilbertIterationNum(vector< Vector3D > const &cor)
Estimate the number of iterations required in the Hilbert Curve, according to the number of points...
double distance(Vector3D const &v1, Vector3D const &v2)
Calculates the distance between two vectors.
Definition: Vector3D.cpp:208