ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
CVKdTree.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "CVKdTree.h"
9 
10 #include "GenericIndexedCloud.h"
12 
13 // system
14 #include <algorithm>
15 
16 using namespace cloudViewer;
17 
19  : m_root(nullptr), m_associatedCloud(nullptr), m_cellCount(0) {}
20 
22 
24  GenericProgressCallback *progressCb) {
25  unsigned cloudsize = cloud->size();
26 
27  m_indexes.resize(0);
28  m_cellCount = 0;
29  m_associatedCloud = nullptr;
30  m_root = nullptr;
31 
32  if (cloudsize == 0) return false;
33 
34  try {
35  m_indexes.resize(cloudsize);
36  } catch (... /*const std::bad_alloc&*/) // out of memory
37  {
38  return false;
39  }
40 
41  m_associatedCloud = cloud;
42 
43  for (unsigned i = 0; i < cloudsize; i++) m_indexes[i] = i;
44 
45  if (progressCb) {
46  if (progressCb->textCanBeEdited()) {
47  progressCb->setInfo("Building KD-tree");
48  }
49  progressCb->update(0);
50  progressCb->start();
51  }
52 
53  m_root = buildSubTree(0, cloudsize - 1, nullptr, m_cellCount, progressCb);
54 
55  if (progressCb) progressCb->stop();
56 
57  // if the tree building has failed (memory issues)
58  if (!m_root) {
59  m_associatedCloud = nullptr;
60  m_cellCount = 0;
61  return false;
62  }
63 
64  try {
65  m_indexes.resize(cloudsize);
66  } catch (... /*const std::bad_alloc&*/) // out of memory
67  {
68  m_associatedCloud = nullptr;
69  m_cellCount = 0;
70  return false;
71  }
72 
73  return true;
74 }
75 
77  if (!cell) return;
78 
79  deleteSubTree(cell->leSon);
80  deleteSubTree(cell->gSon);
81  delete cell;
82  assert(m_cellCount > 0);
83  m_cellCount--;
84 }
85 
86 /*** Comparison functions used by the sort function (Strict ordering must be
87  * used) ***/
89 
91 static bool ComparisonX(const unsigned &a, const unsigned &b) {
92  return (s_comparisonCloud->getPoint(a)->x <
94 }
95 
97 static bool ComparisonY(const unsigned &a, const unsigned &b) {
98  return (s_comparisonCloud->getPoint(a)->y <
100 }
101 
103 static bool ComparisonZ(const unsigned &a, const unsigned &b) {
104  return (s_comparisonCloud->getPoint(a)->z <
106 }
107 
109  unsigned last,
110  KdCell *father,
111  unsigned &nbBuildCell,
112  GenericProgressCallback *progressCb) {
113  KdCell *cell = new KdCell;
114  if (!cell) return nullptr;
115  m_cellCount++;
116 
117  unsigned dim = (father == nullptr ? 0 : ((father->cuttingDim + 1) % 3));
118 
119  // Compute outside bounding box (have to be done before building the current
120  // cell sons)
121  cell->father = father;
122  cell->startingPointIndex = first;
123  cell->nbPoints = last - first + 1;
124  cell->cuttingDim = dim;
126  if (progressCb)
127  progressCb->update(m_cellCount * 100.0f /
128  (m_indexes.size() * 2.0f - 1.0f));
129 
130  // If there is only one point to insert, build a leaf
131  if (first == last) {
132  cell->cuttingDim = 0;
133  cell->leSon = nullptr;
134  cell->gSon = nullptr;
135  } else {
136  // sort the remaining points considering dimension dim
138  m_associatedCloud; // TODO: not compatible with parallelism!!!
139  if (dim == 0)
140  sort(m_indexes.begin() + first, m_indexes.begin() + (last + 1),
141  ComparisonX);
142  else if (dim == 1)
143  sort(m_indexes.begin() + first, m_indexes.begin() + (last + 1),
144  ComparisonY);
145  else if (dim == 2)
146  sort(m_indexes.begin() + first, m_indexes.begin() + (last + 1),
147  ComparisonZ);
148  // find the median point in the sorted tab
149  unsigned split = (first + last) / 2;
150  const CCVector3 *P = m_associatedCloud->getPoint(m_indexes[split]);
151  cell->cuttingCoordinate = P->u[dim];
152  // recursively build the other two sub trees
153  // trap the memory issues. At this point, none of the cell sons can be
154  // set to 0. Otherwise there has been memory allocation failure.
155  cell->leSon = cell->gSon = nullptr;
156  cell->leSon = buildSubTree(first, split, cell, nbBuildCell, progressCb);
157  if (cell->leSon == nullptr) {
158  deleteSubTree(cell);
159  // the tree beyond the current cell will be deleted when noticing
160  // that this cell is set to 0
161  return nullptr;
162  }
163  cell->gSon =
164  buildSubTree(split + 1, last, cell, nbBuildCell, progressCb);
165  if (cell->gSon == nullptr) {
166  deleteSubTree(cell);
167  // the tree beyond the current cell will be deleted when noticing
168  // that this cell is set to 0
169  return nullptr;
170  }
171  }
172  // Compute inside bounding box (have to be done once sons have been built)
174 
175  return cell;
176 }
177 
179  unsigned &nearestPointIndex,
180  ScalarType maxDist) {
181  if (m_root == nullptr) return false;
182 
183  maxDist *= maxDist;
184 
185  // Go down the tree to find which cell contains the query point (at most
186  // log2(N) tests where N is the total number of points in the cloud)
187  KdCell *cellPtr = m_root;
188  while (cellPtr->leSon != nullptr || cellPtr->gSon != nullptr) {
189  if (queryPoint[cellPtr->cuttingDim] <= cellPtr->cuttingCoordinate)
190  cellPtr = cellPtr->leSon;
191  else
192  cellPtr = cellPtr->gSon;
193  }
194 
195  // Once we found the cell containing the query point, the nearest neighbour
196  // has great chances to lie in this cell
197  bool found = false;
198  for (unsigned i = 0; i < cellPtr->nbPoints; i++) {
200  m_indexes[cellPtr->startingPointIndex + i]);
201  PointCoordinateType sqrdist = CCVector3::vdistance2(p->u, queryPoint);
202  if (sqrdist < maxDist) {
203  maxDist = static_cast<ScalarType>(sqrdist);
204  nearestPointIndex = m_indexes[cellPtr->startingPointIndex + i];
205  found = true;
206  }
207  }
208 
209  // Go up in the tree to check that neighbours cells do not contain a nearer
210  // point than the one we found
211  while (cellPtr != nullptr) {
212  KdCell *prevPtr = cellPtr;
213  cellPtr = cellPtr->father;
214  if (cellPtr != nullptr) {
215  ScalarType sqrdist = insidePointToCellDistance(queryPoint, cellPtr);
216  if (sqrdist >= 0 && sqrdist * sqrdist < maxDist) {
217  KdCell *brotherPtr =
218  (cellPtr->leSon == prevPtr ? cellPtr->gSon
219  : cellPtr->leSon);
220  int a = checkNearerPointInSubTree(queryPoint, maxDist,
221  brotherPtr);
222  if (a >= 0) {
223  nearestPointIndex = a;
224  found = true;
225  }
226  } else {
227  cellPtr = nullptr;
228  }
229  }
230  }
231 
232  return found;
233 }
234 
236  const PointCoordinateType *queryPoint, ScalarType maxDist) {
237  if (m_root == nullptr) {
238  return false;
239  }
240 
241  maxDist *= maxDist;
242 
243  // Go down the tree to find which cell contains the query point (at most
244  // log2(N) tests where N is the total number of points in the cloud)
245  KdCell *cellPtr = m_root;
246  while (cellPtr->leSon != nullptr || cellPtr->gSon != nullptr) {
247  if (queryPoint[cellPtr->cuttingDim] <= cellPtr->cuttingCoordinate)
248  cellPtr = cellPtr->leSon;
249  else
250  cellPtr = cellPtr->gSon;
251 
252  if (nullptr == cellPtr) {
253  // internal inconsitency detected
254  return false;
255  }
256  }
257 
258  // Once we've found the cell containing the query point, the nearest
259  // neighbour has great chances to lie in this cell
260  for (unsigned i = 0; i < cellPtr->nbPoints; i++) {
262  m_indexes[cellPtr->startingPointIndex + i]);
263  PointCoordinateType sqrdist = CCVector3::vdistance2(p->u, queryPoint);
264  if (sqrdist < static_cast<PointCoordinateType>(maxDist)) return true;
265  }
266 
267  // Go up in the tree to check that neighbours cells do not contain a point
268  while (cellPtr != nullptr) {
269  KdCell *prevPtr = cellPtr;
270  cellPtr = cellPtr->father;
271  if (cellPtr != nullptr) {
272  ScalarType sqrdist = insidePointToCellDistance(queryPoint, cellPtr);
273  if (sqrdist >= 0 && sqrdist * sqrdist < maxDist) {
274  KdCell *brotherPtr =
275  (cellPtr->leSon == prevPtr ? cellPtr->gSon
276  : cellPtr->leSon);
277  if (checkDistantPointInSubTree(queryPoint, maxDist, brotherPtr))
278  return true;
279  } else {
280  cellPtr = nullptr;
281  }
282  }
283  }
284 
285  return false;
286 }
287 
288 unsigned KDTree::radiusSearch(const PointCoordinateType *queryPoint,
289  ScalarType distance,
290  ScalarType tolerance,
291  std::vector<unsigned> &pointndexes) {
292  if (m_root == nullptr) {
293  return 0;
294  }
295 
296  distanceScanTree(queryPoint, distance, tolerance, m_root, pointndexes);
297 
298  return static_cast<unsigned>(pointndexes.size());
299 }
300 
302  ScalarType maxDist) {
303  if (m_root == nullptr) return false;
304 
305  maxDist *= maxDist;
306 
307  KdCell *cellPtr = m_root;
308  // Go down the tree to find which cell contains the query point (at most
309  // log2(N) tests where N is the total number of points in the cloud)
310  while (!(cellPtr->leSon == nullptr && cellPtr->gSon == nullptr)) {
311  if (queryPoint[cellPtr->cuttingDim] <= cellPtr->cuttingCoordinate)
312  cellPtr = cellPtr->leSon;
313  else
314  cellPtr = cellPtr->gSon;
315  }
316 
317  // Once we found the cell containing the query point, there are great chance
318  // to find a point if it exists
319  for (unsigned i = 0; i < cellPtr->nbPoints; i++) {
321  m_indexes[cellPtr->startingPointIndex + i]);
322  PointCoordinateType sqrdist = CCVector3::vdistance2(p->u, queryPoint);
323  if (sqrdist < static_cast<PointCoordinateType>(maxDist)) return true;
324  }
325 
326  // Go up in the tree to check that neighbours cells do not contain a point
327  while (cellPtr != nullptr) {
328  KdCell *prevPtr = cellPtr;
329  cellPtr = cellPtr->father;
330  if (cellPtr != nullptr) {
331  ScalarType sqrdist = insidePointToCellDistance(queryPoint, cellPtr);
332  if (sqrdist >= 0 && sqrdist * sqrdist < maxDist) {
333  KdCell *brotherPtr =
334  (cellPtr->leSon == prevPtr ? cellPtr->gSon
335  : cellPtr->leSon);
336  if (checkDistantPointInSubTree(queryPoint, maxDist, brotherPtr))
337  return true;
338  } else {
339  cellPtr = nullptr;
340  }
341  }
342  }
343 
344  return false;
345 }
346 
348  const PointCoordinateType *queryPoint,
349  ScalarType distance,
350  ScalarType tolerance,
351  std::vector<unsigned> &points) {
352  if (m_root == nullptr) return 0;
353 
354  distanceScanTree(queryPoint, distance, tolerance, m_root, points);
355 
356  return static_cast<unsigned>(points.size());
357 }
358 
360  if (cell->leSon != nullptr && cell->gSon != nullptr) {
361  cell->inbbmax.x =
362  std::max(cell->leSon->inbbmax.x, cell->gSon->inbbmax.x);
363  cell->inbbmax.y =
364  std::max(cell->leSon->inbbmax.y, cell->gSon->inbbmax.y);
365  cell->inbbmax.z =
366  std::max(cell->leSon->inbbmax.z, cell->gSon->inbbmax.z);
367  cell->inbbmin.x =
368  std::min(cell->leSon->inbbmin.x, cell->gSon->inbbmin.x);
369  cell->inbbmin.y =
370  std::min(cell->leSon->inbbmin.y, cell->gSon->inbbmin.y);
371  cell->inbbmin.z =
372  std::min(cell->leSon->inbbmin.z, cell->gSon->inbbmin.z);
373  } else {
376  cell->inbbmin = cell->inbbmax = *P;
377  for (unsigned i = 1; i < cell->nbPoints; i++) {
379  m_indexes[i + cell->startingPointIndex]);
380  cell->inbbmax.x = std::max(cell->inbbmax.x, P->x);
381  cell->inbbmax.y = std::max(cell->inbbmax.y, P->y);
382  cell->inbbmax.z = std::max(cell->inbbmax.z, P->z);
383  cell->inbbmin.x = std::min(cell->inbbmin.x, P->x);
384  cell->inbbmin.y = std::min(cell->inbbmin.y, P->y);
385  cell->inbbmin.z = std::min(cell->inbbmin.z, P->z);
386  }
387  }
388 }
389 
391  if (cell->father == nullptr) {
392  cell->boundsMask = 0;
393  } else {
394  unsigned char bound = 1;
395  cell->boundsMask = cell->father->boundsMask;
396  cell->outbbmax = cell->father->outbbmax;
397  cell->outbbmin = cell->father->outbbmin;
400  // Check if this cell is its father leSon (if...) or gSon (else...)
401  if (P->u[cell->father->cuttingDim] <= cell->father->cuttingCoordinate) {
402  // Bounding box max point is linked to the bits [3..5] in the bounds
403  // mask
404  bound = bound << (3 + cell->father->cuttingDim);
405  cell->boundsMask = cell->boundsMask | bound;
406  cell->outbbmax.u[cell->father->cuttingDim] =
407  cell->father->cuttingCoordinate;
408  } else {
409  // Bounding box min point is linked to the bits[0..2] in the bounds
410  // mask
411  bound = bound << (cell->father->cuttingDim);
412  cell->boundsMask = cell->boundsMask | bound;
413  cell->outbbmin.u[cell->father->cuttingDim] =
414  cell->father->cuttingCoordinate;
415  }
416  }
417 }
418 
420  const PointCoordinateType *queryPoint, KdCell *cell) {
421  PointCoordinateType dx, dy, dz;
422 
423  // Each d(x)(y)(z) represents the distance to the nearest bounding box plane
424  // (if the point is outside)
425  if (cell->inbbmin.x <= queryPoint[0] && queryPoint[0] <= cell->inbbmax.x)
426  dx = 0;
427  else
428  dx = std::min(std::abs(queryPoint[0] - cell->inbbmin.x),
429  std::abs(queryPoint[0] - cell->inbbmax.x));
430 
431  if (cell->inbbmin.y <= queryPoint[1] && queryPoint[1] <= cell->inbbmax.y)
432  dy = 0;
433  else
434  dy = std::min(std::abs(queryPoint[1] - cell->inbbmin.y),
435  std::abs(queryPoint[1] - cell->inbbmax.y));
436 
437  if (cell->inbbmin.z <= queryPoint[2] && queryPoint[2] <= cell->inbbmax.z)
438  dz = 0;
439  else
440  dz = std::min(std::abs(queryPoint[2] - cell->inbbmin.z),
441  std::abs(queryPoint[2] - cell->inbbmax.z));
442 
443  return static_cast<ScalarType>(dx * dx + dy * dy + dz * dz);
444 }
445 
447  KdCell *cell,
448  ScalarType &min,
449  ScalarType &max) {
450  PointCoordinateType dx, dy, dz;
451 
452  min = sqrt(pointToCellSquareDistance(queryPoint, cell));
453  dx = std::max(std::abs(queryPoint[0] - cell->inbbmin.x),
454  std::abs(queryPoint[0] - cell->inbbmax.x));
455  dy = std::max(std::abs(queryPoint[1] - cell->inbbmin.y),
456  std::abs(queryPoint[1] - cell->inbbmax.y));
457  dz = std::max(std::abs(queryPoint[2] - cell->inbbmin.z),
458  std::abs(queryPoint[2] - cell->inbbmax.z));
459  max = static_cast<ScalarType>(sqrt(dx * dx + dy * dy + dz * dz));
460 }
461 
463  const PointCoordinateType *queryPoint, KdCell *cell) {
464  PointCoordinateType dx, dy, dz, max;
465 
466  dx = dy = dz = -1;
467 
468  if ((cell->boundsMask & 1) && (cell->boundsMask & 8))
469  dx = std::min(std::abs(queryPoint[0] - cell->outbbmin.x),
470  std::abs(queryPoint[0] - cell->outbbmax.x));
471  else if (cell->boundsMask & 1)
472  dx = std::abs(queryPoint[0] - cell->outbbmin.x);
473  else if (cell->boundsMask & 8)
474  dx = std::abs(queryPoint[0] - cell->outbbmax.x);
475 
476  if ((cell->boundsMask & 2) && (cell->boundsMask & 16))
477  dy = std::min(std::abs(queryPoint[1] - cell->outbbmin.y),
478  std::abs(queryPoint[1] - cell->outbbmax.y));
479  else if (cell->boundsMask & 2)
480  dy = std::abs(queryPoint[1] - cell->outbbmin.y);
481  else if (cell->boundsMask & 16)
482  dy = std::abs(queryPoint[1] - cell->outbbmax.y);
483 
484  if ((cell->boundsMask & 4) && (cell->boundsMask & 32))
485  dz = std::min(std::abs(queryPoint[2] - cell->outbbmin.z),
486  std::abs(queryPoint[2] - cell->outbbmax.z));
487  else if (cell->boundsMask & 4)
488  dz = std::abs(queryPoint[2] - cell->outbbmin.z);
489  else if (cell->boundsMask & 32)
490  dz = std::abs(queryPoint[2] - cell->outbbmax.z);
491 
492  if (dx < 0 && dy < 0 && dz < 0) return -1;
493 
494  max = std::max(dx, std::max(dy, dz));
495  if (dx < 0) dx = max;
496  if (dy < 0) dy = max;
497  if (dz < 0) dz = max;
498 
499  return static_cast<ScalarType>(std::min(dx, std::min(dy, dz)));
500 }
501 
503  ScalarType &maxSqrDist,
504  KdCell *cell) {
505  if (pointToCellSquareDistance(queryPoint, cell) >= maxSqrDist) return -1;
506 
507  if (cell->leSon == nullptr && cell->gSon == nullptr) {
508  int a = -1;
509  for (unsigned i = 0; i < cell->nbPoints; i++) {
511  m_indexes[cell->startingPointIndex + i]);
513  if (dist < maxSqrDist) {
514  a = m_indexes[cell->startingPointIndex + i];
515  maxSqrDist = static_cast<ScalarType>(dist);
516  }
517  }
518 
519  return a;
520  }
521 
522  int b = checkNearerPointInSubTree(queryPoint, maxSqrDist, cell->gSon);
523  if (b >= 0) return b;
524 
525  return checkNearerPointInSubTree(queryPoint, maxSqrDist, cell->leSon);
526 }
527 
529  ScalarType &maxSqrDist,
530  KdCell *cell) {
531  if (pointToCellSquareDistance(queryPoint, cell) >= maxSqrDist) return false;
532 
533  if (cell->leSon == nullptr && cell->gSon == nullptr) {
534  for (unsigned i = 0; i < cell->nbPoints; i++) {
536  m_indexes[cell->startingPointIndex + i]);
538  if (dist < maxSqrDist) return true;
539  }
540  return false;
541  }
542 
543  if (checkDistantPointInSubTree(queryPoint, maxSqrDist, cell->leSon))
544  return true;
545  if (checkDistantPointInSubTree(queryPoint, maxSqrDist, cell->gSon))
546  return true;
547 
548  return false;
549 }
550 
552  ScalarType distance,
553  ScalarType tolerance,
554  KdCell *cell,
555  std::vector<unsigned> &localArray) {
556  ScalarType min, max;
557 
558  pointToCellDistances(queryPoint, cell, min, max);
559 
560  if ((min <= distance + tolerance) && (max >= distance - tolerance)) {
561  if ((cell->leSon != nullptr) && (cell->gSon != nullptr)) {
562  // This case shall always happen (the other case is for leaves that
563  // contain more than one point - bucket KDtree)
564  if (cell->nbPoints == 1) {
565  localArray.push_back(m_indexes[cell->startingPointIndex]);
566  } else {
567  for (unsigned i = 0; i < cell->nbPoints; i++) {
569  m_indexes[i + cell->startingPointIndex]);
571  CCVector3::vdistance(queryPoint, p->u);
572  if (distance - tolerance <= dist &&
573  dist <= distance + tolerance)
574  localArray.push_back(
575  m_indexes[cell->startingPointIndex + i]);
576  }
577  }
578  } else {
579  distanceScanTree(queryPoint, distance, tolerance, cell->leSon,
580  localArray);
581  distanceScanTree(queryPoint, distance, tolerance, cell->gSon,
582  localArray);
583  }
584  }
585 }
static bool ComparisonX(const unsigned &a, const unsigned &b)
Compares X coordinates of two points designated by their index.
Definition: CVKdTree.cpp:91
static cloudViewer::GenericIndexedCloud * s_comparisonCloud
Definition: CVKdTree.cpp:88
static bool ComparisonY(const unsigned &a, const unsigned &b)
Compares Y coordinates of two points designated by their index.
Definition: CVKdTree.cpp:97
static bool ComparisonZ(const unsigned &a, const unsigned &b)
Compares Z coordinates of two points designated by their index.
Definition: CVKdTree.cpp:103
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
int points
Type y
Definition: CVGeom.h:137
Type u[3]
Definition: CVGeom.h:139
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
static PointCoordinateType vdistance(const PointCoordinateType p[], const PointCoordinateType q[])
Definition: CVGeom.h:598
static PointCoordinateType vdistance2(const PointCoordinateType p[], const PointCoordinateType q[])
Definition: CVGeom.h:581
virtual unsigned size() const =0
Returns the number of points.
A generic 3D point cloud with index-based point access.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
virtual void stop()=0
Notifies the fact that the process has ended.
virtual void setInfo(const char *infoStr)=0
Notifies some information about the ongoing process.
virtual bool textCanBeEdited() const
Returns whether the dialog title and info can be updated or not.
virtual void update(float percent)=0
Notifies the algorithm progress.
void deleteSubTree(KdCell *cell)
Deletes a sub tree.
Definition: CVKdTree.cpp:76
virtual ~KDTree()
Destructor.
Definition: CVKdTree.cpp:21
std::vector< unsigned > m_indexes
Point indexes.
Definition: CVKdTree.h:171
void updateOutsideBoundingBox(KdCell *cell)
Definition: CVKdTree.cpp:390
unsigned findPointsLyingToDistance(const PointCoordinateType *queryPoint, ScalarType distance, ScalarType tolerance, std::vector< unsigned > &points)
Definition: CVKdTree.cpp:347
KDTree()
Default constructor.
Definition: CVKdTree.cpp:18
GenericIndexedCloud * m_associatedCloud
Associated cloud.
Definition: CVKdTree.h:173
unsigned m_cellCount
Number of cells.
Definition: CVKdTree.h:175
void pointToCellDistances(const PointCoordinateType *queryPoint, KdCell *cell, ScalarType &min, ScalarType &max)
Definition: CVKdTree.cpp:446
bool findNearestNeighbour(const PointCoordinateType *queryPoint, unsigned &nearestPointIndex, ScalarType maxDist)
Nearest point search.
Definition: CVKdTree.cpp:178
ScalarType pointToCellSquareDistance(const PointCoordinateType *queryPoint, KdCell *cell)
Computes the distance between a point and a cell inside bounding box.
Definition: CVKdTree.cpp:419
ScalarType insidePointToCellDistance(const PointCoordinateType *queryPoint, KdCell *cell)
Definition: CVKdTree.cpp:462
int checkNearerPointInSubTree(const PointCoordinateType *queryPoint, ScalarType &maxSqrDist, KdCell *cell)
Definition: CVKdTree.cpp:502
void updateInsideBoundingBox(KdCell *cell)
Definition: CVKdTree.cpp:359
bool findPointBelowDistance(const PointCoordinateType *queryPoint, ScalarType maxDist)
Optimized version of nearest point search method.
Definition: CVKdTree.cpp:301
KdCell * buildSubTree(unsigned first, unsigned last, KdCell *father, unsigned &nbBuildCell, GenericProgressCallback *progressCb=nullptr)
Builds a sub tree.
Definition: CVKdTree.cpp:108
KdCell * m_root
Tree root.
Definition: CVKdTree.h:169
unsigned radiusSearch(const PointCoordinateType *queryPoint, ScalarType distance, ScalarType tolerance, std::vector< unsigned > &pointndexes)
Definition: CVKdTree.cpp:288
void distanceScanTree(const PointCoordinateType *queryPoint, ScalarType distance, ScalarType tolerance, KdCell *cell, std::vector< unsigned > &localArray)
Definition: CVKdTree.cpp:551
bool findNearestNeighbourWithMaxDist(const PointCoordinateType *queryPoint, ScalarType maxDist)
Optimized version of findNearestNeighbour with a maximum distance.
Definition: CVKdTree.cpp:235
bool checkDistantPointInSubTree(const PointCoordinateType *queryPoint, ScalarType &maxSqrDist, KdCell *cell)
Definition: CVKdTree.cpp:528
bool buildFromCloud(GenericIndexedCloud *cloud, GenericProgressCallback *progressCb=nullptr)
Builds the KD-tree.
Definition: CVKdTree.cpp:23
int min(int a, int b)
Definition: cutil_math.h:53
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
int max(int a, int b)
Definition: cutil_math.h:48
static double dist(double x1, double y1, double x2, double y2)
Definition: lsd.c:207
Generic file read and write utility for python interface.
A KDTre cell struct.
Definition: CVKdTree.h:101
CCVector3 outbbmin
Outside bounding box min point.
Definition: CVKdTree.h:129
PointCoordinateType cuttingCoordinate
Place where the space is cut into two sub-spaces (children)
Definition: CVKdTree.h:140
unsigned char boundsMask
Mask to know if the outside box is bounded for a given dimmension.
Definition: CVKdTree.h:160
struct KdCell * father
To go up in the tree.
Definition: CVKdTree.h:148
CCVector3 inbbmin
Inside bounding box min point.
Definition: CVKdTree.h:124
struct KdCell * leSon
Definition: CVKdTree.h:143
CCVector3 outbbmax
Outside bounding box max point.
Definition: CVKdTree.h:134
CCVector3 inbbmax
Inside bounding box max point.
Definition: CVKdTree.h:119
struct KdCell * gSon
Definition: CVKdTree.h:146
unsigned nbPoints
Number of elements in this cell.
Definition: CVKdTree.h:152
unsigned startingPointIndex
Index of the first element that belongs to this cell.
Definition: CVKdTree.h:150