Go to the documentation of this file.00001 #include "RecoParticleFlow/PFProducer/interface/KDTreeLinkerAlgo.h"
00002
00003 KDTreeLinkerAlgo::KDTreeLinkerAlgo()
00004 : root_ (0),
00005 nodePool_(0),
00006 nodePoolSize_(-1),
00007 nodePoolPos_(-1)
00008 {
00009 }
00010
00011 KDTreeLinkerAlgo::~KDTreeLinkerAlgo()
00012 {
00013 clear();
00014 }
00015
00016 void
00017 KDTreeLinkerAlgo::build(std::vector<KDTreeNodeInfo> &eltList,
00018 const KDTreeBox ®ion)
00019 {
00020 if (eltList.size()) {
00021 nodePoolSize_ = eltList.size() * 2 - 1;
00022 nodePool_ = new KDTreeNode[nodePoolSize_];
00023
00024
00025 root_ = recBuild(eltList, 0, eltList.size(), 0, region);
00026 }
00027 }
00028
00029
00030 KDTreeNode*
00031 KDTreeLinkerAlgo::recBuild(std::vector<KDTreeNodeInfo> &eltList,
00032 int low,
00033 int high,
00034 int depth,
00035 const KDTreeBox& region)
00036 {
00037 int portionSize = high - low;
00038
00039
00040 assert(portionSize > 0);
00041
00042 if (portionSize == 1) {
00043
00044 KDTreeNode *leaf = getNextNode();
00045 leaf->setAttributs(region, eltList[low]);
00046 return leaf;
00047
00048 } else {
00049
00050
00051
00052 int medianId = medianSearch(eltList, low, high, depth);
00053
00054
00055 KDTreeNode *node = getNextNode();
00056 node->setAttributs(region);
00057
00058
00059
00060 KDTreeBox leftRegion = region;
00061 KDTreeBox rightRegion = region;
00062 if (depth & 1) {
00063
00064 double medianVal = eltList[medianId].dim2;
00065 leftRegion.dim2max = medianVal;
00066 rightRegion.dim2min = medianVal;
00067
00068 } else {
00069
00070 double medianVal = eltList[medianId].dim1;
00071 leftRegion.dim1max = medianVal;
00072 rightRegion.dim1min = medianVal;
00073
00074 }
00075
00076 ++depth;
00077 ++medianId;
00078
00079
00080 node->left = recBuild(eltList, low, medianId, depth, leftRegion);
00081 node->right = recBuild(eltList, medianId, high, depth, rightRegion);
00082
00083 return node;
00084 }
00085 }
00086
00087
00088
00089 int
00090 KDTreeLinkerAlgo::medianSearch(std::vector<KDTreeNodeInfo> &eltList,
00091 int low,
00092 int high,
00093 int treeDepth)
00094 {
00095
00096 assert(low < high);
00097
00098 int nbrElts = high - low;
00099 int median = (nbrElts & 1) ? nbrElts / 2
00100 : nbrElts / 2 - 1;
00101 median += low;
00102
00103 int l = low;
00104 int m = high - 1;
00105
00106 while (l < m) {
00107 KDTreeNodeInfo elt = eltList[median];
00108 int i = l;
00109 int j = m;
00110
00111 do {
00112
00113
00114
00115 if (treeDepth & 1) {
00116 while (eltList[i].dim2 < elt.dim2) i++;
00117 while (eltList[j].dim2 > elt.dim2) j--;
00118 } else {
00119 while (eltList[i].dim1 < elt.dim1) i++;
00120 while (eltList[j].dim1 > elt.dim1) j--;
00121 }
00122
00123 if (i <= j){
00124 swap(eltList[i], eltList[j]);
00125 i++;
00126 j--;
00127 }
00128 } while (i <= j);
00129 if (j < median) l = i;
00130 if (i > median) m = j;
00131 }
00132
00133 return median;
00134 }
00135
00136 void
00137 KDTreeLinkerAlgo::swap(KDTreeNodeInfo &e1,
00138 KDTreeNodeInfo &e2)
00139 {
00140 KDTreeNodeInfo tmp = e1;
00141 e1 = e2;
00142 e2 = tmp;
00143 }
00144
00145 void
00146 KDTreeLinkerAlgo::search(const KDTreeBox &trackBox,
00147 std::vector<KDTreeNodeInfo> &recHits)
00148 {
00149 if (root_)
00150 recSearch(root_, trackBox, recHits);
00151 }
00152
00153 void
00154 KDTreeLinkerAlgo::recSearch(const KDTreeNode *current,
00155 const KDTreeBox &trackBox,
00156 std::vector<KDTreeNodeInfo> &recHits)
00157 {
00158
00159 assert(current != 0);
00160
00161
00162 assert (!(((current->left == 0) && (current->right != 0)) ||
00163 ((current->left != 0) && (current->right == 0))));
00164
00165 if ((current->left == 0) && (current->right == 0)) {
00166
00167
00168 if ((current->rh.dim1 >= trackBox.dim1min) && (current->rh.dim1 <= trackBox.dim1max) &&
00169 (current->rh.dim2 >= trackBox.dim2min) && (current->rh.dim2 <= trackBox.dim2max))
00170 recHits.push_back(current->rh);
00171
00172 } else {
00173
00174
00175 if ((current->left->region.dim1min >= trackBox.dim1min) &&
00176 (current->left->region.dim1max <= trackBox.dim1max) &&
00177 (current->left->region.dim2min >= trackBox.dim2min) &&
00178 (current->left->region.dim2max <= trackBox.dim2max))
00179 addSubtree(current->left, recHits);
00180
00181 else {
00182
00183 if (!((current->left->region.dim1min >= trackBox.dim1max) ||
00184 (current->left->region.dim1max <= trackBox.dim1min) ||
00185 (current->left->region.dim2min >= trackBox.dim2max) ||
00186 (current->left->region.dim2max <= trackBox.dim2min)))
00187 recSearch(current->left, trackBox, recHits);
00188 }
00189
00190
00191 if ((current->right->region.dim1min >= trackBox.dim1min) &&
00192 (current->right->region.dim1max <= trackBox.dim1max) &&
00193 (current->right->region.dim2min >= trackBox.dim2min) &&
00194 (current->right->region.dim2max <= trackBox.dim2max))
00195 addSubtree(current->right, recHits);
00196
00197 else {
00198
00199 if (!((current->right->region.dim1min >= trackBox.dim1max) ||
00200 (current->right->region.dim1max <= trackBox.dim1min) ||
00201 (current->right->region.dim2min >= trackBox.dim2max) ||
00202 (current->right->region.dim2max <= trackBox.dim2min)))
00203 recSearch(current->right, trackBox, recHits);
00204 }
00205 }
00206 }
00207
00208 void
00209 KDTreeLinkerAlgo::addSubtree(const KDTreeNode *current,
00210 std::vector<KDTreeNodeInfo> &recHits)
00211 {
00212
00213 assert(current != 0);
00214
00215 if ((current->left == 0) && (current->right == 0))
00216 recHits.push_back(current->rh);
00217 else {
00218 addSubtree(current->left, recHits);
00219 addSubtree(current->right, recHits);
00220 }
00221 }
00222
00223
00224 void
00225 KDTreeLinkerAlgo::clearTree()
00226 {
00227 delete[] nodePool_;
00228 nodePool_ = 0;
00229 root_ = 0;
00230 nodePoolSize_ = -1;
00231 nodePoolPos_ = -1;
00232 }
00233
00234 void
00235 KDTreeLinkerAlgo::clear()
00236 {
00237 if (root_)
00238 clearTree();
00239 }
00240
00241
00242 KDTreeNode*
00243 KDTreeLinkerAlgo::getNextNode()
00244 {
00245 ++nodePoolPos_;
00246
00247
00248
00249 assert(nodePoolPos_ < nodePoolSize_);
00250
00251 return &(nodePool_[nodePoolPos_]);
00252 }