8 #ifndef LAR_KD_TREE_LINKER_ALGO_TEMPLATED_H 9 #define LAR_KD_TREE_LINKER_ALGO_TEMPLATED_H 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>
174 template <
typename DATA,
unsigned DIM>
182 template <
typename DATA,
unsigned DIM>
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;
248 template <
typename DATA,
unsigned DIM>
261 template <
typename DATA,
unsigned DIM>
269 if ((current->
left ==
nullptr) && (current->
right ==
nullptr))
273 bool isInside =
true;
275 for (
unsigned i = 0; i < DIM; ++i)
277 const auto thedim = current->
info.dims[i];
278 isInside = isInside && thedim >= trackBox.
dimmin[i] && thedim <= trackBox.
dimmax[i];
288 bool isFullyContained =
true;
289 bool hasIntersection =
true;
291 for (
unsigned i = 0; i < DIM; ++i)
293 const auto regionmin = current->
left->region.dimmin[i];
294 const auto regionmax = current->
left->region.dimmax[i];
295 isFullyContained = isFullyContained && (regionmin >= trackBox.
dimmin[i] && regionmax <= trackBox.
dimmax[i]);
296 hasIntersection = hasIntersection && (regionmin < trackBox.
dimmax[i] && regionmax > trackBox.
dimmin[i]);
299 if (isFullyContained)
303 else if (hasIntersection)
309 isFullyContained =
true;
310 hasIntersection =
true;
312 for (
unsigned i = 0; i < DIM; ++i)
314 const auto regionmin = current->
right->region.dimmin[i];
315 const auto regionmax = current->
right->region.dimmax[i];
316 isFullyContained = isFullyContained && (regionmin >= trackBox.
dimmin[i] && regionmax <= trackBox.
dimmax[i]);
317 hasIntersection = hasIntersection && (regionmin < trackBox.
dimmax[i] && regionmax > trackBox.
dimmin[i]);
320 if (isFullyContained)
324 else if (hasIntersection)
333 template <
typename DATA,
unsigned DIM>
337 if (
nullptr != result || distance != std::numeric_limits<float>::max())
340 distance = std::numeric_limits<float>::max();
348 if (distance != std::numeric_limits<float>::max())
350 result = &(best_match->
info);
351 distance = std::sqrt(distance);
358 template <
typename DATA,
unsigned DIM>
362 const unsigned int current_dim = depth % DIM;
364 if (current->
left ==
nullptr && current->
right ==
nullptr)
366 best_match = current;
367 best_dist = this->
dist2(point, best_match->
info);
372 const float dist_to_axis = point.
dims[current_dim] - current->
info.dims[current_dim];
374 if (dist_to_axis < 0.
f)
384 const float dist_current = this->
dist2(point, current->
info);
386 if (dist_current < best_dist)
388 best_dist = dist_current;
389 best_match = current;
393 if (best_dist > dist_to_axis * dist_to_axis)
397 float check_dist = best_dist;
399 if (dist_to_axis < 0.
f)
408 if (check_dist < best_dist)
410 best_dist = check_dist;
411 best_match = check_best;
420 template <
typename DATA,
unsigned DIM>
426 if ((current->
left ==
nullptr) && (current->
right ==
nullptr))
441 template <
typename DATA,
unsigned DIM>
446 for (
unsigned i = 0; i < DIM; ++i)
448 const double diff = a.
dims[i] - b.
dims[i];
457 template <
typename DATA,
unsigned DIM>
469 template <
typename DATA,
unsigned DIM>
477 template <
typename DATA,
unsigned DIM>
485 template <
typename DATA,
unsigned DIM>
494 template <
typename DATA,
unsigned DIM>
508 template <
typename DATA,
unsigned DIM>
511 const int portionSize = high - low;
516 if (portionSize == 1)
531 node->
info = (*initialEltList)[medianId];
537 const unsigned thedim = depth % DIM;
538 auto medianVal = (*initialEltList)[medianId].dims[thedim];
539 leftRegion.
dimmax[thedim] = medianVal;
540 rightRegion.
dimmin[thedim] = medianVal;
546 node->
left = this->
recBuild(low, medianId, depth, leftRegion);
547 node->
right = this->
recBuild(medianId, high, depth, rightRegion);
554 #endif // LAR_KD_TREE_LINKER_ALGO_TEMPLATED_H int nodePoolPos_
The node pool position.
KDTreeNodeT< DATA, DIM > * root_
The KDTree root.
std::vector< KDTreeNodeInfoT< DATA, DIM > > * initialEltList
The initial element list.
void setAttributs(const KDTreeBoxT< DIM > ®ionBox, const KDTreeNodeInfoT< DATA, DIM > &infoToStore)
setAttributs
Box structure used to define 2D field. It's used in KDTree building step to divide the detector space...
KDTreeNodeInfoT< DATA, DIM > info
Data.
int nodePoolSize_
The node pool size.
std::array< float, DIM > dims
KDTreeLinkerAlgo()
Default constructor.
int size()
Return the number of nodes + leaves in the tree (nElements should be (size() +1) / 2) ...
void clear()
Clear all allocated structures.
KDTreeNodeT< DATA, DIM > * right
Right son.
bool empty()
Whether the tree is empty.
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()
void findNearestNeighbour(const KDTreeNodeInfoT< DATA, DIM > &point, const KDTreeNodeInfoT< DATA, DIM > *&result, float &distance)
findNearestNeighbour
Data stored in each KDTree node. The dim1/dim2 fields are usually the duplication of some PFRecHit va...
void clearTree()
Frees the KDTree.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
KDTreeNodeT< DATA, DIM > * left
Left son.
KDTreeNodeT< DATA, DIM > * getNextNode()
Get the next node from the node pool.
~KDTreeLinkerAlgo()
Destructor calls clear.
float dist2(const KDTreeNodeInfoT< DATA, DIM > &a, const KDTreeNodeInfoT< DATA, DIM > &b) const
dist2
void addSubtree(const KDTreeNodeT< DATA, DIM > *current)
Add all elements of an subtree to the closest elements. Used during the recSearch().
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".
KDTreeNodeT< DATA, DIM > * nodePool_
Node pool allows us to do just 1 call to new for each tree building.
std::vector< KDTreeNodeInfoT< DATA, DIM > > * closestNeighbour
The closest neighbour.
std::array< float, DIM > dimmin
KDTreeNodeT< DATA, DIM > * recBuild(int low, int high, int depth, const KDTreeBoxT< DIM > ®ion)
Recursive kdtree builder. Is called by build()
std::array< float, DIM > dimmax
int medianSearch(int low, int high, int treeDepth)
Fast median search with Wirth algorithm in eltList between low and high indexes.
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...
void recSearch(const KDTreeNodeT< DATA, DIM > *current, const KDTreeBoxT< DIM > &trackBox)
Recursive kdtree search. Is called by search()