CMS 3D CMS Logo

KDTreeLinkerAlgo.cc
Go to the documentation of this file.
2 
4  : root_ (nullptr),
5  nodePool_(nullptr),
6  nodePoolSize_(-1),
7  nodePoolPos_(-1)
8 {
9 }
10 
12 {
13  clear();
14 }
15 
16 void
17 KDTreeLinkerAlgo::build(std::vector<KDTreeNodeInfo> &eltList,
18  const KDTreeBox &region)
19 {
20  if (!eltList.empty()) {
21  nodePoolSize_ = eltList.size() * 2 - 1;
23 
24  // Here we build the KDTree
25  root_ = recBuild(eltList, 0, eltList.size(), 0, region);
26  }
27 }
28 
29 
31 KDTreeLinkerAlgo::recBuild(std::vector<KDTreeNodeInfo> &eltList,
32  int low,
33  int high,
34  int depth,
35  const KDTreeBox& region)
36 {
37  int portionSize = high - low;
38 
39  // By construction, portionSize > 0 can't happend.
40  assert(portionSize > 0);
41 
42  if (portionSize == 1) { // Leaf case
43 
44  KDTreeNode *leaf = getNextNode();
45  leaf->setAttributs(region, eltList[low]);
46  return leaf;
47 
48  } else { // Node case
49 
50  // The even depth is associated to dim1 dimension
51  // The odd one to dim2 dimension
52  int medianId = medianSearch(eltList, low, high, depth);
53 
54  // We create the node
55  KDTreeNode *node = getNextNode();
56  node->setAttributs(region);
57 
58 
59  // Here we split into 2 halfplanes the current plane
60  KDTreeBox leftRegion = region;
61  KDTreeBox rightRegion = region;
62  if (depth & 1) {
63 
64  double medianVal = eltList[medianId].dim2;
65  leftRegion.dim2max = medianVal;
66  rightRegion.dim2min = medianVal;
67 
68  } else {
69 
70  double medianVal = eltList[medianId].dim1;
71  leftRegion.dim1max = medianVal;
72  rightRegion.dim1min = medianVal;
73 
74  }
75 
76  ++depth;
77  ++medianId;
78 
79  // We recursively build the son nodes
80  node->left = recBuild(eltList, low, medianId, depth, leftRegion);
81  node->right = recBuild(eltList, medianId, high, depth, rightRegion);
82 
83  return node;
84  }
85 }
86 
87 
88 //Fast median search with Wirth algorithm in eltList between low and high indexes.
89 int
90 KDTreeLinkerAlgo::medianSearch(std::vector<KDTreeNodeInfo> &eltList,
91  int low,
92  int high,
93  int treeDepth)
94 {
95  //We should have at least 1 element to calculate the median...
96  assert(low < high);
97 
98  int nbrElts = high - low;
99  int median = (nbrElts & 1) ? nbrElts / 2
100  : nbrElts / 2 - 1;
101  median += low;
102 
103  int l = low;
104  int m = high - 1;
105 
106  while (l < m) {
107  KDTreeNodeInfo elt = eltList[median];
108  int i = l;
109  int j = m;
110 
111  do {
112 
113  // The even depth is associated to dim1 dimension
114  // The odd one to dim2 dimension
115  if (treeDepth & 1) {
116  while (eltList[i].dim2 < elt.dim2) i++;
117  while (eltList[j].dim2 > elt.dim2) j--;
118  } else {
119  while (eltList[i].dim1 < elt.dim1) i++;
120  while (eltList[j].dim1 > elt.dim1) j--;
121  }
122 
123  if (i <= j){
124  swap(eltList[i], eltList[j]);
125  i++;
126  j--;
127  }
128  } while (i <= j);
129  if (j < median) l = i;
130  if (i > median) m = j;
131  }
132 
133  return median;
134 }
135 
136 void
138  KDTreeNodeInfo &e2)
139 {
140  KDTreeNodeInfo tmp = e1;
141  e1 = e2;
142  e2 = tmp;
143 }
144 
145 void
147  std::vector<KDTreeNodeInfo> &recHits)
148 {
149  if (root_)
150  recSearch(root_, trackBox, recHits);
151 }
152 
153 void
155  const KDTreeBox &trackBox,
156  std::vector<KDTreeNodeInfo> &recHits)
157 {
158  // By construction, current can't be null
159  assert(current != nullptr);
160 
161  // By Construction, a node can't have just 1 son.
162  assert (!(((current->left == nullptr) && (current->right != nullptr)) ||
163  ((current->left != nullptr) && (current->right == nullptr))));
164 
165  if ((current->left == nullptr) && (current->right == nullptr)) {//leaf case
166 
167  // If point inside the rectangle/area
168  if ((current->rh.dim1 >= trackBox.dim1min) && (current->rh.dim1 <= trackBox.dim1max) &&
169  (current->rh.dim2 >= trackBox.dim2min) && (current->rh.dim2 <= trackBox.dim2max))
170  recHits.push_back(current->rh);
171 
172  } else {
173 
174  //if region( v->left ) is fully contained in the rectangle
175  if ((current->left->region.dim1min >= trackBox.dim1min) &&
176  (current->left->region.dim1max <= trackBox.dim1max) &&
177  (current->left->region.dim2min >= trackBox.dim2min) &&
178  (current->left->region.dim2max <= trackBox.dim2max))
179  addSubtree(current->left, recHits);
180 
181  else { //if region( v->left ) intersects the rectangle
182 
183  if (!((current->left->region.dim1min >= trackBox.dim1max) ||
184  (current->left->region.dim1max <= trackBox.dim1min) ||
185  (current->left->region.dim2min >= trackBox.dim2max) ||
186  (current->left->region.dim2max <= trackBox.dim2min)))
187  recSearch(current->left, trackBox, recHits);
188  }
189 
190  //if region( v->right ) is fully contained in the rectangle
191  if ((current->right->region.dim1min >= trackBox.dim1min) &&
192  (current->right->region.dim1max <= trackBox.dim1max) &&
193  (current->right->region.dim2min >= trackBox.dim2min) &&
194  (current->right->region.dim2max <= trackBox.dim2max))
195  addSubtree(current->right, recHits);
196 
197  else { //if region( v->right ) intersects the rectangle
198 
199  if (!((current->right->region.dim1min >= trackBox.dim1max) ||
200  (current->right->region.dim1max <= trackBox.dim1min) ||
201  (current->right->region.dim2min >= trackBox.dim2max) ||
202  (current->right->region.dim2max <= trackBox.dim2min)))
203  recSearch(current->right, trackBox, recHits);
204  }
205  }
206 }
207 
208 void
210  std::vector<KDTreeNodeInfo> &recHits)
211 {
212  // By construction, current can't be null
213  assert(current != nullptr);
214 
215  if ((current->left == nullptr) && (current->right == nullptr)) // leaf
216  recHits.push_back(current->rh);
217  else { // node
218  addSubtree(current->left, recHits);
219  addSubtree(current->right, recHits);
220  }
221 }
222 
223 
224 void
226 {
227  delete[] nodePool_;
228  nodePool_ = nullptr;
229  root_ = nullptr;
230  nodePoolSize_ = -1;
231  nodePoolPos_ = -1;
232 }
233 
234 void
236 {
237  if (root_)
238  clearTree();
239 }
240 
241 
242 KDTreeNode*
244 {
245  ++nodePoolPos_;
246 
247  // The tree size is exactly 2 * nbrElts - 1 and this is the total allocated memory.
248  // If we have used more than that....there is a big problem.
249  assert(nodePoolPos_ < nodePoolSize_);
250 
251  return &(nodePool_[nodePoolPos_]);
252 }
void setAttributs(const KDTreeBox &regionBox, const KDTreeNodeInfo &rhinfo)
int medianSearch(int low, int high, int treeDepth)
void build(std::vector< KDTreeNodeInfoT< DATA, DIM > > &eltList, const KDTreeBoxT< DIM > &region)
KDTreeNodeT< DATA, DIM > * recBuild(int low, int hight, int depth, const KDTreeBoxT< DIM > &region)
void search(const KDTreeBoxT< DIM > &searchBox, std::vector< KDTreeNodeInfoT< DATA, DIM > > &resRecHitList)
#define nullptr
void addSubtree(const KDTreeNodeT< DATA, DIM > *current)
KDTreeBox region
KDTreeNodeT< DATA, DIM > * nodePool_
KDTreeNodeT< DATA, DIM > * root_
KDTreeNode * right
KDTreeNode * left
void swap(KDTreeNodeInfo &e1, KDTreeNodeInfo &e2)
KDTreeNodeT< DATA, DIM > * getNextNode()
std::vector< std::vector< double > > tmp
Definition: MVATrainer.cc:100
static const char root_[]
void recSearch(const KDTreeNodeT< DATA, DIM > *current, const KDTreeBoxT< DIM > &trackBox)
KDTreeNodeInfo rh