9#include <tracking/gnnFinder/Utils.h>
10#include <framework/logging/Logger.h>
16using namespace Belle2::GNNFinder::Utils;
21 std::generate(
m_pool.begin(),
m_pool.end(), [] { return new KDTNode(); });
34 B2ERROR(
"KDTNodePool:allocate() exceeded pool capacity.");
46template<
typename Iterator,
typename Compare>
49 for (
Iterator i = begin; i != end; ++i) {
51 for (
Iterator j = i; j != begin && cmp(*j, *(j - 1)); --j) {
52 std::iter_swap(j, j - 1);
58 KDTNodePool& pool,
const size_t insertionSortThreshold)
64 const int dim = depth % 2;
65 const auto cmp = [dim](
const KDTHit & a,
const KDTHit & b) {
66 return (dim == 0) ? a.x < b.x : a.y < b.y;
69 const size_t n = std::distance(begin, end);
70 const auto mid = begin + n / 2;
72 if (n < insertionSortThreshold) {
77 std::nth_element(begin, mid, end, cmp);
108 const int dim = node->
dim;
109 const double qVal = (dim == 0) ? query.
x : query.
y;
110 const double nVal = (dim == 0) ? node->
hit.
x : node->
hit.
y;
120 const double diff = qVal - nVal;
121 if ((diff * diff) < bestDist) {
138 const int dim = node->
dim;
139 const double hVal = (dim == 0) ? hit.
x : hit.
y;
140 const double nVal = (dim == 0) ? node->
hit.
x : node->
hit.
y;
161 std::vector<KDTHit> kdtHits)
165 return std::vector<int> {};
172 const KDTHit startingHit{startingX, startingY, -1};
177 const KDTHit& firstHit = *std::min_element(kdtHits.begin(), kdtHits.end(),
179 return a.squaredDistanceTo(startingHit) < b.squaredDistanceTo(startingHit);
186 std::vector<int> sortedIndices;
187 sortedIndices.reserve(kdtHits.size());
188 sortedIndices.push_back(firstHit.
hitIndex);
191 KDTHit currentHit = firstHit;
192 for (
size_t i = 1; i < kdtHits.size(); ++i) {
194 double bestNeighborDist = std::numeric_limits<double>::max();
198 if (bestNeighborDist == std::numeric_limits<double>::max())
201 currentHit = bestNeighbor;
202 sortedIndices.push_back(currentHit.
hitIndex);
206 return sortedIndices;
209std::pair<double, double> Belle2::GNNFinder::Utils::intersectCylinderXY(
const ROOT::Math::XYZVector& pos,
210 const ROOT::Math::XYZVector& mom,
211 const double targetR)
214 const double rSq = pos.X() * pos.X() + pos.Y() * pos.Y();
215 if (rSq >= targetR * targetR)
216 return {pos.X(), pos.Y()};
219 const double a = mom.X() * mom.X() + mom.Y() * mom.Y();
220 const double b = 2.0 * (pos.X() * mom.X() + pos.Y() * mom.Y());
221 const double c = rSq - (targetR * targetR);
222 const double discriminant = b * b - 4.0 * a * c;
223 if (discriminant < 0 or a == 0)
224 return {pos.X(), pos.Y()};
225 const double sqrtD = std::sqrt(discriminant);
226 const double invA = 1.0 / a;
227 const double t1 = 0.5 * (-b + sqrtD) * invA;
228 const double t2 = 0.5 * (-b - sqrtD) * invA;
231 if (t1 > 0 && t2 > 0) t = std::min(t1, t2);
232 else if (t1 > 0) t = t1;
233 else if (t2 > 0) t = t2;
235 return {pos.X() + t * mom.X(), pos.Y() + t * mom.Y()};
236 return {pos.X(), pos.Y()};
static void nearestNeighbor(const KDTNode *node, const KDTHit &query, KDTHit &best, double &bestDist)
Finds the closest unused neighbor to a query hit in the KD-tree.
static bool markUsed(KDTNode *node, const KDTHit &hit)
Marks a KD-tree node as used if its hit index matches the given hit.
static void freeKDTree(KDTNode *node)
Recursively frees all nodes in a KD-tree.
static KDTNode * buildKDTree(std::vector< KDTHit >::iterator begin, std::vector< KDTHit >::iterator end, const int depth, KDTNodePool &pool, const size_t insertionSortThreshold=10)
Recursively builds a balanced KD-tree from a range of KDTHits.
static void insertionSort(Iterator begin, Iterator end, Compare cmp)
Sorts a small range using insertion sort for performance.
static std::vector< int > orderHits(const double startingX, const double startingY, std::vector< KDTHit > kdtHits)
Sort hits spatially based on proximity to a starting position.
Memory pool for pre-allocating and reusing KDTNode objects.
size_t m_index
Current index for the next available node in the pool.
KDTNodePool(size_t capacity)
Constructs a pool with the specified capacity.
std::vector< KDTNode * > m_pool
Internal storage for preallocated KD-tree nodes.
~KDTNodePool()
Destructor.
void reset()
Resets the pool index, making all nodes available for reuse.
KDTNode * allocate()
Allocates and returns the next available KDTNode from the pool.
map< unsigned, size_t >::const_iterator Iterator
Iterator for m_map.
Lightweight 2D representation of a CDC hit for KD-tree sorting.
double squaredDistanceTo(const KDTHit &other) const
Compute squared distance to another KDTHit.
double y
Y coordinate of the hit.
int hitIndex
Index of the hit in the original input collection.
double x
X coordinate of the hit.
Node structure for a 2D KD-tree used in spatial hit sorting.
KDTHit hit
The hit associated with this node (contains x, y, and index).
int dim
Splitting dimension: 0 for x-axis, 1 for y-axis.
KDTNode * left
Pointer to the left subtree (for values less than split).
KDTNode * right
Pointer to the right subtree (for values greater than split).
bool used
Flag indicating whether the node has already been used in traversal.