LBKdTree.cpp
Go to the documentation of this file.
1 
28 #include <stdio.h>
29 
30 #include <iostream>
33 
34 namespace lvr2
35 {
36 
37 // Static variables
38 
42 
44 
45 LBKdTree::LBKdTree( LBPointArray<float>& vertices, int num_threads) {
46  this->m_values = boost::shared_ptr<LBPointArray<float> >(new LBPointArray<float>);
47  this->m_splits = boost::shared_ptr<LBPointArray<unsigned char> >(new LBPointArray<unsigned char>);
48  st_num_threads = num_threads;
49  st_depth_threads = static_cast<int>(log2(st_num_threads));
51  this->generateKdTree(vertices);
52 }
53 
55  if(pool)
56  {
57  delete pool;
58  }
59 }
60 
62 
63  LBPointArray<unsigned int>* indices_sorted =
64  (LBPointArray<unsigned int>*)malloc(vertices.dim * sizeof(LBPointArray<unsigned int>) );
65  LBPointArray<float>* values_sorted =
66  (LBPointArray<float>*)malloc(vertices.dim * sizeof(LBPointArray<float>) );
67 
68  for(unsigned int i=0; i< vertices.dim; i++)
69  {
70  pool->push(generateAndSort<float, unsigned int>, vertices, indices_sorted, values_sorted, i);
71  //generateAndSort<float, unsigned int>(0, vertices, indices_sorted, values_sorted, i);
72  }
73 
74  pool->stop(true);
75  delete pool;
77 
78 
79  this->generateKdTreeArray(vertices, indices_sorted, vertices.dim);
80 
81  for(unsigned int i=0; i<vertices.dim;i++)
82  {
83  free(values_sorted[i].elements);
84  }
85 }
86 
87 boost::shared_ptr<LBPointArray<float> > LBKdTree::getKdTreeValues() {
88  return this->m_values;
89 }
90 
91 boost::shared_ptr<LBPointArray<unsigned char> > LBKdTree::getKdTreeSplits() {
92  return this->m_splits;
93 }
94 
96 
98  LBPointArray<unsigned int>* sorted_indices, int max_dim) {
99 
100  // DEBUG CHECK
101 
102  int first_split_dim = -1;
103  float best_deviation = -1.0;
104 
105  for(int i=0; i<V.dim; i++)
106  {
107  float deviation = V.elements[static_cast<unsigned int>(
108  sorted_indices[i].elements[sorted_indices[i].width-1]+0.5)* V.dim + i]
109  - V.elements[static_cast<unsigned int>(
110  sorted_indices[i].elements[i]+0.5)* V.dim + i] ;
111 
112  if(deviation > best_deviation)
113  {
114  best_deviation = deviation;
115  first_split_dim = i;
116  }
117  }
118 
119 
120  unsigned int size;
121  int max_tree_depth;
122 
123  max_tree_depth = static_cast<int>( log2f(V.width - 1 ) + 2.0 ) ;
124 
125  if (V.width == 1)
126  {
127  max_tree_depth = 1;
128  }
129 
130  size = V.width * 2 - 1;
131 
132  // std::cout << "size values: " << size << std::endl;
133  this->m_values->elements = (float*)malloc(sizeof(float) * size );
134  this->m_values->width = size;
135  this->m_values->dim = 1;
136 
137  unsigned int size_splits = size - V.width;
138  // std::cout << "size splits: " << size_splits << std::endl;
139  this->m_splits->elements = (unsigned char*)malloc(sizeof(unsigned char) * size_splits );
140  this->m_splits->width = size_splits;
141  this->m_splits->dim = 1;
142 
143  LBPointArray<float>* value_ptr = this->m_values.get();
144  LBPointArray<unsigned char>* splits_ptr = this->m_splits.get();
145  //start real generate
146  generateKdTreeRecursive(0, V, sorted_indices, first_split_dim,
147  max_dim, value_ptr, splits_ptr ,size, max_tree_depth, 0, 0);
148 
149  pool->stop(true);
150  delete pool;
152 }
153 
155  LBPointArray<unsigned int>& sorted_indices, unsigned int current_dim,
156  float split_value, unsigned int split_index,
157  std::list<unsigned int>& critical_indices_left,
158  std::list<unsigned int>& critical_indices_right)
159 {
160  critical_indices_left.push_back( sorted_indices.elements[split_index] );
161 
162  unsigned int iterator;
163  // nach links
164  for(iterator = split_index-1;
165  iterator < sorted_indices.width
166  && V.elements[ sorted_indices.elements[iterator] * V.dim + current_dim] == split_value;
167  iterator--)
168  {
169  critical_indices_left.push_back( sorted_indices.elements[iterator] );
170  }
171 
172  // nach rechts
173  for(iterator = split_index+1;
174  iterator < sorted_indices.width
175  && V.elements[ sorted_indices.elements[iterator] * V.dim + current_dim] == split_value;
176  iterator++)
177  {
178  critical_indices_right.push_back( sorted_indices.elements[iterator] );
179  }
180 
181 }
182 
184  LBPointArray<unsigned int>& sorted_indices, unsigned int current_dim,
185  float split_value, unsigned int split_index,
186  std::unordered_set<unsigned int>& critical_indices_left,
187  std::unordered_set<unsigned int>& critical_indices_right)
188 {
189  // push split index to the left
190  critical_indices_left.insert(sorted_indices.elements[split_index]);
191 
192  unsigned int iterator;
193  // to the left
194  for(iterator = split_index-1;
195  iterator < sorted_indices.width
196  && V.elements[ sorted_indices.elements[iterator] * V.dim + current_dim] == split_value;
197  iterator--)
198  {
199  critical_indices_left.insert( sorted_indices.elements[iterator] );
200  }
201 
202  // to the right
203  for(iterator = split_index+1;
204  iterator < sorted_indices.width
205  && V.elements[ sorted_indices.elements[iterator] * V.dim + current_dim] == split_value;
206  iterator++)
207  {
208  critical_indices_right.insert( sorted_indices.elements[iterator] );
209  }
210 
211 }
212 
214  LBPointArray<unsigned int>* sorted_indices, int current_dim, int max_dim,
216  int size, int max_tree_depth, int position, int current_depth)
217 {
218  int left = position*2+1;
219  int right = position*2+2;
220 
221 
222  if( sorted_indices[current_dim].width <= 1 )
223  {
224  values->elements[position] = static_cast<float>(sorted_indices[current_dim].elements[0] );
225  } else {
227  unsigned int indices_size = sorted_indices[current_dim].width;
228 
229  unsigned int v = pow( 2, static_cast<int>( log2(indices_size-1) ) );
230  unsigned int left_size = indices_size - v/2;
231 
232  if( left_size > v )
233  {
234  left_size = v;
235  }
236 
237  unsigned int right_size = indices_size - left_size;
238 
239 
240 
241  unsigned int split_index = static_cast<unsigned int>(
242  sorted_indices[current_dim].elements[left_size-1] + 0.5
243  );
244 
245  float split_value = V.elements[split_index * V.dim + current_dim ];
246 
247  // critical indices
248  std::unordered_set<unsigned int> critical_indices_left;
249  std::unordered_set<unsigned int> critical_indices_right;
250 
251  fillCriticalIndicesSet(V, sorted_indices[current_dim],
252  current_dim, split_value, left_size-1,
253  critical_indices_left, critical_indices_right);
254 
255  //std::cout << "Split in dimension: " << current_dim << std::endl;
256  values->elements[ position ] = split_value;
257  splits->elements[ position ] = static_cast<unsigned char>(current_dim);
258 
259 
260  LBPointArray<unsigned int> *sorted_indices_left =
262  LBPointArray<unsigned int> *sorted_indices_right =
264 
265  int next_dim_left = -1;
266  int next_dim_right = -1;
267  float biggest_deviation_left = -1.0;
268  float biggest_deviation_right = -1.0;
269 
270  for( int i=0; i<max_dim; i++ )
271  {
272 
273  sorted_indices_left[i].width = left_size;
274  sorted_indices_left[i].dim = 1;
275  sorted_indices_left[i].elements = (unsigned int*)malloc( left_size * sizeof(unsigned int) );
276 
277  sorted_indices_right[i].width = right_size;
278  sorted_indices_right[i].dim = 1;
279  sorted_indices_right[i].elements = (unsigned int*)malloc( right_size * sizeof(unsigned int) );
280 
281  float deviation_left;
282  float deviation_right;
283 
284 
285  if( i == current_dim ){
286  splitPointArray<unsigned int>( sorted_indices[i],
287  sorted_indices_left[i],
288  sorted_indices_right[i]);
289 
290 
291  deviation_left = fabs(V.elements[sorted_indices_left[i].elements[left_size - 1] * V.dim + i ]
292  - V.elements[sorted_indices_left[i].elements[0] * V.dim + i ] );
293  deviation_right = fabs( V.elements[ sorted_indices_right[i].elements[right_size - 1] * V.dim + i ]
294  - V.elements[sorted_indices_right[i].elements[0] * V.dim + i] );
295 
296  } else {
297 
298 
299  // check for wrong value in sorted indices
300 
301  splitPointArrayWithValueSet<float, unsigned int>(V, sorted_indices[i],
302  sorted_indices_left[i], sorted_indices_right[i],
303  current_dim, split_value,
304  deviation_left, deviation_right, i,
305  critical_indices_left, critical_indices_right);
306 
307  }
308 
309  if(deviation_left > biggest_deviation_left )
310  {
311  biggest_deviation_left = deviation_left;
312  next_dim_left = i;
313  }
314 
315  if(deviation_right > biggest_deviation_right )
316  {
317  biggest_deviation_right = deviation_right;
318  next_dim_right = i;
319  }
320  }
321 
322  //int next_dim = (current_dim+1)%max_dim;
323 
324  if(current_depth == st_depth_threads )
325  {
326  pool->push(generateKdTreeRecursive, V, sorted_indices_left,
327  next_dim_left, max_dim, values, splits, size, max_tree_depth,
328  left, current_depth + 1);
329 
330  pool->push(generateKdTreeRecursive, V, sorted_indices_right,
331  next_dim_right, max_dim, values, splits, size, max_tree_depth,
332  right, current_depth +1);
333  } else {
334  //std::cout<< "left " << current_dim << std::endl;
335  generateKdTreeRecursive(0, V, sorted_indices_left, next_dim_left, max_dim,
336  values, splits, size, max_tree_depth, left, current_depth + 1);
337  //std::cout << "right " << current_dim << std::endl;
338  generateKdTreeRecursive(0, V, sorted_indices_right, next_dim_right, max_dim,
339  values, splits, size, max_tree_depth, right, current_depth +1);
340  }
341 
342  }
343 
344  for(int i=0; i<max_dim; i++) {
345  free(sorted_indices[i].elements );
346  }
347  free(sorted_indices);
348 
349 }
350 
351 } /* namespace lvr2 */
static void fillCriticalIndicesSet(const LBPointArray< float > &V, LBPointArray< unsigned int > &sorted_indices, unsigned int current_dim, float split_value, unsigned int split_index, std::unordered_set< unsigned int > &critical_indices_left, std::unordered_set< unsigned int > &critical_indices_right)
Definition: LBKdTree.cpp:183
static int getNumThreads()
Returns the number of supported threads (or 1 if OpenMP is not supported)
Definition: lvropenmp.cpp:70
static ctpl::thread_pool * pool
Definition: LBKdTree.hpp:80
auto push(F &&f, Rest &&... rest) -> std::future< decltype(f(0, rest...))>
Definition: ctpl.h:152
boost::shared_ptr< LBPointArray< unsigned char > > getKdTreeSplits()
Definition: LBKdTree.cpp:91
unsigned int width
boost::shared_ptr< LBPointArray< float > > m_values
Definition: LBKdTree.hpp:70
void generateKdTree(LBPointArray< float > &vertices)
Definition: LBKdTree.cpp:61
static int st_num_threads
Definition: LBKdTree.hpp:77
static void fillCriticalIndices(const LBPointArray< float > &V, LBPointArray< unsigned int > &sorted_indices, unsigned int current_dim, float split_value, unsigned int split_index, std::list< unsigned int > &critical_indices_left, std::list< unsigned int > &critical_indices_right)
Definition: LBKdTree.cpp:154
static void generateKdTreeRecursive(int id, LBPointArray< float > &V, LBPointArray< unsigned int > *sorted_indices, int current_dim, int max_dim, LBPointArray< float > *values, LBPointArray< unsigned char > *splits, int size, int max_tree_depth, int position, int current_depth)
Definition: LBKdTree.cpp:213
static int st_depth_threads
Definition: LBKdTree.hpp:78
unsigned int dim
void generateKdTreeArray(LBPointArray< float > &V, LBPointArray< unsigned int > *sorted_indices, int max_dim)
Private.
Definition: LBKdTree.cpp:97
boost::shared_ptr< LBPointArray< float > > getKdTreeValues()
Definition: LBKdTree.cpp:87
boost::shared_ptr< LBPointArray< unsigned char > > m_splits
Definition: LBKdTree.hpp:73
void stop(bool isWait=false)
Definition: ctpl.h:121
LBKdTree(LBPointArray< float > &vertices, int num_threads=8)
Public.
Definition: LBKdTree.cpp:45


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Mon Feb 28 2022 22:46:07