12 #include <tracking/trackFindingCDC/legendre/quadtree/QuadTreeNode.h>
13 #include <tracking/trackFindingCDC/legendre/quadtree/QuadTreeItem.h>
15 #include <tracking/trackFindingCDC/utilities/Algorithms.h>
30 namespace TrackFindingCDC {
38 template<
typename AX,
typename AY,
class AData>
39 class QuadTreeProcessor {
43 using Item = QuadTreeItem<AData>;
46 using QuadTree = QuadTreeNode<AX, AY, Item>;
55 using XYSpans = std::pair<XSpan, YSpan>;
73 bool debugOutput =
false)
74 :
m_quadTree{std::make_unique<QuadTree>(xySpans.first, xySpans.second, 0,
nullptr)}
104 void seed(std::vector<AData*>& datas)
107 for (AData* data : datas) {
117 std::vector<QuadTree*> nextSeededTrees;
119 for (
int level = 0; level <
m_seedLevel; ++level) {
121 if (node->getChildren().empty()) {
124 for (
QuadTree& child : node->getChildren()) {
125 nextSeededTrees.push_back(&child);
129 nextSeededTrees.clear();
134 seededTree->reserveItems(
m_items.size());
137 if (item.isUsed())
continue;
138 if (
isInNode(seededTree, item.getPointer())) {
139 seededTree->insertItem(&item);
152 std::vector<const CDCWireHit*> result;
154 for (
Item* item : seededTree->getItems()) {
155 result.push_back(item->getPointer());
158 std::sort(result.begin(), result.end());
159 result.erase(std::unique(result.begin(), result.end()), result.end());
171 fill(candidateReceiver, nHitsThreshold, std::numeric_limits<AY>::max());
183 std::sort(quadTrees.begin(), quadTrees.end(), [](
QuadTree * quadTree1,
QuadTree * quadTree2) {
184 return quadTree1->getNItems() > quadTree2->getNItems();
188 erase_remove_if(tree->getItems(), [](
Item * hit) { return hit->isUsed(); });
189 fillGivenTree(tree, candidateReceiver, nHitsThreshold, yLimit);
203 if (node->getNItems() < nItemsThreshold) {
207 if ((node->getYMin() > yLimit) or (-node->getYMax() > yLimit)) {
216 if (node->getChildren().empty()) {
220 if (!node->checkFilled()) {
225 std::vector<QuadTree*> children;
226 for (
QuadTree& child : node->getChildren()) {
227 children.push_back(&child);
230 return lhs->getNItems() < rhs->getNItems();
234 const int nChildren = children.size();
235 for (
int iChild = 0; iChild < nChildren; ++iChild) {
236 auto itHeaviestChild = std::max_element(children.begin(), children.end(), compareNItems);
237 QuadTree* heaviestChild = *itHeaviestChild;
238 children.erase(itHeaviestChild);
241 erase_remove_if(heaviestChild->getItems(), [&](
Item * hit) { return hit->isUsed(); });
242 this->
fillGivenTree(heaviestChild, candidateReceiver, nItemsThreshold, yLimit);
252 for (
int i = 0; i < node->getXNbins(); ++i) {
253 for (
int j = 0; j < node->getYNbins(); ++j) {
255 const XSpan& xSpan = xySpans.first;
256 const YSpan& ySpan = xySpans.second;
257 m_children.push_back(
QuadTree(xSpan, ySpan, node->getLevel() + 1, node));
268 const size_t neededSize = 2 * items.size();
269 for (
QuadTree& child : node->getChildren()) {
270 child.reserveItems(neededSize);
273 for (
Item* item : items) {
274 if (item->isUsed())
continue;
277 if (
isInNode(&child, item->getPointer())) {
278 child.insertItem(item);
291 const std::vector<Item*>& foundItems = node->getItems();
292 std::vector<AData*> candidate;
293 candidate.reserve(foundItems.size());
295 for (
Item* item : foundItems) {
297 candidate.push_back(item->getPointer());
300 candidateReceiver(candidate, node);
314 AX xMin = node->getXLowerBound(iX);
315 AX xMax = node->getXUpperBound(iX);
316 AY yMin = node->getYLowerBound(iY);
317 AY yMax = node->getYUpperBound(iY);
318 return XYSpans({xMin, xMax}, {yMin, yMax});
360 for (
QuadTree& childNode : children) {