TKDTree.cxx

Go to the documentation of this file.
00001 // @(#)root/mathcore:$Id: TKDTree.cxx 37573 2010-12-13 16:42:10Z brun $
00002 // Authors: Marian Ivanov and Alexandru Bercuci 04/03/2005
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 #include "TKDTree.h"
00013 #include "TRandom.h"
00014 
00015 #include "TString.h"
00016 #include <string.h>
00017 #include <limits>
00018 
00019 #ifndef R__ALPHA
00020 templateClassImp(TKDTree)
00021 #endif
00022 
00023 
00024 //////////////////////////////////////////////////////////////////////////
00025 //
00026 //                      kd-tree and its implementation in TKDTree
00027 //
00028 // Contents:
00029 // 1. What is kd-tree
00030 // 2. How to cosntruct kdtree - Pseudo code
00031 // 3. Using TKDTree
00032 //    a. Creating the kd-tree and setting the data
00033 //    b. Navigating the kd-tree
00034 // 4. TKDTree implementation - technical details
00035 //    a. The order of nodes in internal arrays
00036 //    b. Division algorithm
00037 //    c. The order of nodes in boundary related arrays
00038 //
00039 //
00040 //
00041 // 1. What is kdtree ? ( http://en.wikipedia.org/wiki/Kd-tree )
00042 //
00043 // In computer science, a kd-tree (short for k-dimensional tree) is a space-partitioning data structure
00044 // for organizing points in a k-dimensional space. kd-trees are a useful data structure for several
00045 // applications, such as searches involving a multidimensional search key (e.g. range searches and
00046 // nearest neighbour searches). kd-trees are a special case of BSP trees.
00047 //
00048 // A kd-tree uses only splitting planes that are perpendicular to one of the coordinate system axes.
00049 // This differs from BSP trees, in which arbitrary splitting planes can be used.
00050 // In addition, in the typical definition every node of a kd-tree, from the root to the leaves, stores a point.
00051 // This differs from BSP trees, in which leaves are typically the only nodes that contain points
00052 // (or other geometric primitives). As a consequence, each splitting plane must go through one of
00053 // the points in the kd-tree. kd-trees are a variant that store data only in leaf nodes.
00054 //
00055 // 2. Constructing a classical kd-tree ( Pseudo code)
00056 //
00057 // Since there are many possible ways to choose axis-aligned splitting planes, there are many different ways
00058 // to construct kd-trees. The canonical method of kd-tree construction has the following constraints:
00059 //
00060 //     * As one moves down the tree, one cycles through the axes used to select the splitting planes.
00061 //      (For example, the root would have an x-aligned plane, the root's children would both have y-aligned
00062 //       planes, the root's grandchildren would all have z-aligned planes, and so on.)
00063 //     * At each step, the point selected to create the splitting plane is the median of the points being
00064 //       put into the kd-tree, with respect to their coordinates in the axis being used. (Note the assumption
00065 //       that we feed the entire set of points into the algorithm up-front.)
00066 //
00067 // This method leads to a balanced kd-tree, in which each leaf node is about the same distance from the root.
00068 // However, balanced trees are not necessarily optimal for all applications.
00069 // The following pseudo-code illustrates this canonical construction procedure (NOTE, that the procedure used
00070 // by the TKDTree class is a bit different, the following pseudo-code is given as a simple illustration of the
00071 // concept):
00072 //
00073 // function kdtree (list of points pointList, int depth)
00074 // {
00075 //     if pointList is empty
00076 //         return nil;
00077 //     else
00078 //     {
00079 //         // Select axis based on depth so that axis cycles through all valid values
00080 //         var int axis := depth mod k;
00081 //
00082 //         // Sort point list and choose median as pivot element
00083 //         select median from pointList;
00084 //
00085 //         // Create node and construct subtrees
00086 //         var tree_node node;
00087 //         node.location := median;
00088 //         node.leftChild := kdtree(points in pointList before median, depth+1);
00089 //         node.rightChild := kdtree(points in pointList after median, depth+1);
00090 //         return node;
00091 //     }
00092 // }
00093 //
00094 // Our construction method is optimized to save memory, and differs a bit from the constraints above.
00095 // In particular, the division axis is chosen as the one with the biggest spread, and the point to create the
00096 // splitting plane is chosen so, that one of the two subtrees contains exactly 2^k terminal nodes and is a
00097 // perfectly balanced binary tree, and, while at the same time, trying to keep the number of terminal nodes
00098 // in the 2 subtrees as close as possible. The following section gives more details about our implementation.
00099 //
00100 // 3. Using TKDTree
00101 //
00102 // 3a. Creating the tree and setting the data
00103 //     The interface of the TKDTree, that allows to set input data, has been developped to simplify using it
00104 //     together with TTree::Draw() functions. That's why the data has to be provided column-wise. For example:
00105 //     {
00106 //     TTree *datatree = ...
00107 //     ...
00108 //     datatree->Draw("x:y:z", "selection", "goff");
00109 //     //now make a kd-tree on the drawn variables
00110 //     TKDTreeID *kdtree = new TKDTreeID(npoints, 3, 1);
00111 //     kdtree->SetData(0, datatree->GetV1());
00112 //     kdtree->SetData(1, datatree->GetV2());
00113 //     kdtree->SetData(2, datatree->GetV3());
00114 //     kdtree->Build();
00115 //     }
00116 //     NOTE, that this implementation of kd-tree doesn't support adding new points after the tree has been built
00117 //     Of course, it's not necessary to use TTree::Draw(). What is important, is to have data columnwise.
00118 //     An example with regular arrays:
00119 //     {
00120 //     Int_t npoints = 100000;
00121 //     Int_t ndim = 3;
00122 //     Int_t bsize = 1;
00123 //     Double_t xmin = -0.5;
00124 //     Double_t xmax = 0.5;
00125 //     Double_t *data0 = new Double_t[npoints];
00126 //     Double_t *data1 = new Double_t[npoints];
00127 //     Double_t *data2 = new Double_t[npoints];
00128 //     Double_t *y     = new Double_t[npoints];
00129 //     for (Int_t i=0; i<npoints; i++){
00130 //        data0[i]=gRandom->Uniform(xmin, xmax);
00131 //        data1[i]=gRandom->Uniform(xmin, xmax);
00132 //        data2[i]=gRandom->Uniform(xmin, xmax);
00133 //     }
00134 //     TKDTreeID *kdtree = new TKDTreeID(npoints, ndim, bsize);
00135 //     kdtree->SetData(0, data0);
00136 //     kdtree->SetData(1, data1);
00137 //     kdtree->SetData(2, data2);
00138 //     kdtree->Build();
00139 //     }
00140 //
00141 //     By default, the kd-tree doesn't own the data and doesn't delete it with itself. If you want the
00142 //     data to be deleted together with the kd-tree, call TKDTree::SetOwner(kTRUE).
00143 //
00144 //     Most functions of the kd-tree don't require the original data to be present after the tree
00145 //     has been built. Check the functions documentation for more details.
00146 //
00147 // 3b. Navigating the kd-tree
00148 //
00149 //     Nodes of the tree are indexed top to bottom, left to right. The root node has index 0. Functions
00150 //     TKDTree::GetLeft(Index inode), TKDTree::GetRight(Index inode) and TKDTree::GetParent(Index inode)
00151 //     allow to find the children and the parent of a given node.
00152 //
00153 //     For a given node, one can find the indexes of the original points, contained in this node,
00154 //     by calling the GetNodePointsIndexes(Index inode) function. Additionally, for terminal nodes,
00155 //     there is a function GetPointsIndexes(Index inode) that returns a pointer to the relevant
00156 //     part of the index array. To find the number of point in the node
00157 //     (not only terminal), call TKDTree::GetNpointsNode(Index inode).
00158 //
00159 // 4.  TKDtree implementation details - internal information, not needed to use the kd-tree.
00160 //     4a. Order of nodes in the node information arrays:
00161 //
00162 // TKDtree is optimized to minimize memory consumption.
00163 // Nodes of the TKDTree do not store pointers to the left and right children or to the parent node,
00164 // but instead there are several 1-d arrays of size fNNodes with information about the nodes.
00165 // The order of the nodes information in the arrays is described below. It's important to understand
00166 // it, if one's class needs to store some kind of additional information on the per node basis, for
00167 // example, the fit function parameters.
00168 //
00169 // Drawback:   Insertion to the TKDtree is not supported.
00170 // Advantage:  Random access is supported
00171 //
00172 // As noted above, the construction of the kd-tree involves choosing the axis and the point on
00173 // that axis to divide the remaining points approximately in half. The exact algorithm for choosing
00174 // the division point is described in the next section. The sequence of divisions is
00175 // recorded in the following arrays:
00176 // fAxix[fNNodes]  - Division axis (0,1,2,3 ...)
00177 // fValue[fNNodes] - Division value
00178 //
00179 // Given the index of a node in those arrays, it's easy to find the indices, corresponding to
00180 // children nodes or the parent node:
00181 // Suppose, the parent node is stored under the index inode. Then:
00182 // Left child index  = inode*2+1
00183 // Right child index =  (inode+1)*2
00184 // Suppose, that the child node is stored under the index inode. Then:
00185 // Parent index = inode/2
00186 //
00187 // Number of division nodes and number of terminals :
00188 // fNNodes = (fNPoints/fBucketSize)
00189 //
00190 // The nodes are filled always from left side to the right side:
00191 // Let inode be the index of a node, and irow - the index of a row
00192 // The TKDTree looks the following way:
00193 // Ideal case:
00194 // Number of _terminal_ nodes = 2^N,  N=3
00195 //
00196 //            INode
00197 // irow 0     0                                                                   -  1 inode
00198 // irow 1     1                              2                                    -  2 inodes
00199 // irow 2     3              4               5               6                    -  4 inodes
00200 // irow 3     7       8      9      10       11     12       13      14           -  8 inodes
00201 //
00202 //
00203 // Non ideal case:
00204 // Number of _terminal_ nodes = 2^N+k,  N=3  k=1
00205 //
00206 //           INode
00207 // irow 0     0                                                                   - 1 inode
00208 // irow 1     1                              2                                    - 2 inodes
00209 // irow 2     3              4               5               6                    - 3 inodes
00210 // irow 3     7       8      9      10       11     12       13      14           - 8 inodes
00211 // irow 4     15  16                                                              - 2 inodes
00212 //
00213 //
00214 // 3b. The division algorithm:
00215 //
00216 // As described above, the kd-tree is built by repeatingly dividing the given set of points into
00217 // 2 smaller sets. The cut is made on the axis with the biggest spread, and the value on the axis,
00218 // on which the cut is performed, is chosen based on the following formula:
00219 // Suppose, we want to divide n nodes into 2 groups, left and right. Then the left and right
00220 // will have the following number of nodes:
00221 //
00222 // n=2^k+rest
00223 //
00224 // Left  = 2^k-1 +  ((rest>2^k-2) ?  2^k-2      : rest)
00225 // Right = 2^k-1 +  ((rest>2^k-2) ?  rest-2^k-2 : 0)
00226 //
00227 // For example, let n_nodes=67. Then, the closest 2^k=64, 2^k-1=32, 2^k-2=16.
00228 // Left node gets 32+3=35 sub-nodes, and the right node gets 32 sub-nodes
00229 //
00230 // The division process continues until all the nodes contain not more than a predefined number
00231 // of points.
00232 //
00233 // 3c. The order of nodes in boundary-related arrays
00234 //
00235 // Some kd-tree based algorithms need to know the boundaries of each node. This information can
00236 // be computed by calling the TKDTree::MakeBoundaries() function. It fills the following arrays:
00237 //
00238 // fRange : array containing the boundaries of the domain:
00239 // | 1st dimension (min + max) | 2nd dimension (min + max) | ...
00240 // fBoundaries : nodes boundaries
00241 // | 1st node {1st dim * 2 elements | 2nd dim * 2 elements | ...} | 2nd node {...} | ...
00242 // The nodes are arranged in the order described in section 3a.
00243 //////////////////////////////////////////////////////////////////////////
00244 
00245 
00246 //_________________________________________________________________
00247 template <typename  Index, typename Value>
00248 TKDTree<Index, Value>::TKDTree() :
00249    TObject()
00250    ,fDataOwner(kFALSE)
00251    ,fNNodes(0)
00252    ,fTotalNodes(0)
00253    ,fNDim(0)
00254    ,fNDimm(0)
00255    ,fNPoints(0)
00256    ,fBucketSize(0)
00257    ,fAxis(0x0)
00258    ,fValue(0x0)
00259    ,fRange(0x0)
00260    ,fData(0x0)
00261    ,fBoundaries(0x0)
00262    ,fIndPoints(0x0)
00263    ,fRowT0(0)
00264    ,fCrossNode(0)
00265    ,fOffset(0)
00266 {
00267 // Default constructor. Nothing is built
00268 }
00269 
00270 template <typename  Index, typename Value>
00271 TKDTree<Index, Value>::TKDTree(Index npoints, Index ndim, UInt_t bsize) :
00272    TObject()
00273    ,fDataOwner(0)
00274    ,fNNodes(0)
00275    ,fTotalNodes(0)
00276    ,fNDim(ndim)
00277    ,fNDimm(2*ndim)
00278    ,fNPoints(npoints)
00279    ,fBucketSize(bsize)
00280    ,fAxis(0x0)
00281    ,fValue(0x0)
00282    ,fRange(0x0)
00283    ,fData(0x0)
00284    ,fBoundaries(0x0)
00285    ,fIndPoints(0x0)
00286    ,fRowT0(0)
00287    ,fCrossNode(0)
00288    ,fOffset(0)
00289 {
00290 // Create the kd-tree of npoints from ndim-dimensional space. Parameter bsize stands for the
00291 // maximal number of points in the terminal nodes (buckets).
00292 // Proceed by calling one of the SetData() functions and then the Build() function
00293 // Note, that updating the tree with new data after the Build() function has been called is
00294 // not possible!
00295 
00296 }
00297 
00298 //_________________________________________________________________
00299 template <typename  Index, typename Value>
00300 TKDTree<Index, Value>::TKDTree(Index npoints, Index ndim, UInt_t bsize, Value **data) :
00301    TObject()
00302    ,fDataOwner(0)
00303    ,fNNodes(0)
00304    ,fTotalNodes(0)
00305    ,fNDim(ndim)
00306    ,fNDimm(2*ndim)
00307    ,fNPoints(npoints)
00308    ,fBucketSize(bsize)
00309    ,fAxis(0x0)
00310    ,fValue(0x0)
00311    ,fRange(0x0)
00312    ,fData(data) //Columnwise!!!!!
00313    ,fBoundaries(0x0)
00314    ,fIndPoints(0x0)
00315    ,fRowT0(0)
00316    ,fCrossNode(0)
00317    ,fOffset(0)
00318 {
00319    // Create a kd-tree from the provided data array. This function only sets the data,
00320    // call Build() to build the tree!!!
00321    // Parameteres:
00322    // - npoints - total number of points. Adding points after the tree is built is not supported
00323    // - ndim    - number of dimensions
00324    // - bsize   - maximal number of points in the terminal nodes
00325    // - data    - the data array
00326    //
00327    // The data should be placed columnwise (like in a TTree).
00328    // The columnwise orientation is chosen to simplify the usage together with TTree::GetV1() like functions.
00329    // An example of filling such an array for a 2d case:
00330    // Double_t **data = new Double_t*[2];
00331    // data[0] = new Double_t[npoints];
00332    // data[1] = new Double_t[npoints];
00333    // for (Int_t i=0; i<npoints; i++){
00334    //    data[0][i]=gRandom->Uniform(-1, 1); //fill the x-coordinate
00335    //    data[1][i]=gRandom->Uniform(-1, 1); //fill the y-coordinate
00336    // }
00337    //
00338    // By default, the kd-tree doesn't own the data. If you want the kd-tree to delete the data array, call
00339    // kdtree->SetOwner(kTRUE).
00340    //
00341 
00342 
00343    //Build();
00344 }
00345 
00346 //_________________________________________________________________
00347 template <typename  Index, typename Value>
00348 TKDTree<Index, Value>::~TKDTree()
00349 {
00350    // Destructor
00351    // By default, the original data is not owned by kd-tree and is not deleted with it.
00352    // If you want to delete the data along with the kd-tree, call SetOwner(kTRUE).
00353 
00354    if (fAxis) delete [] fAxis;
00355    if (fValue) delete [] fValue;
00356    if (fIndPoints) delete [] fIndPoints;
00357    if (fRange) delete [] fRange;
00358    if (fBoundaries) delete [] fBoundaries;
00359    if (fData) {
00360       if (fDataOwner==1){
00361          //the tree owns all the data
00362          for(int idim=0; idim<fNDim; idim++) delete [] fData[idim];
00363       }
00364       if (fDataOwner>0) {
00365          //the tree owns the array of pointers
00366          delete [] fData;
00367       }
00368    }
00369 //   if (fDataOwner && fData){
00370 //      for(int idim=0; idim<fNDim; idim++) delete [] fData[idim];
00371 //      delete [] fData;
00372 //   }
00373 }
00374 
00375 
00376 //_________________________________________________________________
00377 template <typename  Index, typename Value>
00378 void TKDTree<Index, Value>::Build()
00379 {
00380    //
00381    // Build the kd-tree
00382    //
00383    // 1. calculate number of nodes
00384    // 2. calculate first terminal row
00385    // 3. initialize index array
00386    // 4. non recursive building of the binary tree
00387    //
00388    //
00389    // The tree is divided recursively. See class description, section 4b for the details
00390    // of the division alogrithm
00391 
00392    //1.
00393    fNNodes = fNPoints/fBucketSize-1;
00394    if (fNPoints%fBucketSize) fNNodes++;
00395    fTotalNodes = fNNodes + fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);
00396    //2.
00397    fRowT0=0;
00398    for ( ;(fNNodes+1)>(1<<fRowT0);fRowT0++) {}
00399    fRowT0-=1;
00400    //         2 = 2**0 + 1
00401    //         3 = 2**1 + 1
00402    //         4 = 2**1 + 2
00403    //         5 = 2**2 + 1
00404    //         6 = 2**2 + 2
00405    //         7 = 2**2 + 3
00406    //         8 = 2**2 + 4
00407 
00408    //3.
00409    // allocate space for boundaries
00410    fRange = new Value[2*fNDim];
00411    fIndPoints= new Index[fNPoints];
00412    for (Index i=0; i<fNPoints; i++) fIndPoints[i] = i;
00413    fAxis  = new UChar_t[fNNodes];
00414    fValue = new Value[fNNodes];
00415    //
00416    fCrossNode = (1<<(fRowT0+1))-1;
00417    if (fCrossNode<fNNodes) fCrossNode = 2*fCrossNode+1;
00418    //
00419    //  fOffset = (((fNNodes+1)-(1<<fRowT0)))*2;
00420    Int_t   over   = (fNNodes+1)-(1<<fRowT0);
00421    Int_t   filled = ((1<<fRowT0)-over)*fBucketSize;
00422    fOffset = fNPoints-filled;
00423 
00424    //
00425    //   printf("Row0      %d\n", fRowT0);
00426    //   printf("CrossNode %d\n", fCrossNode);
00427    //   printf("Offset    %d\n", fOffset);
00428    //
00429    //
00430    //4.
00431    //    stack for non recursive build - size 128 bytes enough
00432    Int_t rowStack[128];
00433    Int_t nodeStack[128];
00434    Int_t npointStack[128];
00435    Int_t posStack[128];
00436    Int_t currentIndex = 0;
00437    Int_t iter =0;
00438    rowStack[0]    = 0;
00439    nodeStack[0]   = 0;
00440    npointStack[0] = fNPoints;
00441    posStack[0]   = 0;
00442    //
00443    Int_t nbucketsall =0;
00444    while (currentIndex>=0){
00445       iter++;
00446       //
00447       Int_t npoints  = npointStack[currentIndex];
00448       if (npoints<=fBucketSize) {
00449          //printf("terminal node : index %d iter %d\n", currentIndex, iter);
00450          currentIndex--;
00451          nbucketsall++;
00452          continue; // terminal node
00453       }
00454       Int_t crow     = rowStack[currentIndex];
00455       Int_t cpos     = posStack[currentIndex];
00456       Int_t cnode    = nodeStack[currentIndex];
00457       //printf("currentIndex %d npoints %d node %d\n", currentIndex, npoints, cnode);
00458       //
00459       // divide points
00460       Int_t nbuckets0 = npoints/fBucketSize;           //current number of  buckets
00461       if (npoints%fBucketSize) nbuckets0++;            //
00462       Int_t restRows = fRowT0-rowStack[currentIndex];  // rest of fully occupied node row
00463       if (restRows<0) restRows =0;
00464       for (;nbuckets0>(2<<restRows); restRows++) {}
00465       Int_t nfull = 1<<restRows;
00466       Int_t nrest = nbuckets0-nfull;
00467       Int_t nleft =0, nright =0;
00468       //
00469       if (nrest>(nfull/2)){
00470          nleft  = nfull*fBucketSize;
00471          nright = npoints-nleft;
00472       }else{
00473          nright = nfull*fBucketSize/2;
00474          nleft  = npoints-nright;
00475       }
00476 
00477       //
00478       //find the axis with biggest spread
00479       Value maxspread=0;
00480       Value tempspread, min, max;
00481       Index axspread=0;
00482       Value *array;
00483       for (Int_t idim=0; idim<fNDim; idim++){
00484          array = fData[idim];
00485          Spread(npoints, array, fIndPoints+cpos, min, max);
00486          tempspread = max - min;
00487          if (maxspread < tempspread) {
00488             maxspread=tempspread;
00489             axspread = idim;
00490          }
00491          if(cnode) continue;
00492          //printf("set %d %6.3f %6.3f\n", idim, min, max);
00493          fRange[2*idim] = min; fRange[2*idim+1] = max;
00494       }
00495       array = fData[axspread];
00496       KOrdStat(npoints, array, nleft, fIndPoints+cpos);
00497       fAxis[cnode]  = axspread;
00498       fValue[cnode] = array[fIndPoints[cpos+nleft]];
00499       //printf("Set node %d : ax %d val %f\n", cnode, node->fAxis, node->fValue);
00500       //
00501       //
00502       npointStack[currentIndex] = nleft;
00503       rowStack[currentIndex]    = crow+1;
00504       posStack[currentIndex]    = cpos;
00505       nodeStack[currentIndex]   = cnode*2+1;
00506       currentIndex++;
00507       npointStack[currentIndex] = nright;
00508       rowStack[currentIndex]    = crow+1;
00509       posStack[currentIndex]    = cpos+nleft;
00510       nodeStack[currentIndex]   = (cnode*2)+2;
00511       //
00512       if (0){
00513          // consistency check
00514          Info("Build()", "%s", Form("points %d left %d right %d", npoints, nleft, nright));
00515          if (nleft<nright) Warning("Build", "Problem Left-Right");
00516          if (nleft<0 || nright<0) Warning("Build()", "Problem Negative number");
00517       }
00518    }
00519 }
00520 
00521 //_________________________________________________________________
00522 template <typename  Index, typename Value>
00523 void TKDTree<Index, Value>::FindNearestNeighbors(const Value *point, const Int_t kNN, Index *ind, Value *dist)
00524 {
00525    //Find kNN nearest neighbors to the point in the first argument
00526    //Returns 1 on success, 0 on failure
00527    //Arrays ind and dist are provided by the user and are assumed to be at least kNN elements long
00528 
00529 
00530    if (!ind || !dist) {
00531       Error("FindNearestNeighbors", "Working arrays must be allocated by the user!");
00532       return;
00533    }
00534    for (Int_t i=0; i<kNN; i++){
00535       dist[i]=std::numeric_limits<Value>::max();
00536       ind[i]=-1;
00537    }
00538    MakeBoundariesExact();
00539    UpdateNearestNeighbors(0, point, kNN, ind, dist);
00540 
00541 }
00542 
00543 //_________________________________________________________________
00544 template <typename Index, typename Value>
00545 void TKDTree<Index, Value>::UpdateNearestNeighbors(Index inode, const Value *point, Int_t kNN, Index *ind, Value *dist)
00546 {
00547    //Update the nearest neighbors values by examining the node inode
00548 
00549    Value min=0;
00550    Value max=0;
00551    DistanceToNode(point, inode, min, max);
00552    if (min > dist[kNN-1]){
00553       //there are no closer points in this node
00554       return;
00555    }
00556    if (IsTerminal(inode)) {
00557       //examine points one by one
00558       Index f1, l1, f2, l2;
00559       GetNodePointsIndexes(inode, f1, l1, f2, l2);
00560       for (Int_t ipoint=f1; ipoint<=l1; ipoint++){
00561          Double_t d = Distance(point, fIndPoints[ipoint]);
00562          if (d<dist[kNN-1]){
00563             //found a closer point
00564             Int_t ishift=0;
00565             while(ishift<kNN && d>dist[ishift])
00566                ishift++;
00567             //replace the neighbor #ishift with the found point
00568             //and shift the rest 1 index value to the right
00569             for (Int_t i=kNN-1; i>ishift; i--){
00570                dist[i]=dist[i-1];
00571                ind[i]=ind[i-1];
00572             }
00573             dist[ishift]=d;
00574             ind[ishift]=fIndPoints[ipoint];
00575          }
00576       }
00577       return;
00578    }
00579    if (point[fAxis[inode]]<fValue[inode]){
00580       //first examine the node that contains the point
00581       UpdateNearestNeighbors(GetLeft(inode), point, kNN, ind, dist);
00582       UpdateNearestNeighbors(GetRight(inode), point, kNN, ind, dist);
00583    } else {
00584       UpdateNearestNeighbors(GetRight(inode), point, kNN, ind, dist);
00585       UpdateNearestNeighbors(GetLeft(inode), point, kNN, ind, dist);
00586    }
00587 }
00588 
00589 //_________________________________________________________________
00590 template <typename Index, typename Value>
00591 Double_t TKDTree<Index, Value>::Distance(const Value *point, Index ind, Int_t type) const
00592 {
00593 //Find the distance between point of the first argument and the point at index value ind
00594 //Type argument specifies the metric: type=2 - L2 metric, type=1 - L1 metric
00595 
00596    Double_t dist = 0;
00597    if (type==2){
00598       for (Int_t idim=0; idim<fNDim; idim++){
00599          dist+=(point[idim]-fData[idim][ind])*(point[idim]-fData[idim][ind]);
00600       }
00601       return TMath::Sqrt(dist);
00602    } else {
00603       for (Int_t idim=0; idim<fNDim; idim++){
00604          dist+=TMath::Abs(point[idim]-fData[idim][ind]);
00605       }
00606 
00607       return dist;
00608    }
00609    return -1;
00610 
00611 }
00612 
00613 //_________________________________________________________________
00614 template <typename Index, typename Value>
00615 void TKDTree<Index, Value>::DistanceToNode(const Value *point, Index inode, Value &min, Value &max, Int_t type)
00616 {
00617 //Find the minimal and maximal distance from a given point to a given node.
00618 //Type argument specifies the metric: type=2 - L2 metric, type=1 - L1 metric
00619 //If the point is inside the node, both min and max are set to 0.
00620 
00621    Value *bound = GetBoundaryExact(inode);
00622    min = 0;
00623    max = 0;
00624    Double_t dist1, dist2;
00625 
00626    if (type==2){
00627       for (Int_t idim=0; idim<fNDimm; idim+=2){
00628          dist1 = (point[idim/2]-bound[idim])*(point[idim/2]-bound[idim]);
00629          dist2 = (point[idim/2]-bound[idim+1])*(point[idim/2]-bound[idim+1]);
00630          //min+=TMath::Min(dist1, dist2);
00631          if (point[idim/2]<bound[idim] || point[idim/2]>bound[idim+1])
00632             min+= (dist1>dist2)? dist2 : dist1;
00633          // max+=TMath::Max(dist1, dist2);
00634          max+= (dist1>dist2)? dist1 : dist2;
00635       }
00636       min = TMath::Sqrt(min);
00637       max = TMath::Sqrt(max);
00638    } else {
00639       for (Int_t idim=0; idim<fNDimm; idim+=2){
00640          dist1 = TMath::Abs(point[idim/2]-bound[idim]);
00641          dist2 = TMath::Abs(point[idim/2]-bound[idim+1]);
00642          //min+=TMath::Min(dist1, dist2);
00643          min+= (dist1>dist2)? dist2 : dist1;
00644          // max+=TMath::Max(dist1, dist2);
00645          max+= (dist1>dist2)? dist1 : dist2;
00646       }
00647    }
00648 }
00649 
00650 //_________________________________________________________________
00651 template <typename  Index, typename Value>
00652 Index TKDTree<Index, Value>::FindNode(const Value * point) const
00653 {
00654    // returns the index of the terminal node to which point belongs
00655    // (index in the fAxis, fValue, etc arrays)
00656    // returns -1 in case of failure
00657 
00658    Index stackNode[128], inode;
00659    Int_t currentIndex =0;
00660    stackNode[0] = 0;
00661    while (currentIndex>=0){
00662       inode    = stackNode[currentIndex];
00663       if (IsTerminal(inode)) return inode;
00664 
00665       currentIndex--;
00666       if (point[fAxis[inode]]<=fValue[inode]){
00667          currentIndex++;
00668          stackNode[currentIndex]=(inode<<1)+1; //GetLeft()
00669       }
00670       if (point[fAxis[inode]]>=fValue[inode]){
00671          currentIndex++;
00672          stackNode[currentIndex]=(inode+1)<<1; //GetRight()
00673       }
00674    }
00675 
00676    return -1;
00677 }
00678 
00679 
00680 
00681 //_________________________________________________________________
00682 template <typename  Index, typename Value>
00683 void TKDTree<Index, Value>::FindPoint(Value * point, Index &index, Int_t &iter){
00684   //
00685   // find the index of point
00686   // works only if we keep fData pointers
00687 
00688   Int_t stackNode[128];
00689   Int_t currentIndex =0;
00690   stackNode[0] = 0;
00691   iter =0;
00692   //
00693   while (currentIndex>=0){
00694     iter++;
00695     Int_t inode    = stackNode[currentIndex];
00696     currentIndex--;
00697     if (IsTerminal(inode)){
00698       // investigate terminal node
00699       Int_t indexIP  = (inode >= fCrossNode) ? (inode-fCrossNode)*fBucketSize : (inode-fNNodes)*fBucketSize+fOffset;
00700       printf("terminal %d indexP %d\n", inode, indexIP);
00701       for (Int_t ibucket=0;ibucket<fBucketSize;ibucket++){
00702         Bool_t isOK    = kTRUE;
00703         indexIP+=ibucket;
00704         printf("ibucket %d index %d\n", ibucket, indexIP);
00705         if (indexIP>=fNPoints) continue;
00706         Int_t index0   = fIndPoints[indexIP];
00707         for (Int_t idim=0;idim<fNDim;idim++) if (fData[idim][index0]!=point[idim]) isOK = kFALSE;
00708         if (isOK) index = index0;
00709       }
00710       continue;
00711     }
00712 
00713     if (point[fAxis[inode]]<=fValue[inode]){
00714       currentIndex++;
00715       stackNode[currentIndex]=(inode*2)+1;
00716     }
00717     if (point[fAxis[inode]]>=fValue[inode]){
00718       currentIndex++;
00719       stackNode[currentIndex]=(inode*2)+2;
00720     }
00721   }
00722   //
00723   //  printf("Iter\t%d\n",iter);
00724 }
00725 
00726 //_________________________________________________________________
00727 template <typename  Index, typename Value>
00728 void TKDTree<Index, Value>::FindInRange(Value * point, Value range, std::vector<Index> &res)
00729 {
00730 //Find all points in the sphere of a given radius "range" around the given point
00731 //1st argument - the point
00732 //2nd argument - radius of the shere
00733 //3rd argument - a vector, in which the results will be returned
00734 
00735    MakeBoundariesExact();
00736    UpdateRange(0, point, range, res);
00737 }
00738 
00739 //_________________________________________________________________
00740 template <typename  Index, typename Value>
00741 void TKDTree<Index, Value>::UpdateRange(Index inode, Value* point, Value range, std::vector<Index> &res)
00742 {
00743 //Internal recursive function with the implementation of range searches
00744 
00745    Value min, max;
00746    DistanceToNode(point, inode, min, max);
00747    if (min>range) {
00748       //all points of this node are outside the range
00749       return;
00750    }
00751    if (max<range && max>0) {
00752       //all points of this node are inside the range
00753 
00754       Index f1, l1, f2, l2;
00755       GetNodePointsIndexes(inode, f1, l1, f2, l2);
00756 
00757       for (Int_t ipoint=f1; ipoint<=l1; ipoint++){
00758          res.push_back(fIndPoints[ipoint]);
00759       }
00760       for (Int_t ipoint=f2; ipoint<=l2; ipoint++){
00761          res.push_back(fIndPoints[ipoint]);
00762       }
00763       return;
00764    }
00765 
00766    //this node intersects with the range
00767    if (IsTerminal(inode)){
00768       //examine the points one by one
00769       Index f1, l1, f2, l2;
00770       Double_t d;
00771       GetNodePointsIndexes(inode, f1, l1, f2, l2);
00772       for (Int_t ipoint=f1; ipoint<=l1; ipoint++){
00773          d = Distance(point, fIndPoints[ipoint]);
00774          if (d <= range){
00775             res.push_back(fIndPoints[ipoint]);
00776          }
00777       }
00778       return;
00779    }
00780    if (point[fAxis[inode]]<=fValue[inode]){
00781       //first examine the node that contains the point
00782       UpdateRange(GetLeft(inode),point, range, res);
00783       UpdateRange(GetRight(inode),point, range, res);
00784    } else {
00785       UpdateRange(GetLeft(inode),point, range, res);
00786       UpdateRange(GetRight(inode),point, range, res);
00787    }
00788 }
00789 
00790 //_________________________________________________________________
00791 template <typename Index, typename Value>
00792 Index*  TKDTree<Index, Value>::GetPointsIndexes(Int_t node) const
00793 {
00794    //return the indices of the points in that terminal node
00795    //for all the nodes except last, the size is fBucketSize
00796    //for the last node it's fOffset%fBucketSize
00797 
00798    if (!IsTerminal(node)){
00799       printf("GetPointsIndexes() only for terminal nodes, use GetNodePointsIndexes() instead\n");
00800       return 0;
00801    }
00802    Int_t offset = (node >= fCrossNode) ? (node-fCrossNode)*fBucketSize : fOffset+(node-fNNodes)*fBucketSize;
00803    return &fIndPoints[offset];
00804 }
00805 
00806 //_________________________________________________________________
00807 template <typename Index, typename Value>
00808 void  TKDTree<Index, Value>::GetNodePointsIndexes(Int_t node, Int_t &first1, Int_t &last1, Int_t &first2, Int_t &last2) const
00809 {
00810    //Return the indices of points in that node
00811    //Indices are returned as the first and last value of the part of indices array, that belong to this node
00812    //Sometimes points are in 2 intervals, then the first and last value for the second one are returned in
00813    //third and fourth parameter, otherwise first2 is set to 0 and last2 is set to -1
00814    //To iterate over all the points of the node #inode, one can do, for example:
00815    //Index *indices = kdtree->GetPointsIndexes();
00816    //Int_t first1, last1, first2, last2;
00817    //kdtree->GetPointsIndexes(inode, first1, last1, first2, last2);
00818    //for (Int_t ipoint=first1; ipoint<=last1; ipoint++){
00819    //   point = indices[ipoint];
00820    //   //do something with point;
00821    //}
00822    //for (Int_t ipoint=first2; ipoint<=last2; ipoint++){
00823    //   point = indices[ipoint];
00824    //   //do something with point;
00825    //}
00826 
00827 
00828    if (IsTerminal(node)){
00829       //the first point in the node is computed by the following formula:
00830       Index offset = (node >= fCrossNode) ? (node-fCrossNode)*fBucketSize : fOffset+(node-fNNodes)*fBucketSize;
00831       first1 = offset;
00832       last1 = offset + GetNPointsNode(node)-1;
00833       first2 = 0;
00834       last2 = -1;
00835       return;
00836    }
00837 
00838    Index firsttermnode = fNNodes;
00839    Index ileft = node;
00840    Index iright = node;
00841    Index f1, l1, f2, l2;
00842 //this is the left-most node
00843    while (ileft<firsttermnode)
00844       ileft = GetLeft(ileft);
00845 //this is the right-most node
00846    while (iright<firsttermnode)
00847       iright = GetRight(iright);
00848 
00849    if (ileft>iright){
00850 //      first1 = firsttermnode;
00851 //      last1 = iright;
00852 //      first2 = ileft;
00853 //      last2 = fTotalNodes-1;
00854       GetNodePointsIndexes(firsttermnode, f1, l1, f2, l2);
00855       first1 = f1;
00856       GetNodePointsIndexes(iright, f1, l1, f2, l2);
00857       last1 = l1;
00858       GetNodePointsIndexes(ileft, f1, l1, f2, l2);
00859       first2 = f1;
00860       GetNodePointsIndexes(fTotalNodes-1, f1, l1, f2, l2);
00861       last2 = l1;
00862 
00863    }  else {
00864       GetNodePointsIndexes(ileft, f1, l1, f2, l2);
00865       first1 = f1;
00866       GetNodePointsIndexes(iright, f1, l1, f2, l2);
00867       last1 = l1;
00868       first2 = 0;
00869       last2 = -1;
00870    }
00871 }
00872 
00873 //_________________________________________________________________
00874 template <typename Index, typename Value>
00875 Index TKDTree<Index, Value>::GetNPointsNode(Int_t inode) const
00876 {
00877    //Get number of points in this node
00878    //for all the terminal nodes except last, the size is fBucketSize
00879    //for the last node it's fOffset%fBucketSize, or if fOffset%fBucketSize==0, it's also fBucketSize
00880 
00881    if (IsTerminal(inode)){
00882 
00883       if (inode!=fTotalNodes-1) return fBucketSize;
00884       else {
00885          if (fOffset%fBucketSize==0) return fBucketSize;
00886          else return fOffset%fBucketSize;
00887       }
00888    }
00889 
00890    Int_t f1, l1, f2, l2;
00891    GetNodePointsIndexes(inode, f1, l1, f2, l2);
00892    Int_t sum = l1-f1+1;
00893    sum += l2-f2+1;
00894    return sum;
00895 }
00896 
00897 
00898 //_________________________________________________________________
00899 template <typename  Index, typename Value>
00900 void TKDTree<Index, Value>::SetData(Index npoints, Index ndim, UInt_t bsize, Value **data)
00901 {
00902 // Set the data array. See the constructor function comments for details
00903 
00904 // TO DO
00905 //
00906 // Check reconstruction/reallocation of memory of data. Maybe it is not
00907 // necessary to delete and realocate space but only to use the same space
00908 
00909    Clear();
00910 
00911    //Columnwise!!!!
00912    fData = data;
00913    fNPoints = npoints;
00914    fNDim = ndim;
00915    fBucketSize = bsize;
00916 
00917    Build();
00918 }
00919 
00920 //_________________________________________________________________
00921 template <typename  Index, typename Value>
00922 Int_t TKDTree<Index, Value>::SetData(Index idim, Value *data)
00923 {
00924    //Set the coordinate #ndim of all points (the column #ndim of the data matrix)
00925    //After setting all the data columns, proceed by calling Build() function
00926    //Note, that calling this function after Build() is not possible
00927    //Note also, that no checks on the array sizes is performed anywhere
00928 
00929    if (fAxis || fValue) {
00930       Error("SetData", "The tree has already been built, no updates possible");
00931       return 0;
00932    }
00933 
00934    if (!fData) {
00935       fData = new Value*[fNDim];
00936    }
00937    fData[idim]=data;
00938    fDataOwner = 2;
00939    return 1;
00940 }
00941 
00942 
00943 //_________________________________________________________________
00944 template <typename  Index, typename Value>
00945 void TKDTree<Index, Value>::Spread(Index ntotal, Value *a, Index *index, Value &min, Value &max) const
00946 {
00947    //Calculate spread of the array a
00948 
00949    Index i;
00950    min = a[index[0]];
00951    max = a[index[0]];
00952    for (i=0; i<ntotal; i++){
00953       if (a[index[i]]<min) min = a[index[i]];
00954       if (a[index[i]]>max) max = a[index[i]];
00955    }
00956 }
00957 
00958 
00959 //_________________________________________________________________
00960 template <typename  Index, typename Value>
00961 Value TKDTree<Index, Value>::KOrdStat(Index ntotal, Value *a, Index k, Index *index) const
00962 {
00963    //
00964    //copy of the TMath::KOrdStat because I need an Index work array
00965 
00966    Index i, ir, j, l, mid;
00967    Index arr;
00968    Index temp;
00969 
00970    Index rk = k;
00971    l=0;
00972    ir = ntotal-1;
00973    for(;;) {
00974       if (ir<=l+1) { //active partition contains 1 or 2 elements
00975          if (ir == l+1 && a[index[ir]]<a[index[l]])
00976          {temp = index[l]; index[l]=index[ir]; index[ir]=temp;}
00977          Value tmp = a[index[rk]];
00978          return tmp;
00979       } else {
00980          mid = (l+ir) >> 1; //choose median of left, center and right
00981          {temp = index[mid]; index[mid]=index[l+1]; index[l+1]=temp;}//elements as partitioning element arr.
00982           if (a[index[l]]>a[index[ir]])  //also rearrange so that a[l]<=a[l+1]
00983           {temp = index[l]; index[l]=index[ir]; index[ir]=temp;}
00984 
00985           if (a[index[l+1]]>a[index[ir]])
00986           {temp=index[l+1]; index[l+1]=index[ir]; index[ir]=temp;}
00987 
00988           if (a[index[l]]>a[index[l+1]])
00989           {temp = index[l]; index[l]=index[l+1]; index[l+1]=temp;}
00990 
00991           i=l+1;        //initialize pointers for partitioning
00992           j=ir;
00993           arr = index[l+1];
00994           for (;;) {
00995              do i++; while (a[index[i]]<a[arr]);
00996              do j--; while (a[index[j]]>a[arr]);
00997              if (j<i) break;  //pointers crossed, partitioning complete
00998              {temp=index[i]; index[i]=index[j]; index[j]=temp;}
00999           }
01000           index[l+1]=index[j];
01001           index[j]=arr;
01002           if (j>=rk) ir = j-1; //keep active the partition that
01003           if (j<=rk) l=i;      //contains the k_th element
01004       }
01005    }
01006 }
01007 
01008 //_________________________________________________________________
01009 template <typename Index, typename Value>
01010 void TKDTree<Index, Value>::MakeBoundaries(Value *range)
01011 {
01012 // Build boundaries for each node. Note, that the boundaries here are built
01013 // based on the splitting planes of the kd-tree, and don't necessarily pass
01014 // through the points of the original dataset. For the latter functionality
01015 // see function MakeBoundariesExact()
01016 // Boundaries can be retrieved by calling GetBoundary(inode) function that would
01017 // return an array of boundaries for the specified node, or GetBoundaries() function
01018 // that would return the complete array.
01019 
01020 
01021    if(range) memcpy(fRange, range, fNDimm*sizeof(Value));
01022    // total number of nodes including terminal nodes
01023    Int_t totNodes = fNNodes + fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);
01024    fBoundaries = new Value[totNodes*fNDimm];
01025    //Info("MakeBoundaries(Value*)", Form("Allocate boundaries for %d nodes", totNodes));
01026 
01027 
01028    // loop
01029    Value *tbounds = 0x0, *cbounds = 0x0;
01030    Int_t cn;
01031    for(int inode=fNNodes-1; inode>=0; inode--){
01032       tbounds = &fBoundaries[inode*fNDimm];
01033       memcpy(tbounds, fRange, fNDimm*sizeof(Value));
01034 
01035       // check left child node
01036       cn = (inode<<1)+1;
01037       if(IsTerminal(cn)) CookBoundaries(inode, kTRUE);
01038       cbounds = &fBoundaries[fNDimm*cn];
01039       for(int idim=0; idim<fNDim; idim++) tbounds[idim<<1] = cbounds[idim<<1];
01040 
01041       // check right child node
01042       cn = (inode+1)<<1;
01043       if(IsTerminal(cn)) CookBoundaries(inode, kFALSE);
01044       cbounds = &fBoundaries[fNDimm*cn];
01045       for(int idim=0; idim<fNDim; idim++) tbounds[(idim<<1)+1] = cbounds[(idim<<1)+1];
01046    }
01047 }
01048 
01049 //_________________________________________________________________
01050 template <typename Index, typename Value>
01051 void TKDTree<Index, Value>::CookBoundaries(const Int_t node, Bool_t LEFT)
01052 {
01053    // define index of this terminal node
01054    Int_t index = (node<<1) + (LEFT ? 1 : 2);
01055    //Info("CookBoundaries()", Form("Node %d", index));
01056 
01057    // build and initialize boundaries for this node
01058    Value *tbounds = &fBoundaries[fNDimm*index];
01059    memcpy(tbounds, fRange, fNDimm*sizeof(Value));
01060    Bool_t flag[256];  // cope with up to 128 dimensions
01061    memset(flag, kFALSE, fNDimm);
01062    Int_t nvals = 0;
01063 
01064    // recurse parent nodes
01065    Int_t pn = node;
01066    while(pn >= 0 && nvals < fNDimm){
01067       if(LEFT){
01068          index = (fAxis[pn]<<1)+1;
01069          if(!flag[index]) {
01070             tbounds[index] = fValue[pn];
01071             flag[index] = kTRUE;
01072             nvals++;
01073          }
01074       } else {
01075          index = fAxis[pn]<<1;
01076          if(!flag[index]) {
01077             tbounds[index] = fValue[pn];
01078             flag[index] = kTRUE;
01079             nvals++;
01080          }
01081       }
01082       LEFT = pn&1;
01083       pn =  (pn - 1)>>1;
01084    }
01085 }
01086 
01087 //______________________________________________________________________
01088 template <typename Index, typename Value>
01089 void TKDTree<Index, Value>::MakeBoundariesExact()
01090 {
01091 // Build boundaries for each node. Unlike MakeBoundaries() function
01092 // the boundaries built here always pass through a point of the original dataset
01093 // So, for example, for a terminal node with just one point minimum and maximum for each
01094 // dimension are the same.
01095 // Boundaries can be retrieved by calling GetBoundaryExact(inode) function that would
01096 // return an array of boundaries for the specified node, or GetBoundaries() function
01097 // that would return the complete array.
01098 
01099 
01100    // total number of nodes including terminal nodes
01101    //Int_t totNodes = fNNodes + fNPoints/fBucketSize + ((fNPoints%fBucketSize)?1:0);
01102    if (fBoundaries){
01103       //boundaries were already computed for this tree
01104       return;
01105    }
01106    fBoundaries = new Value[fTotalNodes*fNDimm];
01107    Value *min = new Value[fNDim];
01108    Value *max = new Value[fNDim];
01109    for (Index inode=fNNodes; inode<fTotalNodes; inode++){
01110       //go through the terminal nodes
01111       for (Index idim=0; idim<fNDim; idim++){
01112          min[idim]= std::numeric_limits<Value>::max();
01113          max[idim]=-std::numeric_limits<Value>::max();
01114       }
01115       Index *points = GetPointsIndexes(inode);
01116       Index npoints = GetNPointsNode(inode);
01117       //find max and min in each dimension
01118       for (Index ipoint=0; ipoint<npoints; ipoint++){
01119          for (Index idim=0; idim<fNDim; idim++){
01120             if (fData[idim][points[ipoint]]<min[idim])
01121                min[idim]=fData[idim][points[ipoint]];
01122             if (fData[idim][points[ipoint]]>max[idim])
01123                max[idim]=fData[idim][points[ipoint]];
01124          }
01125       }
01126       for (Index idim=0; idim<fNDimm; idim+=2){
01127          fBoundaries[inode*fNDimm + idim]=min[idim/2];
01128          fBoundaries[inode*fNDimm + idim+1]=max[idim/2];
01129       }
01130    }
01131 
01132    delete [] min; 
01133    delete [] max; 
01134 
01135    Index left, right;
01136    for (Index inode=fNNodes-1; inode>=0; inode--){
01137       //take the min and max of left and right
01138       left = GetLeft(inode)*fNDimm;
01139       right = GetRight(inode)*fNDimm;
01140       for (Index idim=0; idim<fNDimm; idim+=2){
01141          //take the minimum on each dimension
01142          fBoundaries[inode*fNDimm+idim]=TMath::Min(fBoundaries[left+idim], fBoundaries[right+idim]);
01143          //take the maximum on each dimension
01144          fBoundaries[inode*fNDimm+idim+1]=TMath::Max(fBoundaries[left+idim+1], fBoundaries[right+idim+1]);
01145 
01146       }
01147    }
01148 }
01149 
01150 //_________________________________________________________________
01151 template <typename  Index, typename Value>
01152    void TKDTree<Index, Value>::FindBNodeA(Value *point, Value *delta, Int_t &inode){
01153    //
01154    // find the smallest node covering the full range - start
01155    //
01156    inode =0;
01157    for (;inode<fNNodes;){
01158       if (TMath::Abs(point[fAxis[inode]] - fValue[inode])<delta[fAxis[inode]]) break;
01159       inode = (point[fAxis[inode]] < fValue[inode]) ? (inode*2)+1: (inode*2)+2;
01160    }
01161 }
01162 
01163 //_________________________________________________________________
01164 template <typename  Index, typename Value>
01165    Value* TKDTree<Index, Value>::GetBoundaries()
01166 {
01167    // Get the boundaries
01168    if(!fBoundaries) MakeBoundaries();
01169    return fBoundaries;
01170 }
01171 
01172 
01173 //_________________________________________________________________
01174 template <typename  Index, typename Value>
01175    Value* TKDTree<Index, Value>::GetBoundariesExact()
01176 {
01177    // Get the boundaries
01178    if(!fBoundaries) MakeBoundariesExact();
01179    return fBoundaries;
01180 }
01181 
01182 //_________________________________________________________________
01183 template <typename  Index, typename Value>
01184    Value* TKDTree<Index, Value>::GetBoundary(const Int_t node)
01185 {
01186    // Get a boundary
01187    if(!fBoundaries) MakeBoundaries();
01188    return &fBoundaries[node*2*fNDim];
01189 }
01190 
01191 //_________________________________________________________________
01192 template <typename  Index, typename Value>
01193 Value* TKDTree<Index, Value>::GetBoundaryExact(const Int_t node)
01194 {
01195    // Get a boundary
01196    if(!fBoundaries) MakeBoundariesExact();
01197    return &fBoundaries[node*2*fNDim];
01198 }
01199 
01200 
01201 //______________________________________________________________________
01202 TKDTreeIF *TKDTreeTestBuild(const Int_t npoints, const Int_t bsize){
01203    //
01204    // Example function to
01205    //
01206    Float_t *data0 =  new Float_t[npoints*2];
01207    Float_t *data[2];
01208    data[0] = &data0[0];
01209    data[1] = &data0[npoints];
01210    for (Int_t i=0;i<npoints;i++) {
01211       data[1][i]= gRandom->Rndm();
01212       data[0][i]= gRandom->Rndm();
01213    }
01214    TKDTree<Int_t, Float_t> *kdtree = new TKDTreeIF(npoints, 2, bsize, data);
01215    return kdtree;
01216 }
01217 
01218 
01219 
01220 template class TKDTree<Int_t, Float_t>;
01221 template class TKDTree<Int_t, Double_t>;

Generated on Tue Jul 5 14:34:27 2011 for ROOT_528-00b_version by  doxygen 1.5.1