8 #ifndef LC_KD_TREE_LINKER_ALGO_TEMPLATED_H
9 #define LC_KD_TREE_LINKER_ALGO_TEMPLATED_H
15 namespace april_content
21 template <
typename DATA,
unsigned DIM = 2>
22 class KDTreeLinkerAlgo
41 void build(std::vector<KDTreeNodeInfoT<DATA, DIM> > &eltList,
const KDTreeBoxT<DIM> ®ion);
50 void search(
const KDTreeBoxT<DIM> &searchBox, std::vector<KDTreeNodeInfoT<DATA, DIM> > &resRecHitList);
59 void findNearestNeighbour(
const KDTreeNodeInfoT<DATA, DIM> &point,
const KDTreeNodeInfoT<DATA, DIM> *&result,
float &distance);
105 KDTreeNodeT<DATA, DIM> *
recBuild(
int low,
int high,
int depth,
const KDTreeBoxT<DIM> ®ion);
113 void recSearch(
const KDTreeNodeT<DATA, DIM> *current,
const KDTreeBoxT<DIM> &trackBox);
124 void recNearestNeighbour(
unsigned depth,
const KDTreeNodeT<DATA, DIM> *current,
const KDTreeNodeInfoT<DATA, DIM> &point,
125 const KDTreeNodeT<DATA, DIM> *&best_match,
float &best_dist);
132 void addSubtree(
const KDTreeNodeT<DATA, DIM> *current);
142 float dist2(
const KDTreeNodeInfoT<DATA, DIM> &a,
const KDTreeNodeInfoT<DATA, DIM> &b)
const;
161 template <
typename DATA,
unsigned DIM>
167 closestNeighbour(nullptr),
168 initialEltList(nullptr)
174 template <
typename DATA,
unsigned DIM>
182 template <
typename DATA,
unsigned DIM>
187 initialEltList = &eltList;
188 const size_t mysize = initialEltList->size();
190 nodePoolSize_ = mysize * 2 - 1;
194 root_ = this->recBuild(0, mysize, 0, region);
195 initialEltList =
nullptr;
201 template <
typename DATA,
unsigned DIM>
207 const int nbrElts = high - low;
208 int median = nbrElts / 2 - (1 - 1 * (nbrElts & 1));
223 const unsigned thedim = treeDepth % DIM;
224 while ((*initialEltList)[i].dims[thedim] < elt.dims[thedim]) ++i;
225 while ((*initialEltList)[j].dims[thedim] > elt.dims[thedim]) --j;
229 std::swap((*initialEltList)[i], (*initialEltList)[j]);
236 if (j < median) l = i;
237 if (i > median) m = j;
245 template <
typename DATA,
unsigned DIM>
250 closestNeighbour = &recHits;
251 this->recSearch(root_, trackBox);
252 closestNeighbour =
nullptr;
258 template <
typename DATA,
unsigned DIM>
266 if ((current->
left ==
nullptr) && (current->
right ==
nullptr))
270 bool isInside =
true;
272 for (
unsigned i = 0; i < DIM; ++i)
274 const auto thedim = current->
info.dims[i];
275 isInside *= thedim >= trackBox.dimmin[i] && thedim <= trackBox.dimmax[i];
279 closestNeighbour->push_back(current->
info);
285 bool isFullyContained =
true;
286 bool hasIntersection =
true;
288 for (
unsigned i = 0; i < DIM; ++i)
290 const auto regionmin = current->
left->region.dimmin[i];
291 const auto regionmax = current->
left->region.dimmax[i];
292 isFullyContained *= (regionmin >= trackBox.dimmin[i] && regionmax <= trackBox.dimmax[i]);
293 hasIntersection *= (regionmin < trackBox.dimmax[i] && regionmax > trackBox.dimmin[i]);
296 if (isFullyContained)
298 this->addSubtree(current->
left);
300 else if (hasIntersection)
302 this->recSearch(current->
left, trackBox);
306 isFullyContained =
true;
307 hasIntersection =
true;
309 for (
unsigned i = 0; i < DIM; ++i)
311 const auto regionmin = current->
right->region.dimmin[i];
312 const auto regionmax = current->
right->region.dimmax[i];
313 isFullyContained *= (regionmin >= trackBox.dimmin[i] && regionmax <= trackBox.dimmax[i]);
314 hasIntersection *= (regionmin < trackBox.dimmax[i] && regionmax > trackBox.dimmin[i]);
317 if (isFullyContained)
319 this->addSubtree(current->
right);
321 else if (hasIntersection)
323 this->recSearch(current->
right, trackBox);
330 template <
typename DATA,
unsigned DIM>
334 if (
nullptr != result || distance != std::numeric_limits<float>::max())
337 distance = std::numeric_limits<float>::max();
343 this->recNearestNeighbour(0, root_, point, best_match, distance);
345 if (distance != std::numeric_limits<float>::max())
347 result = &(best_match->
info);
348 distance = std::sqrt(distance);
355 template <
typename DATA,
unsigned DIM>
359 const unsigned int current_dim = depth % DIM;
361 if (current->
left ==
nullptr && current->
right ==
nullptr)
363 best_match = current;
364 best_dist = this->dist2(point, best_match->
info);
369 const float dist_to_axis = point.dims[current_dim] - current->
info.dims[current_dim];
371 if (dist_to_axis < 0.f)
373 this->recNearestNeighbour(depth + 1, current->
left, point, best_match, best_dist);
377 this->recNearestNeighbour(depth + 1, current->
right, point, best_match, best_dist);
381 const float dist_current = this->dist2(point, current->
info);
383 if (dist_current < best_dist)
385 best_dist = dist_current;
386 best_match = current;
390 if (best_dist > dist_to_axis * dist_to_axis)
394 float check_dist = best_dist;
396 if (dist_to_axis < 0.f)
398 this->recNearestNeighbour(depth + 1, current->
right, point, check_best, check_dist);
402 this->recNearestNeighbour(depth + 1, current->
left, point, check_best, check_dist);
405 if (check_dist < best_dist)
407 best_dist = check_dist;
408 best_match = check_best;
417 template <
typename DATA,
unsigned DIM >
423 if ((current->
left ==
nullptr) && (current->
right ==
nullptr))
426 closestNeighbour->push_back(current->
info);
431 this->addSubtree(current->
left);
432 this->addSubtree(current->
right);
438 template <
typename DATA,
unsigned DIM>
443 for (
unsigned i = 0 ; i < DIM; ++i)
445 const double diff = a.dims[i] - b.dims[i];
454 template <
typename DATA,
unsigned DIM>
466 template <
typename DATA,
unsigned DIM>
469 return (nodePoolPos_ == -1);
474 template <
typename DATA,
unsigned DIM>
477 return (nodePoolPos_ + 1);
482 template <
typename DATA,
unsigned DIM>
491 template <
typename DATA,
unsigned DIM>
500 return &(nodePool_[nodePoolPos_]);
505 template <
typename DATA,
unsigned DIM>
508 const int portionSize = high - low;
513 if (portionSize == 1)
523 int medianId = this->medianSearch(low, high, depth);
528 node->
info = (*initialEltList)[medianId];
534 const unsigned thedim = depth % DIM;
535 auto medianVal = (*initialEltList)[medianId].dims[thedim];
536 leftRegion.dimmax[thedim] = medianVal;
537 rightRegion.dimmin[thedim] = medianVal;
543 node->
left = this->recBuild(low, medianId, depth, leftRegion);
544 node->
right = this->recBuild(medianId, high, depth, rightRegion);
551 #endif // LC_KD_TREE_LINKER_ALGO_TEMPLATED_H
KDTreeNodeT< DATA, DIM > * root_
The KDTree root.
Definition: KDTreeLinkerAlgoT.h:149
std::vector< KDTreeNodeInfoT< DATA, DIM > > * closestNeighbour
The closest neighbour.
Definition: KDTreeLinkerAlgoT.h:154
KDTreeNodeInfoT< DATA, DIM > info
Data.
Definition: KDTreeLinkerToolsT.h:116
KDTree node.
Definition: KDTreeLinkerToolsT.h:93
float dist2(const KDTreeNodeInfoT< DATA, DIM > &a, const KDTreeNodeInfoT< DATA, DIM > &b) const
dist2
Definition: KDTreeLinkerAlgoT.h:439
std::vector< KDTreeNodeInfoT< DATA, DIM > > * initialEltList
The initial element list.
Definition: KDTreeLinkerAlgoT.h:155
void clearTree()
Frees the KDTree.
Definition: KDTreeLinkerAlgoT.h:455
KDTreeLinkerAlgo()
Default constructor.
Definition: KDTreeLinkerAlgoT.h:162
void recNearestNeighbour(unsigned depth, const KDTreeNodeT< DATA, DIM > *current, const KDTreeNodeInfoT< DATA, DIM > &point, const KDTreeNodeT< DATA, DIM > *&best_match, float &best_dist)
Recursive nearest neighbour search. Is called by findNearestNeighbour()
Definition: KDTreeLinkerAlgoT.h:356
KDTreeNodeT< DATA, DIM > * nodePool_
Node pool allows us to do just 1 call to new for each tree building.
Definition: KDTreeLinkerAlgoT.h:150
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM > > &resRecHitList)
Search in the KDTree for all points that would be contained in the given searchbox The founded points...
Definition: KDTreeLinkerAlgoT.h:246
void addSubtree(const KDTreeNodeT< DATA, DIM > *current)
Add all elements of an subtree to the closest elements. Used during the recSearch().
Definition: KDTreeLinkerAlgoT.h:418
void findNearestNeighbour(const KDTreeNodeInfoT< DATA, DIM > &point, const KDTreeNodeInfoT< DATA, DIM > *&result, float &distance)
findNearestNeighbour
Definition: KDTreeLinkerAlgoT.h:331
void clear()
Clear all allocated structures.
Definition: KDTreeLinkerAlgoT.h:483
void recSearch(const KDTreeNodeT< DATA, DIM > *current, const KDTreeBoxT< DIM > &trackBox)
Recursive kdtree search. Is called by search()
Definition: KDTreeLinkerAlgoT.h:259
KDTreeNodeT< DATA, DIM > * left
Left son.
Definition: KDTreeLinkerToolsT.h:117
KDTreeNodeT< DATA, DIM > * recBuild(int low, int high, int depth, const KDTreeBoxT< DIM > ®ion)
Recursive kdtree builder. Is called by build()
Definition: KDTreeLinkerAlgoT.h:506
int size()
Return the number of nodes + leaves in the tree (nElements should be (size() +1) / 2) ...
Definition: KDTreeLinkerAlgoT.h:475
int nodePoolSize_
The node pool size.
Definition: KDTreeLinkerAlgoT.h:151
void build(std::vector< KDTreeNodeInfoT< DATA, DIM > > &eltList, const KDTreeBoxT< DIM > ®ion)
Build the KD tree from the "eltList" in the space define by "region".
Definition: KDTreeLinkerAlgoT.h:183
KDTreeNodeT< DATA, DIM > * right
Right son.
Definition: KDTreeLinkerToolsT.h:118
int nodePoolPos_
The node pool position.
Definition: KDTreeLinkerAlgoT.h:152
~KDTreeLinkerAlgo()
Destructor calls clear.
Definition: KDTreeLinkerAlgoT.h:175
bool empty()
Whether the tree is empty.
Definition: KDTreeLinkerAlgoT.h:467
KDTreeNodeT< DATA, DIM > * getNextNode()
Get the next node from the node pool.
Definition: KDTreeLinkerAlgoT.h:492
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
Definition: KDTreeLinkerToolsT.h:35
void setAttributs(const KDTreeBoxT< DIM > ®ionBox, const KDTreeNodeInfoT< DATA, DIM > &infoToStore)
setAttributs
Definition: KDTreeLinkerToolsT.h:296
int medianSearch(int low, int high, int treeDepth)
Fast median search with Wirth algorithm in eltList between low and high indexes.
Definition: KDTreeLinkerAlgoT.h:202