CMS 3D CMS Logo

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
KDTreeLinkerAlgo.h
Go to the documentation of this file.
1 #ifndef KDTreeLinkerAlgoTemplated_h
2 #define KDTreeLinkerAlgoTemplated_h
3 
4 #include "KDTreeLinkerTools.h"
5 
6 #include <cassert>
7 #include <vector>
8 
9 // Class that implements the KDTree partition of 2D space and
10 // a closest point search algorithme.
11 
12 template <typename DATA>
13 class KDTreeLinkerAlgo
14 {
15  public:
17 
18  // Dtor calls clear()
20 
21  // Here we build the KD tree from the "eltList" in the space define by "region".
22  void build(std::vector<KDTreeNodeInfo<DATA> > &eltList,
23  const KDTreeBox &region);
24 
25  // Here we search in the KDTree for all points that would be
26  // contained in the given searchbox. The founded points are stored in resRecHitList.
27  void search(const KDTreeBox &searchBox,
28  std::vector<DATA> &resRecHitList);
29 
30  // This reurns true if the tree is empty
31  bool empty() {return nodePool_.empty();}
32 
33  // This returns the number of nodes + leaves in the tree
34  // (nElements should be (size() +1)/2)
35  int size() { return nodePool_.size();}
36 
37  // This method clears all allocated structures.
38  void clear();
39 
40  private:
41  // The node pool allow us to do just 1 call to new for each tree building.
43 
44  std::vector<DATA> *closestNeighbour;
45  std::vector<KDTreeNodeInfo<DATA> > *initialEltList;
46 
47  private:
48 
49  //Fast median search with Wirth algorithm in eltList between low and high indexes.
50  int medianSearch(int low,
51  int high,
52  int treeDepth);
53 
54  // Recursif kdtree builder. Is called by build()
55  int recBuild(int low,
56  int hight,
57  int depth);
58 
59  // Recursif kdtree search. Is called by search()
60  void recSearch(int current,
61  float dimCurrMin, float dimCurrMax,
62  float dimOtherMin, float dimOtherMax);
63 
64  // This method frees the KDTree.
65  void clearTree();
66 };
67 
68 
69 //Implementation
70 
71 template < typename DATA >
72 void
74  const KDTreeBox &region)
75 {
76  if (eltList.size()) {
77  initialEltList = &eltList;
78 
79  size_t size = initialEltList->size();
80  nodePool_.build(size);
81 
82  // Here we build the KDTree
83  int root = recBuild(0, size, 0);
84  assert(root == 0);
85 
86  initialEltList = 0;
87  }
88 }
89 
90 //Fast median search with Wirth algorithm in eltList between low and high indexes.
91 template < typename DATA >
92 int
94  int high,
95  int treeDepth)
96 {
97  int nbrElts = high - low;
98  int median = (nbrElts & 1) ? nbrElts / 2
99  : nbrElts / 2 - 1;
100  median += low;
101 
102  int l = low;
103  int m = high - 1;
104 
105  while (l < m) {
106  KDTreeNodeInfo<DATA> elt = (*initialEltList)[median];
107  int i = l;
108  int j = m;
109 
110  do {
111  // The even depth is associated to dim1 dimension
112  // The odd one to dim2 dimension
113  if (treeDepth & 1) {
114  while ((*initialEltList)[i].dim[1] < elt.dim[1]) i++;
115  while ((*initialEltList)[j].dim[1] > elt.dim[1]) j--;
116  } else {
117  while ((*initialEltList)[i].dim[0] < elt.dim[0]) i++;
118  while ((*initialEltList)[j].dim[0] > elt.dim[0]) j--;
119  }
120 
121  if (i <= j){
122  std::swap((*initialEltList)[i], (*initialEltList)[j]);
123  i++;
124  j--;
125  }
126  } while (i <= j);
127  if (j < median) l = i;
128  if (i > median) m = j;
129  }
130 
131  return median;
132 }
133 
134 
135 
136 template < typename DATA >
137 void
139  std::vector<DATA> &recHits)
140 {
141  if (!empty()) {
142  closestNeighbour = &recHits;
143  recSearch(0, trackBox.dim1min, trackBox.dim1max, trackBox.dim2min, trackBox.dim2max);
144  closestNeighbour = 0;
145  }
146 }
147 
148 
149 template < typename DATA >
150 void
152  float dimCurrMin, float dimCurrMax,
153  float dimOtherMin, float dimOtherMax)
154 {
155  // Iterate until leaf is found, or there are no children in the
156  // search window. If search has to proceed on both children, proceed
157  // the search to left child via recursion. Swap search window
158  // dimension on alternate levels.
159  while(true) {
160  int right = nodePool_.right[current];
161  if(nodePool_.isLeaf(right)) {
162  float dimCurr = nodePool_.median[current];
163 
164  // If point inside the rectangle/area
165  // Use intentionally bit-wise & instead of logical && for better
166  // performance. It is faster to always do all comparisons than to
167  // allow use of branches to not do some if any of the first ones
168  // is false.
169  if((dimCurr >= dimCurrMin) & (dimCurr <= dimCurrMax)) {
170  float dimOther = nodePool_.dimOther[current];
171  if((dimOther >= dimOtherMin) & (dimOther <= dimOtherMax)) {
172  closestNeighbour->push_back(nodePool_.data[current]);
173  }
174  }
175  break;
176  }
177  else {
178  float median = nodePool_.median[current];
179 
180  bool goLeft = (dimCurrMin <= median);
181  bool goRight = (dimCurrMax >= median);
182 
183  // Swap dimension for the next search level
184  std::swap(dimCurrMin, dimOtherMin);
185  std::swap(dimCurrMax, dimOtherMax);
186  if(goLeft & goRight) {
187  int left = current+1;
188  recSearch(left, dimCurrMin, dimCurrMax, dimOtherMin, dimOtherMax);
189  // continue with right
190  current = right;
191  }
192  else if(goLeft) {
193  ++current;
194  }
195  else if(goRight) {
196  current = right;
197  }
198  else {
199  break;
200  }
201  }
202  }
203 }
204 
205 template <typename DATA>
207 {
208 }
209 
210 template <typename DATA>
212 {
213  clear();
214 }
215 
216 
217 template <typename DATA>
218 void
220 {
221  nodePool_.clear();
222 }
223 
224 template <typename DATA>
225 void
227 {
228  clearTree();
229 }
230 
231 
232 template <typename DATA>
233 int
235  int high,
236  int depth)
237 {
238  int portionSize = high - low;
239  int dimIndex = depth&1;
240 
241  if (portionSize == 1) { // Leaf case
242  int leaf = nodePool_.getNextNode();
243  const KDTreeNodeInfo<DATA>& info = (*initialEltList)[low];
244  nodePool_.right[leaf] = 0;
245  nodePool_.median[leaf] = info.dim[dimIndex]; // dimCurrent
246  nodePool_.dimOther[leaf] = info.dim[1-dimIndex];
247  nodePool_.data[leaf] = info.data;
248  return leaf;
249 
250  } else { // Node case
251 
252  // The even depth is associated to dim1 dimension
253  // The odd one to dim2 dimension
254  int medianId = medianSearch(low, high, depth);
255  float medianVal = (*initialEltList)[medianId].dim[dimIndex];
256 
257  // We create the node
258  int nodeInd = nodePool_.getNextNode();
259  nodePool_.median[nodeInd] = medianVal;
260 
261  ++depth;
262  ++medianId;
263 
264  // We recursively build the son nodes
265  int left = recBuild(low, medianId, depth);
266  assert(nodeInd+1 == left);
267  nodePool_.right[nodeInd] = recBuild(medianId, high, depth);
268 
269  return nodeInd;
270  }
271 }
272 
273 #endif
int i
Definition: DBlmapReader.cc:9
void recSearch(const KDTreeNode *current, const KDTreeBox &trackBox, std::vector< KDTreeNodeInfo > &recHits)
static const TGPicture * info(bool iBackgroundIsBlack)
void build(std::vector< KDTreeNodeInfo > &eltList, const KDTreeBox &region)
assert(m_qm.get())
int medianSearch(std::vector< KDTreeNodeInfo > &eltList, int low, int high, int treeDepth)
std::vector< DATA > * closestNeighbour
std::vector< KDTreeNodeInfo< DATA > > * initialEltList
KDTreeNodes< DATA > nodePool_
void search(const KDTreeBox &searchBox, std::vector< KDTreeNodeInfo > &resRecHitList)
void swap(edm::DataFrameContainer &lhs, edm::DataFrameContainer &rhs)
void clear(CLHEP::HepGenMatrix &m)
Helper function: Reset all elements of a matrix to 0.
Definition: matutil.cc:167
tuple leaf
Definition: Node.py:62
KDTreeNode * recBuild(std::vector< KDTreeNodeInfo > &eltList, int low, int hight, int depth, const KDTreeBox &region)
int j
Definition: DBlmapReader.cc:9
KDTreeNode * nodePool_
tuple size
Write out results.
string root
initialization
Definition: dbtoconf.py:70