LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiKdTree.h

00001 /*
00002  * Copyright (C) 2003, 2004, 2005, 2006
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  * This file is part of the LTI-Computer Vision Library (LTI-Lib)
00006  *
00007  * The LTI-Lib is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License (LGPL)
00009  * as published by the Free Software Foundation; either version 2.1 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * The LTI-Lib is distributed in the hope that it will be
00013  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
00014  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with the LTI-Lib; see the file LICENSE.  If
00019  * not, write to the Free Software Foundation, Inc., 59 Temple Place -
00020  * Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 
00024 /*--------------------------------------------------------------------
00025  * project ....: LTI-Lib: Image Processing and Computer Vision Library
00026  * file .......: ltiKdTree.h
00027  * authors ....: Frederik Lange, Pablo Alvarado, Jens Rietzschel
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 9.1.2003
00030  * revisions ..: $Id: ltiKdTree.h,v 1.29 2006/02/08 12:28:23 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_KD_TREE_H_
00034 #define _LTI_KD_TREE_H_
00035 
00036 #include "ltiMathObject.h"
00037 #include "ltiMath.h"
00038 #include "ltiQuickMedian.h"
00039 #include "ltiL2Distance.h"
00040 #include "ltiSTLIoInterface.h"
00041 #include "ltiTypeInfo.h"
00042 
00043 #include <list>
00044 #include <map>
00045 
00046 namespace lti {
00047 
00048   /**
00049    * A class for k-d tree.
00050    *
00051    * A k-d tree is a generalization of the simple binary tree used for
00052    * sorting and searching.  At each level of the tree, a
00053    * n-dimensional subspace is split in two subspaces at a given
00054    * dimension.  The leaves of the tree contain a "bucket" of data
00055    * within the described subspace.
00056    *
00057    * You can consider data for building with the add() method. Then
00058    * you can either build() the tree from that data, discarding the
00059    * old data, or rebuild() the tree, which will then contain the data
00060    * added since the last call to build() or rebuild() plus the newly
00061    * added data.
00062    *
00063    * This type allows to search in an efficient way for the
00064    * more similar neighbors of a given point.
00065    *
00066    * The type T describes a point in an n-dimensional space.  Usually,
00067    * you will use vector<float> or vector<double>, but types like
00068    * rgbPixel, trgbPixel<float>, tpoint<float> are also supported.
00069    * The type T MUST provide following methods/operators:
00070 
00071    * - copy %operator=()
00072    * - access operator[]()
00073    * - size() method
00074    * - must define the type <code>value_type</code>, which describes the 
00075    *   type of each element in the container.
00076    * - comparison %operator==()
00077    *
00078    * (lti::vector, lti::tpoint, lti::tpoint3D, lti::trgbpixel and 
00079    * lti::rgbPixel provide this interface)
00080    *
00081    * The type D describes the data contained at each node, which is per default
00082    * just an integer value.  It must provide following methods/operators
00083    * - copy operator=()
00084    *
00085    * The type U specifies a "distantor" policy, i.e. it specifies the
00086    * distance to be used while computing the nearest neighbors.  If
00087    * not given, the default value will be l2SquareDistantor, which
00088    * provides, as the name says, the square of the euclidian distance.
00089    * Only Minkowski distances are allowed.  If you need your own
00090    * distance measure you can create your policy following the
00091    * interfaces of one of the classes lti::l2Distantor,
00092    * lti::l1Distantor or l2SquareDistantor.
00093    *
00094    * \Note: Elements added to the tree after a call to build() or
00095    * rebuild() are not saved when calling write().
00096    *
00097    * The original kd-Tree algorithm for k-neareast neighbors problems was
00098    * introduced in:
00099    * Friedman, J.H., Bentley, J.L. and Finkel, R.A.  An Algorithm for Finding
00100    *     Best Matches in Logarithmic Expected Time. ACM Transaction on
00101    *     Mathematical Software, Vol. 3, No. 3, September 1977, Pages 209-225
00102    *
00103    * @ingroup gAggregate
00104    */
00105   template <class T,class D=int,class U=l2SquareDistantor<T> >
00106   class kdTree : public mathObject, public status {
00107   public:
00108     /**
00109      * Value type at each dimension of the space
00110      */
00111     typedef typename T::value_type value_type;
00112 
00113     /**
00114      * Type used to accumulate data of value_type elements
00115      */
00116     typedef typename typeInfo<value_type>::accumulation_type acc_type;
00117 
00118     /**
00119      * At the leave nodes, a list of elements of this type will contain
00120      * the points and their corresponding data.
00121      *
00122      * Implementation must be here due to MS VC++ bug
00123      */
00124     class element : public ioObject {
00125     public:
00126 
00127       /**
00128        * n-dimensional point representing the position of this element
00129        * in the n-dimensional space
00130        */
00131       T point;
00132 
00133       /**
00134        * data contained in this element.
00135        */
00136       D data;
00137 
00138       /**
00139        * Constructor
00140        */
00141       element() : ioObject(),point(T()),data(D()) {
00142       };
00143 
00144       /**
00145        * Constructor
00146        *
00147        * @param pos n-dimensional vector position of this element
00148        * @param dat data contained in this element
00149        */
00150       element(const T& pos, const D& dat)
00151         : ioObject(),point(pos),data(dat) {
00152       };
00153 
00154       /**
00155        * Copy constructor
00156        */
00157       element(const element& other) 
00158         : ioObject(),point(other.point),data(other.data) {
00159       };
00160 
00161       /**
00162        * destructor
00163        */
00164       ~element() {
00165       };
00166 
00167       /**
00168        * shortcut to access the point value at each dimension
00169        */
00170       inline value_type& operator[](const int a) {return point[a];}
00171 
00172       /**
00173        * shortcut to access the point value at each dimension
00174        */
00175       inline const value_type& operator[](const int a) const {return point[a];}
00176 
00177       /**
00178        * shortcut to access the size of the points stored
00179        */
00180       inline int size() const {
00181         return point.size();
00182       }
00183       
00184       /**
00185        * copy method
00186        */
00187       element& copy(const element& other) {
00188         point=other.point;
00189         data=other.data;
00190         return *this;
00191       }
00192 
00193       /**
00194        * copy operator
00195        */
00196       inline element& operator=(const element& other) {
00197         return copy(other);
00198       }
00199 
00200       /**
00201        * clone member
00202        */
00203       element* clone() const {
00204         return new element(*this);
00205       }
00206 
00207 #     ifndef _LTI_MSC_6
00208       /**
00209        * read the parameters from the given ioHandler
00210        * @param handler the ioHandler to be used
00211        * @param complete if true (the default) the enclosing begin/end will
00212        *        be also read, otherwise only the data block will be read.
00213        * @return true if write was successful
00214        */
00215       virtual bool read(ioHandler &handler, const bool complete=true)
00216 #     else
00217       bool readMS(ioHandler& handler,const bool complete=true)
00218 #     endif
00219       {
00220         bool b=true;
00221 
00222         if (complete) {
00223           b = handler.readBegin();
00224         }
00225 
00226         b = b && lti::read(handler,point);
00227         b = b && handler.readDataSeparator();
00228         b = b && lti::read(handler,data);
00229 
00230         if (complete) {
00231           b= b && handler.readEnd();
00232         }
00233 
00234         return b;
00235       }
00236 
00237 #     ifdef _LTI_MSC_6
00238       /**
00239        * read the parameters from the given ioHandler
00240        * @param handler the ioHandler to be used
00241        * @param complete if true (the default) the enclosing begin/end will
00242        *        be also read, otherwise only the data block will be read.
00243        * @return true if write was successful
00244        */
00245       virtual bool read(ioHandler& handler,const bool complete=true) {
00246         // ...we need this workaround to cope with another really awful MSVC
00247         // bug.
00248         return readMS(handler,complete);
00249       }
00250 #     endif
00251 
00252 #     ifndef _LTI_MSC_6
00253       /**
00254        * write the parameters in the given ioHandler
00255        * @param handler the ioHandler to be used
00256        * @param complete if true (the default) the enclosing begin/end will
00257        *        be also written, otherwise only the data block will be
00258        *        written.
00259        * @return true if write was successful
00260        */
00261       virtual bool write(ioHandler& handler,const bool complete=true) const
00262 #     else
00263       bool writeMS(ioHandler& handler,const bool complete=true) const
00264 #     endif
00265       {
00266         bool b=true;
00267 
00268         if (complete) {
00269           b = handler.writeBegin();
00270         }
00271 
00272         b = b && lti::write(handler,point);
00273         b = b && handler.writeDataSeparator();
00274         b = b && lti::write(handler,data);
00275 
00276         if (complete) {
00277           b= b && handler.writeEnd();
00278         }
00279 
00280         return b;
00281       }
00282 
00283 #     ifdef _LTI_MSC_6
00284       /**
00285        * write the parameters to the given ioHandler
00286        * @param handler the ioHandler to be used
00287        * @param complete if true (the default) the enclosing begin/end will
00288        *        be also writen, otherwise only the data block will be writen.
00289        * @return true if write was successful
00290        */
00291       virtual bool write(ioHandler& handler,const bool complete=true) {
00292         // ...we need this workaround to cope with another really awful MSVC
00293         // bug.
00294         return writeMS(handler,complete);
00295       }
00296 #     endif
00297     };
00298 
00299     /**
00300      * Class of nodes of the kd-tree
00301      *
00302      * Implementation must be here due to MS VC++ bug
00303      */
00304     class node : public ioObject {
00305       // the enclosing class is a friend of mine.
00306       friend class kdTree<T,D,U>;
00307     public:
00308 
00309       /**
00310        * type used for the container of elements.
00311        * A std::vector is for the search much more appropriate because
00312        * the access through iterators is about a factor 5 faster than the
00313        * std::list type.
00314        */
00315       typedef std::vector<element*> points_type;
00316 
00317       /**
00318        * @name Attributes
00319        */
00320       //@{
00321       /**
00322        * Points stored in this node.  These are pointers to the data
00323        * allocated in the kdTree class, this way the data can be
00324        * "transfered" more efficiently between different nodes.  The
00325        * memory managment is done by this node.
00326        */
00327       points_type points;
00328 
00329       /**
00330        *  the left subtree (lower coordinate) from the split plane
00331        */
00332       node* left;
00333 
00334       /**
00335        *  the right subtree (higher coordinate) from the split plane
00336        */
00337       node* right;
00338 
00339       /**
00340        * the dimension in which the subnodes are split.  This is
00341        * called in the original paper "discriminator"
00342        */
00343       int splitDim;
00344 
00345       /**
00346        * Value at the split dimension where the splitting takes place.
00347        * Usually this value corresponds to the median at the given
00348        * split dimension.
00349        *
00350        */
00351       value_type partition;
00352       //@}
00353 
00354       /**
00355        * constructor
00356        */
00357       node() 
00358         : ioObject(),points(),left(0),right(0),splitDim(0),
00359           partition(value_type()) {
00360       };
00361 
00362       /**
00363        * copy constructor.
00364        * Makes a deep copy, i.e. the pointers will be different
00365        */
00366       node(const node& other) 
00367         : ioObject(),points(),left(0),right(0) {
00368         copy(other);
00369       }
00370 
00371       /**
00372        * destructor
00373        */
00374       ~node() {
00375         clearPoints();
00376 
00377         if(left!=0) {
00378           delete left;
00379           left=0;
00380         }
00381         if(right!=0) {
00382           delete right;
00383           right=0;
00384         }
00385       };
00386 
00387       /**
00388        * insert a pointer to an element into the points list.  
00389        *
00390        * The pointed element will be inserted as is (without copying), and
00391        * the memory managment is controled by the node itself.
00392        *
00393        * The dimensionality of each element MUST be equal than the one
00394        * of the first element added.
00395        */
00396       void add(element* f) {
00397         points.push_back(f);
00398       }
00399 
00400       /**
00401        * return true if this node is a leaf.
00402        */
00403       inline bool isLeaf() const {
00404         return (!points.empty()); 
00405       }
00406 
00407       /**
00408        * copy method
00409        */
00410       node& copy(const node& other) {
00411 
00412         // copy the data
00413         splitDim = other.splitDim;
00414         partition = other.partition;
00415 
00416         // remove the current elements
00417         clearPoints();
00418 
00419         // deep copy the other elements
00420         typename points_type::const_iterator cit,ceit;
00421         for (cit=other.points.begin(),ceit=other.points.end();
00422              cit!=ceit;
00423              ++cit) {
00424           points.push_back((*cit)->clone());
00425         }
00426         
00427         // remove old data
00428         if (notNull(left)) {
00429           delete left;
00430           left = 0;
00431         }
00432 
00433         if (notNull(right)) {
00434           delete right;
00435           right = 0;
00436         }
00437 
00438         // copy children if necessary.
00439         if (notNull(other.left)) {
00440           left = other.left->clone();
00441         }
00442 
00443         if (notNull(other.right)) {
00444           right = other.right->clone();
00445         }
00446 
00447         return *this;
00448       }
00449 
00450       /**
00451        * copy method
00452        */
00453       inline node& operator=(const node& other) {
00454         return copy(other);
00455       }
00456 
00457 
00458       /**
00459        * clone method
00460        */
00461       node* clone() const {
00462         return new node(*this);
00463       }
00464 
00465 #     ifndef _LTI_MSC_6
00466       /**
00467        * read the parameters from the given ioHandler
00468        * @param handler the ioHandler to be used
00469        * @param complete if true (the default) the enclosing begin/end will
00470        *        be also read, otherwise only the data block will be read.
00471        * @return true if write was successful
00472        */
00473       virtual bool read(ioHandler &handler, const bool complete=true)
00474 #     else
00475       bool readMS(ioHandler& handler,const bool complete=true)
00476 #     endif
00477       {
00478         bool b=true;
00479 
00480         delete left;
00481         left = 0;
00482         delete right;
00483         right = 0;
00484 
00485         if (complete) {
00486           b = handler.readBegin();
00487         }
00488 
00489         b = b && lti::read(handler,"splitDim",splitDim);
00490         b = b && lti::read(handler,"partition",partition);
00491         
00492         // read the points with their corresponding data
00493         clearPoints();
00494 
00495         // -----------------------------------------------------
00496 
00497         b = b && handler.readBegin();              // points field (1)
00498         b = b && handler.trySymbol("points");      //
00499         b = b && handler.readKeyValueSeparator();  //
00500         b = b && handler.readBegin();              // vector data  (2)
00501 
00502         // -----------------------------
00503         int i;
00504         element* tmpElem;
00505         int pointsSize;
00506         b = b && handler.read("size",pointsSize);
00507 
00508         points.resize(pointsSize);
00509 
00510         b = b && handler.readBegin(); // data block of vector      (3)
00511         if (pointsSize > 0) {
00512           for (i=0;i<pointsSize-1;++i) {
00513             tmpElem = new element;
00514             b = b && tmpElem->read(handler);
00515             points[i] = tmpElem;
00516             tmpElem=0;
00517             b = b && handler.readDataSeparator();
00518           }
00519           tmpElem = new element;
00520           b = b && tmpElem->read(handler);
00521           points[i] = tmpElem;
00522           tmpElem=0;
00523         }
00524         b = b && handler.readEnd();   // data block of vector      (2)
00525         
00526         // -----------------------------
00527 
00528         b = b && handler.readEnd(); // vector data                 (1)
00529         b = b && handler.readEnd(); // points field                (0)
00530 
00531         // -----------------------------------------------------
00532         
00533 
00534         // load the children
00535 
00536 
00537         // left node first
00538         b = b && handler.readBegin();              // left scope  (1)
00539         b = b && handler.trySymbol("left");        //
00540         b = b && handler.readKeyValueSeparator();  //
00541         b = b && handler.readBegin();              // left data   (2)
00542                                                    //
00543         if (!handler.tryEnd()) {                   // 
00544           left = new node;                         //
00545           // recursively read the children         //
00546           b = b && left->read(handler,false);      //
00547           b = b && handler.readEnd();              // left data   (1)
00548         }                                          //
00549                                                    //
00550         b = b && handler.readEnd();                // left scope  (0)
00551 
00552         // right node next
00553         b = b && handler.readBegin();              // right scope (1)
00554         b = b && handler.trySymbol("right");       //
00555         b = b && handler.readKeyValueSeparator();  //
00556         b = b && handler.readBegin();              // right data  (2)
00557                                                    //
00558         if (!handler.tryEnd()) {                   // 
00559           right = new node();                      //
00560           // recursively read the children         //
00561           b = b && right->read(handler,false);     //
00562           b = b && handler.readEnd();              // right data  (1)
00563         }                                          //
00564                                                    //
00565         b = b && handler.readEnd();                // right scope (0)
00566 
00567         if (complete) {
00568           b = b && handler.readEnd();
00569         }
00570 
00571         return b;
00572       }
00573 
00574 #     ifdef _LTI_MSC_6
00575       /**
00576        * read the parameters from the given ioHandler
00577        * @param handler the ioHandler to be used
00578        * @param complete if true (the default) the enclosing begin/end will
00579        *        be also read, otherwise only the data block will be read.
00580        * @return true if write was successful
00581        */
00582       virtual bool read(ioHandler& handler,const bool complete=true) {
00583         // ...we need this workaround to cope with another really awful MSVC
00584         // bug.
00585         return readMS(handler,complete);
00586       }
00587 #     endif
00588 
00589 #     ifndef _LTI_MSC_6
00590       /**
00591        * write the parameters in the given ioHandler
00592        * @param handler the ioHandler to be used
00593        * @param complete if true (the default) the enclosing begin/end will
00594        *        be also written, otherwise only the data block will be
00595        *        written.
00596        * @return true if write was successful
00597        */
00598       virtual bool write(ioHandler& handler,const bool complete=true) const
00599 #     else
00600       bool writeMS(ioHandler& handler,const bool complete=true) const
00601 #     endif
00602       {
00603         bool b=true;
00604 
00605         if (complete) {
00606           b = handler.writeBegin();
00607         }
00608 
00609         b = b && lti::write(handler,"splitDim",splitDim);
00610         b = b && lti::write(handler,"partition",partition);
00611         
00612         // write from the points only the index
00613         // -------------------------------------------------------
00614 
00615         b = b && handler.writeBegin();             // points field
00616         b = b && handler.writeSymbol("points");    //
00617         b = b && handler.writeKeyValueSeparator(); //
00618                                                    //
00619         b = b && handler.writeBegin();             // vector data
00620 
00621         // ------------------------------------------
00622         b = b && handler.write("size",static_cast<unsigned int>(points.size()));
00623         b = b && handler.writeBegin(); // data block of vector
00624         if (!points.empty()) {                     //      |
00625           typename points_type::const_iterator it; //      |
00626           it=points.begin();                       //      |
00627           b = b && (*it)->write(handler);          //      |
00628           for (++it;it!=points.end();++it) {       //      |
00629             b = b && handler.writeDataSeparator(); //      |
00630             b = b && (*it)->write(handler);        //      |
00631           }                                        //      |
00632         }                                          //      |
00633         b = b && handler.writeEnd();   // data block of vector
00634         
00635         // -------------------------------------------
00636 
00637         b = b && handler.writeEnd(); // vector data
00638         b = b && handler.writeEnd(); // points field
00639 
00640         // -------------------------------------------------------
00641 
00642         b = b && handler.writeEOL();  
00643         
00644         // Save the children
00645 
00646         // left node first
00647         b = b && handler.writeBegin();             // left child   (1)
00648         b = b && handler.writeSymbol("left");      //
00649         b = b && handler.writeKeyValueSeparator(); //
00650         b = b && handler.writeBegin();             // node block   (2)
00651         if (notNull(left)) {                       //
00652           // recursivelly save the children        // 
00653           b = b && left->write(handler,false);     //
00654         }                                          //
00655         b = b && handler.writeEnd();               // node block   (1)
00656         b = b && handler.writeEnd();               // left child   (0)
00657         b = b && handler.writeEOL();  
00658         
00659         // right node next
00660         b = b && handler.writeBegin();             // right child  (1)
00661         b = b && handler.writeSymbol("right");     //
00662         b = b && handler.writeKeyValueSeparator(); //
00663         b = b && handler.writeBegin();             // node block   (2)
00664         if (notNull(right)) {                      //
00665           // recursivelly save the children        //
00666           b = b && right->write(handler,false);    //
00667         }                                          //
00668         b = b && handler.writeEnd();               // node block   (1)
00669         b = b && handler.writeEnd();               // right child  (0)
00670 
00671         b = b && handler.writeEOL();
00672 
00673         if (complete) {
00674           b=b && handler.writeEnd();
00675         }
00676 
00677         return b;
00678       }
00679 
00680 #     ifdef _LTI_MSC_6
00681       /**
00682        * write the parameters to the given ioHandler
00683        * @param handler the ioHandler to be used
00684        * @param complete if true (the default) the enclosing begin/end will
00685        *        be also writen, otherwise only the data block will be writen.
00686        * @return true if write was successful
00687        */
00688       virtual bool write(ioHandler& handler,const bool complete=true) {
00689         // ...we need this workaround to cope with another really awful MSVC
00690         // bug.
00691         return writeMS(handler,complete);
00692       }
00693 #     endif
00694 
00695 
00696     protected:
00697       /**
00698        * deep clear points
00699        */
00700       void clearPoints() {
00701         // delete the elements
00702         typename points_type::iterator it,eit;
00703         for (it=points.begin(),eit=points.end();it!=eit;++it) {
00704           delete (*it);
00705           (*it)=0;
00706         }
00707 
00708         points.clear();
00709       }
00710 
00711       /**
00712        * split the data stored at this node considering the axis with
00713        * the highest variance.
00714        *
00715        * @param maxCount maximum bucket size (how many elements are allowed
00716        *                 to be in a leaf node)
00717        * @param levels number of levels required until now for this tree.
00718        * @param leaves at the end this variable (which should be initialized
00719        *        with zero externally) contains the number of leaves in the tree
00720        */
00721       void subdivide(const int maxCount,int& levels,int& leaves) {
00722         const int n = static_cast<int>(points.size());
00723         if (n <= maxCount) {
00724           // we don't need to split.  This now is small enough
00725           leaves++;
00726           levels=1;
00727           return;
00728         }
00729 
00730         // remove the old children and create empty ones.
00731         if (notNull(left)) {
00732           delete left;
00733           left = 0;
00734         }
00735         left = new node();
00736 
00737         if (notNull(right)) {
00738           delete right;
00739           right = 0;
00740         }
00741         right = new node();      
00742 
00743         // split dimension at this node
00744         // remember split dimension (splitDim is a class attribute)
00745         const int dim = splitDim = getDimWithHighestVariance();
00746 
00747         // get the median of the splitDim as the value to split the space
00748         // remember split position
00749         const value_type medVal = partition = getMedianVal(dim);
00750 
00751         const int lc = n/2;
00752         int npleft(0),npeq(0); // number of points in the left side
00753         typename points_type::iterator it=points.begin();
00754         std::list<element*> stack;
00755         // split the points into the two children. 
00756         while (it!=points.end()) {
00757           if (((*it)->point[dim] < medVal)) {
00758             left->add(*it);
00759             npleft++;
00760           } else if (((*it)->point[dim] > medVal)) {
00761             right->add(*it);
00762           } else {
00763             npeq++;
00764             stack.push_back(*it);
00765           }
00766           ++it;
00767         }
00768 
00769         // the remaining median-equal values need to be split so
00770         // that both children have the same number of points
00771         while (npleft<lc) {
00772           left->add(stack.front());
00773           stack.pop_front();
00774           npleft++;
00775         }
00776         if (!stack.empty()) {
00777           right->add(stack);
00778         }
00779         
00780         points.clear();
00781 
00782         // recursively split the data into both child nodes
00783         int llev,rlev;
00784         left->subdivide(maxCount,llev,leaves);
00785         right->subdivide(maxCount,rlev,leaves);
00786         levels = 1+max(llev,rlev);
00787       }
00788 
00789       /**
00790        * get the dimension of the data with the highest variance.
00791        * We assume the whole data set to be considered is located
00792        * at the points vector.
00793        */
00794       int getDimWithHighestVariance() const {
00795         assert(!points.empty() && notNull(points.front()));
00796 
00797         // get the used dimension
00798         const int dim = points.front()->size();
00799 
00800         assert(dim>0);
00801         
00802         // total number of points
00803         const int n = static_cast<int>(points.size());
00804 
00805         // type for squares
00806         typedef typename typeInfo<value_type>::square_accumulation_type
00807           sqrType;
00808 
00809         // sum of all elements
00810         vector<sqrType> sum(dim,sqrType(0));
00811         // variance
00812         vector<sqrType> var(dim,sqrType(0));
00813 
00814         typename points_type::const_iterator it;
00815         int mxi,j;
00816         sqrType tmp,mx;
00817 
00818         // compute some temporary variables with the sum of elements and
00819         // the sum of square of elements
00820         for (it=points.begin();it!=points.end();++it) {
00821           // we cannot just add the points, because we don't really know
00822           // the type.  So let's add the elements separately
00823           for (j=0;j<dim;++j) {
00824             tmp=(*(*it))[j];
00825             sum[j]+=tmp;
00826             var[j]+=(tmp*tmp);
00827           }
00828         }
00829 
00830         // compute not the variance, but m x variance, to save some time,
00831         // and get the dimension where the maximal one is found
00832         mxi=0;
00833         tmp=sum[mxi];
00834         mx = var[mxi]-(tmp*tmp/n); // the first "variance" for dimension 0
00835         for (j=1;j<dim;++j) {      // the rest of "variances"
00836           tmp = sum[j];
00837           tmp = var[j]-(tmp*tmp/n);
00838           if (tmp>mx) {            // if greater
00839             mxi=j;                 // remember it.
00840             mx=tmp;
00841           }
00842         }
00843 
00844         return mxi;
00845       }
00846 
00847       /**
00848        * get the median value at the given search dimension
00849        *
00850        * @param searchDim search dimension
00851        * @return the median of the given dimension
00852        */
00853       value_type getMedianVal(const int searchDim) const {
00854         int i;
00855         const int n = static_cast<int>(points.size());
00856 
00857         vector<value_type> val(false,n); // don't initialize
00858 
00859         // get elements in the split dimension
00860         typename points_type::const_iterator it;
00861         for (i=0,it=points.begin(); it!=points.end();++it,++i) {
00862           val[i] = (*(*it))[searchDim];
00863         }
00864 
00865         // the quickMedian functor can be created just once and const,
00866         // because we don't need to change the parameters and the required
00867         // apply is const.  Even multi-thread applications would use different
00868         // stack-frames, and should work. (This should be tested!!!)
00869         static const quickMedian<value_type> qmed;
00870 
00871         // get the median of desired dimension
00872         return qmed.apply(val);
00873       }
00874 
00875       /**
00876        * search for exactly the given key in the list of elements.  If
00877        * found, return true, otherwise return false and leave the
00878        * element instance untouched.
00879        * 
00880        * For floating types this method usually returns false, because
00881        * the exact match of the key is very unprobable.  This method is
00882        * therefore used mostly for integer value_types 
00883        */
00884       bool getPoint(const T& key,element& elem) const {
00885         if (!points.empty()) {
00886           typename points_type::const_iterator it,eit;
00887           for (it=points.begin(),eit=points.end();it!=eit;++it) {
00888             if ((*it)->point == key) {
00889               elem=*(*it);
00890               return true;
00891             }
00892           }
00893         }
00894         return false;
00895       }
00896 
00897       /**
00898        * search for exactly the given key in the list of elements.  If
00899        * found, return true, otherwise return false and leave the
00900        * element instance untouched.
00901        * 
00902        * For floating types this method usually returns false, because
00903        * the exact match of the key is very unprobable.  This method is
00904        * therefore used mostly for integer value_types 
00905        */
00906       bool getPoint(const T& key,std::list<element>& elems) const {
00907         bool found=false;
00908         if (!points.empty()) {
00909           typename points_type::const_iterator it,eit;
00910           for (it=points.begin(),eit=points.end();it!=eit;++it) {
00911             if ((*it)->point == key) {
00912               elems.push_back(*(*it));
00913               found=true;
00914             }
00915           }
00916         }
00917         return found;
00918       }
00919 
00920       /**
00921        * insert all elements in the given list into the internal
00922        * elements vector.
00923        *
00924        * The pointed elements will be inserted as they are (without copying),
00925        * and the memory managment is controled by this node itself.
00926        *
00927        * The dimensionality of each element MUST be equal than the one
00928        * of the first added element.
00929        */
00930       void add(std::list<element*>& pts) {
00931         typename std::list<element*>::iterator it=pts.begin();
00932         while (it!=pts.end()) {
00933           points.push_back(*it);
00934           ++it;
00935         }
00936       }
00937 
00938     };  // end of node class
00939   
00940     // ----------------------------------------------------------------------
00941     // kdTree Definition
00942     // ----------------------------------------------------------------------
00943 
00944   public:
00945 
00946     /**
00947      * Return type of the size() member
00948      */
00949     typedef int size_type;
00950 
00951     /**
00952      * Default constructor
00953      */
00954     kdTree();
00955 
00956     /**
00957      * Copy constructor
00958      * @param other the object to be copied
00959      */
00960     kdTree(const kdTree& other);
00961 
00962     /**
00963      * Destructor
00964      */
00965     virtual ~kdTree();
00966 
00967     /**
00968      * Returns the name of this type ("kdTree")
00969      */
00970     virtual const char* getTypeName() const;
00971 
00972     /**
00973      * Copy data of "other" functor.
00974      * @param other the functor to be copied
00975      * @return a reference to this functor object
00976      */
00977     kdTree& copy(const kdTree& other);
00978 
00979     /**
00980      * Alias for copy member
00981      * @param other the functor to be copied
00982      * @return a reference to this functor object
00983      */
00984     kdTree& operator=(const kdTree& other);
00985 
00986     /**
00987      * Returns a pointer to a clone of this functor.
00988      */
00989     virtual mathObject* clone() const;
00990 
00991     /**
00992      * Clear the tree.
00993      *
00994      * All elements belonging to the tree will be removed.  Also all elements
00995      * added until now will be deleted.
00996      */
00997     virtual void clear();
00998 
00999     /**
01000      * Check if the tree is empty
01001      */
01002     virtual bool empty() const;
01003 
01004     /**
01005      * Get the number of elements added to the tree with the function add().
01006      *
01007      * Note that these points are not really \b in the tree until you
01008      * call build() or rebuild(). After calling either the added
01009      * points are flushed and the return value of this function is
01010      * zero.
01011      *
01012      * @see size()
01013      */
01014     virtual int getNumberOfAddedElements() const;
01015 
01016     /**
01017      * Get the number of elements in the built tree.
01018      *
01019      * Note that this value can differ substantially from the value
01020      * returned by getNumberOfAddedElements(). The latter don't belong
01021      * to the tree yet. Thus, adding elements, then calling build and
01022      * then adding more elements, generally results in two different
01023      * values.
01024      *
01025      * The return value is zero if no tree has been built yet.
01026      *
01027      * @see getNumberOfAddedElements()
01028      */
01029     virtual int size() const;
01030 
01031     /**
01032      * Get the number of leaves in the tree.
01033      *
01034      * Return zero if the tree hasn't been build yet.
01035      */
01036     virtual int getNumberOfLeaves() const;
01037 
01038     /**
01039      * Get the number of levels of the tree.
01040      *
01041      * Return zero if the tree hasn't been build yet.
01042      */
01043     virtual int getLevels() const;
01044 
01045     /**
01046      * Get pointer to root node
01047      *
01048      * Return a null pointer if the tree hasn't been build yet.
01049      */
01050     virtual node* getRoot();
01051 
01052     /**
01053      * @name Search methods
01054      */
01055     //@{
01056 
01057     /**
01058      * Search for an element with exactly the given position in the
01059      * hyperspace.
01060      *
01061      * This is the classical search in a kd-tree, that assumes that 
01062      * a leaf node contains exactly the given point.
01063      * If found, the contents of the element will by copied in the 
01064      * elem attributes and true will be returned.   Otherwise false will
01065      * be returned.
01066      *
01067      * If the key is present more than once, only the "first" one will
01068      * be returned, which is the first one the list of points at the
01069      * left-most node containing it.
01070      *
01071      * @param key point in the n-dimensional space you are looking for.
01072      * @param elem the contents of the found point will be left here.
01073      * @return true if key was found, otherwise false.
01074      */
01075     bool searchExactly(const T& key,element& elem) const;
01076 
01077     /**
01078      * Search for all elements with exactly the given position in the
01079      * hyperspace.
01080      *
01081      * This is the classical search in a kd-tree, that assumes that 
01082      * a leaf node contains exactly the given point.
01083      * If found, the contents of the element will by copied in the 
01084      * elem attributes and true will be returned.   Otherwise false will
01085      * be returned.
01086      *
01087      * @param key point in the n-dimensional space you are looking for.
01088      * @param elems a list containing copies to all found elements with the
01089      *              given keys
01090      * @return true if at least one key was found, otherwise false.
01091      */
01092     bool searchExactly(const T& key,std::list<element>& elems) const;
01093 
01094     /**
01095      * Search for the nearest element in the tree to the given key point.
01096      *
01097      * If found, a pointer to the element will be written in the 
01098      * \a elem parameters and true will be returned.   Otherwise false will
01099      * be returned and the pointer will be set to zero.
01100      *
01101      * The pointer is not const to allow you to change the \a data of the
01102      * element, but if you also change the \a point, the tree will be corrupted
01103      * and will not work appropriately.  There is no way to change the search
01104      * keys dynamically in a kd-tree without a heavy load of computation.  If
01105      * that is what you are looking for, you should consider rebuilding the
01106      * entire tree (expensive!).
01107      *
01108      * @param key point in the n-dimensional space you are looking for.
01109      * @param elem pointer to the contents of the point found, or zero if
01110      *             not found.  You should \b never delete the pointed data.
01111      * @return true if key was found, otherwise false (i.e. tree empty).
01112      *
01113      * \warning This method is not thread safe.  In order to provide a
01114      *          fast search mechanism for the nearest neighbor some
01115      *          temporary variables are stored in the tree class itself,
01116      *          and therefore it is not possible to search the
01117      *          nearest neighbor in the same tree from different
01118      *          threads.
01119      */
01120     bool searchNearest(const T& key,element*& elem) const;
01121 
01122     /**
01123      * Search for the nearest element in the tree to the given key point.
01124      *
01125      * If found, a pointer to the element will be written in the 
01126      * \a elem parameters and true will be returned.   Otherwise false will
01127      * be returned and the pointer will be set to zero.
01128      *
01129      * The pointer is not const to allow you to change the \a data of the
01130      * element, but if you also change the \a point the tree will be corrupted
01131      * and will not work appropriately.  There is no way to change the search
01132      * keys dynamically in a kd-tree without a heavy load of computation.  If
01133      * that is what you are looking for, you should consider rebuilding the
01134      * entire tree (expensive!).
01135      *
01136      * @param key point in the n-dimensional space you are looking for.
01137      * @param elem pointer to the contents of the point found, or zero if
01138      *             not found.  You should \b never delete the pointed data.
01139      * @param dist distance between the points.  The type of distance is 
01140      *             determined by the used distanctor (the third template
01141      *             type of the tree, which return per default the square
01142      *             of the euclidean distance).
01143      * @return true if key was found, otherwise false (i.e. tree empty).
01144      *
01145      * \warning This method is not thread safe.  In order to provide a
01146      *          fast search mechanism for the nearest neighbor some
01147      *          temporary variables are stored in the tree class itself,
01148      *          and therefore it is not possible to search the
01149      *          nearest neighbor in the same tree from different
01150      *          threads.
01151      */
01152     bool searchNearest(const T& key,element*& elem,acc_type& dist) const;
01153 
01154     /**
01155      * Search for the nearest element in the tree to the given key point.
01156      *
01157      * If found, the contents of the element will by copied in the 
01158      * elem parameters and true will be returned.   Otherwise false will
01159      * be returned.
01160      * @param key point in the n-dimensional space you are looking for.
01161      * @param elem the contents of the found point will be left here.
01162      * @return true if key was found, otherwise false (i.e. tree empty).
01163      *
01164      * \warning This method is not thread safe.  In order to provide a
01165      *          fast search mechanism for the nearest neighbor some
01166      *          temporary variables are stored in the tree class itself,
01167      *          and therefore it is not possible to search the
01168      *          nearest neighbor in the same tree from different
01169      *          threads.
01170      */
01171     bool searchNearest(const T& key,element& elem) const;
01172 
01173     /**
01174      * Search for the nearest element in the tree to the given key point.
01175      *
01176      * If found, the contents of the element will by copied in the 
01177      * elem parameters and true will be returned.   Otherwise false will
01178      * be returned.
01179      * @param key point in the n-dimensional space you are looking for.
01180      * @param elem the contents of the found point will be left here.
01181      * @param dist distance between the points.  The type of distance is 
01182      *             determined by the used distanctor (the third template
01183      *             type of the tree, which return per default the square
01184      *             of the euclidean distance).
01185      * @return true if key was found, otherwise false (i.e. tree empty).
01186      *
01187      * \warning This method is not thread safe.  In order to provide a
01188      *          fast search mechanism for the nearest neighbor some
01189      *          temporary variables are stored in the tree class itself,
01190      *          and therefore it is not possible to search the
01191      *          nearest neighbor in the same tree from different
01192      *          threads.
01193      */
01194     bool searchNearest(const T& key,element& elem,acc_type& dist) const;
01195 
01196     /**
01197      * Search for the nearest element in the tree to the given key point.
01198      *
01199      * If found, the contents of the element will by copied in the 
01200      * elem parameters and true will be returned.   Otherwise false will
01201      * be returned.
01202      * @param key point in the n-dimensional space you are looking for.
01203      * @param data the contents of the found nearest point will be left here.
01204      * @return true if key was found, otherwise false (i.e. tree empty).
01205      *
01206      * \warning This method is not thread safe.  In order to provide a
01207      *          fast search mechanism for the nearest neighbor some
01208      *          temporary variables are stored in the tree class itself,
01209      *          and therefore it is not possible to search the
01210      *          nearest neighbor in the same tree from different
01211      *          threads.
01212      */
01213     bool searchNearest(const T& key,D& data) const;
01214 
01215     /**
01216      * Search for the nearest k elements in the tree to the given key point.
01217      *
01218      * If you are looking just for the nearest elements (i.e. k=1) use the
01219      * searchNearest(const T&,D&) or searchNearest(const T&,element&) methods
01220      * instead.  They are optimized for this case and are much faster.
01221      *
01222      * @param k number of elements you are looking for
01223      * @param key the point in the n-dimensional space you are looking for
01224      * @param neighbors contains the pointers to the found elements.  You
01225      *                  should NEVER delete these elements.
01226      * @return true if k elements were found, or false, if the tree contains
01227      *             less than k elements
01228      */
01229     bool searchNearest(const int k,
01230                        const T& key,
01231                        std::list<element*>& neighbors) const;
01232     
01233     /**
01234      * Search for the nearest k elements in the tree to the given key point.
01235      *
01236      * If you are looking just for the nearest elements (i.e. k=1) use the
01237      * searchNearest(const T&,D&) or searchNearest(const T&,element&) methods
01238      * instead.  They are optimized for this case and are much faster.
01239      *
01240      * @param k number of elements you are looking for.
01241      * @param key the point in the n-dimensional space you are looking for.
01242      * @param neighbors is a multimap containing as access key the
01243      *                  square of the euclidean distance or the result of
01244      *                  the given distantor between the
01245      *                  corresponding element* and the search key.
01246      *                  Remember that if you iterate the multimap, the
01247      *                  elements will be sorted in increasing order of
01248      *                  the distance (i.e. the nearest element first).
01249      *                  You should NEVER delete the pointed elements.
01250      * @return true if k elements were found, or false, if the tree contains
01251      *         less than k elements
01252      */
01253     bool searchNearest(const int k,
01254                        const T& key,
01255                        std::multimap<acc_type,element*>& neighbors) const;
01256 
01257     /**
01258      * Search for elements in an hyper-spheric neighbourhood of a given key
01259      * point, i.e. search for all elements that reside within a hypersphere
01260      * with the given radius centered at the given key.  Note that the
01261      * hypersphere is always defined using an Euclidean distance, no matter
01262      * of the specified distanctor policy.
01263      *
01264      * The returned list of elements is not sorted.  If you need it sorted
01265      * you should use the searchWithin() method with the multimap result.
01266      *
01267      * @param key point at which the hypersphere must be centered
01268      * @param dist allowed distance from the key point.  Note that this
01269      *             represents exaclty the radius of the hypersphere and not
01270      *             the square of it.
01271      * @param elems list of elements found.  You should NEVER delete the
01272      *              pointed elements.
01273      */
01274     bool searchWithin(const T& key,
01275           const acc_type& dist,
01276           std::list<element*>& elems) const;
01277       
01278 
01279     /**
01280      * Search for elements in an hyper-spheric neighbourhood of a given key
01281      * point, i.e. search for all elements that reside within a hypersphere
01282      * with the given radius centered at the given key.  Note that the
01283      * hypersphere is always defined using an Euclidean distance, no matter
01284      * of the specified distanctor policy.
01285      *
01286      * The returned multimap is always sorted in ascending order of
01287      * the distances (this is a property of all std::multimaps).  If you
01288      * want to save some time and don't need the sorted data consider using
01289      * the other searchWithin() method, which stores the result in a std::list.
01290      *
01291      * @param key point at which the hypersphere must be centered
01292      * @param dist allowed distance from the key point.  Note that this
01293      *             represents exaclty the radius of the hypersphere and not
01294      *             the square of it.
01295      * @param neighbors multimap of elements found.  You should NEVER delete
01296      *              the pointed elements.  Note that the keys used to sort
01297      *              the multimap are the square of the distances to the
01298      *              given key point.  This is done this way to save the
01299      *              time of applying the "sqrt()" function, which takes some
01300      *              time.
01301      */
01302     bool searchWithin(const T& key,
01303           const acc_type& dist,
01304           std::multimap<acc_type,element*>& neighbors) const;
01305 
01306 
01307     /**
01308      * Search the best-bin-first algorithm of Beis and Lowe.
01309      *
01310      * Use this method only if the dimensionality of your data is high
01311      * enough.  The time savings take effect only if the kd-tree is big
01312      * enough and the dimensionality of the data too.  Make a few tests
01313      * with your data in order to detect if this approximation is good enough
01314      * and fast enough for you.  Otherwise use the traditional search with
01315      * searchNearest()
01316      *
01317      * @param k number of elements you are looking for
01318      * @param key the point in the n-dimensional space you are looking for
01319      * @param neighbors contains the pointers to the found elements.  You
01320      *                  should NEVER delete these elements.
01321      * @param emax is the maximal number of visits allowed for leaf nodes.
01322      *             (in the original paper is called \f$E_{max}\f$).  Of course
01323      *             there can be more visits than emax if it is necessary to 
01324      *             find at least k neighbors.
01325      * @return true if k elements were found, or false, if the tree contains
01326      *             less than k elements
01327      */
01328     bool searchBestBinFirst(const int k,
01329                             const T& key,
01330                             const int emax,
01331                             std::list<element*>& neighbors) const;
01332 
01333 
01334     /**
01335      * Search the best-bin-first algorithm of Beis and Lowe.
01336      *
01337      * Use this method only if the dimensionality of your data is high
01338      * enough.  The time savings take effect only if the kd-tree is big
01339      * enough and the dimensionality of the data too.  Make a few tests
01340      * with your data in order to detect if this approximation is good enough
01341      * and fast enough for you.  Otherwise use the traditional search with
01342      * searchNearest()
01343      *
01344      * @param k number of elements you are looking for
01345      * @param key the point in the n-dimensional space you are looking for
01346      * @param neighbors contains the pointers to the found elements.  You
01347      *                  should NEVER delete these elements.
01348      * @param emax is the maximal number of visits allowed for leaf nodes.
01349      *             (in the original paper is called \f$E_{max}\f$).
01350      * @return true if k elements were found, or false, if the tree contains
01351      *             less than k elements
01352      */
01353     bool searchBestBinFirst(const int k,
01354                             const T& key,
01355                             const int emax,
01356                             std::multimap<acc_type,element*>& neighbors) const;
01357 
01358     /**
01359      * Search for all points lying within the given hyperbox.
01360      * @param boxMin point representing the lowest values at each coordinate
01361      *               building the lower limits of the bounding box.
01362      * @param boxMax point representing the highest values at each coordinate
01363      *               building the upper limits of the bounding box.
01364      * @param neighbors list of pointer to the elements found until now.
01365      * @return true if any element was found.
01366      */
01367     bool searchRange(const T& boxMin,
01368                      const T& boxMax,
01369                      std::list<element*>& neighbors) const;
01370 
01371     //@}
01372 
01373     /**
01374      * Consider the given element to be inserted in the tree after calling
01375      * the build(const int) method.
01376      *
01377      * The dimensionality of each point MUST be equal than the one
01378      * first added, otherwise an assertion will be thrown when building the 
01379      * tree.
01380      *
01381      * @param point n-dimensional point representint the position of
01382      *              this element * in the n-dimensional space
01383      * @param data data contained in this element.
01384      */
01385     void add(const T& point,const D& data);
01386  
01387     /**
01388      * Build the kd-Tree for all nodes added with the add() method, using
01389      * the given bucket size as the maximum number of elements a node
01390      * can contain.  The previous tree will be destroyed before the new one
01391      * is constructed.
01392      * the 
01393      * @param bucketSize maximum size of elements a node can contain (default
01394      *                   value is 1).
01395      * @return true if successful, false otherwise.
01396      */
01397     bool build(const int bucketSize = 1);
01398 
01399     /**
01400      * Rebuild the kd-Tree for all elements added with the add()
01401      * method and those already present in the tree, using the given
01402      * bucket size as the maximum number of elements a node can
01403      * contain. Although the previous tree will be destroyed before
01404      * the new one is constructed it will contain all elements
01405      * contained in the old one.
01406      *
01407      * Rebuilding the tree is quite slow since the elements have to be
01408      * extracted and copied from the existing tree first. This is
01409      * necessary since a kd-tree needs to know the complete set of
01410      * data for building.
01411      *  
01412      * @param bucketSize maximum size of elements a node can contain (default
01413      *                   value is 1).
01414      * @return true if successful, false otherwise.
01415      */
01416     bool rebuild(const int bucketSize = 1);
01417 
01418     /**
01419      * Read the parameters from the given ioHandler
01420      * @param handler the ioHandler to be used
01421      * @param complete if true (the default) the enclosing begin/end will
01422      *        be also read, otherwise only the data block will be read.
01423      * @return true if write was successful
01424      */
01425     virtual bool read(ioHandler &handler, const bool complete=true);
01426 
01427     /**
01428      * Write the parameters in the given ioHandler
01429      * @param handler the ioHandler to be used
01430      * @param complete if true (the default) the enclosing begin/end will
01431      *        be also written, otherwise only the data block will be
01432      *        written.
01433      * @return true if write was successful
01434      */
01435     virtual bool write(ioHandler& handler,const bool complete=true) const;
01436 
01437   protected:
01438     /**
01439      * The root node
01440      */
01441     node *root;
01442     
01443     /**
01444      * Number of levels in the tree
01445      */
01446     int levels;
01447 
01448     /**
01449      * Number of elements contained in the tree
01450      */
01451     int numElements;
01452 
01453     /**
01454      * Number of elements added to the tree (see add())
01455      */
01456     int numAddedElements;
01457 
01458     /**
01459      * Number of leaf nodes in the tree
01460      */
01461     int numLeaves;
01462 
01463     /**
01464      * Bounding Box
01465      * After creating the tree with build(), this matrix will be a
01466      * 2 x n matrix containing at the first row the minimum possible values
01467      * for the current type, and the second row the maximum values.
01468      */
01469     matrix<value_type> totalBounds;
01470 
01471     /**
01472      * Elements that will be contained in the tree.
01473      * All nodes contain pointers to the elements objects, that will be
01474      * transfered to the nodes in the tree with the build method.  
01475      * Thereafter, this list will be empty.
01476      */
01477     std::list<element*> points;
01478 
01479     /** 
01480      * Instance of the policy class used for computing the distances.
01481      */ 
01482     U distantor;
01483 
01484   private:
01485     /**
01486      * Read recursivelly the points contained in the node
01487      */
01488     void getDataInSubtree(node* nodePtr,std::list<element*>& data) const;
01489 
01490     /**
01491      * Search for an element with exactly the given position in the
01492      * hyperspace.
01493      *
01494      * This is the classical search in a kd-tree, that assumes that 
01495      * a leaf node contains exactly the given point.
01496      * If found, the contents of the element will by copied in the 
01497      * elem attributes and true will be returned.   Otherwise false will
01498      * be returned, and the elem will be left unchanged.
01499      *
01500      * @param nptr node at which the search begins.
01501      * @param key point in the n-dimensional space you are looking for.
01502      * @param elem the contents of the found point will be left here.
01503      * @return true if key was found, otherwise false.
01504      */
01505     bool searchExactly(const node* nptr,const T& key,element& elem) const;
01506 
01507     /**
01508      * Search for all elements with exactly the given position in the
01509      * hyperspace.
01510      *
01511      * This is the classical search in a kd-tree, that assumes that 
01512      * a leaf node contains exactly the given point.
01513      * If found, the contents of the element will by copied in the 
01514      * elem attributes and true will be returned.   Otherwise false will
01515      * be returned.
01516      *
01517      * @param nptr node at which the search begins.
01518      * @param key point in the n-dimensional space you are looking for.
01519      * @param elems a list containing copies to all found elements with the
01520      *              given keys
01521      * @return true if at least one key was found, otherwise false.
01522      */
01523     bool searchExactly(const node* nptr,
01524                        const T& key,std::list<element>& elems) const;
01525 
01526 
01527     /**
01528      * Check if the hypersphere is within bounds.  This is called in
01529      * the original paper "ball within bounds).
01530      * It only returns true if the distance at each component between
01531      * the key and the bounds is greater than the given distance.
01532      * (dist expects here the square of the distance, as it has been
01533      * stored in the multimap).
01534      */ 
01535     inline bool 
01536     checkHypersphereWithinBounds(const T& key,
01537                                  const matrix<value_type>& bounds,
01538                                  const acc_type& dist) const;
01539 
01540     /**
01541      * Check if the bounds overlap the hypersphere.  It was called in
01542      * the original paper "bounds overlap ball".
01543      */
01544     inline bool 
01545     checkBoundsOverlapHypersphere(const T& key,
01546                                   const matrix<value_type>& bounds,
01547                                   const acc_type& dist) const;
01548 
01549     /**
01550      * Search for the nearest k elements in the tree to the given key point.
01551      * @param nptr pointer to the subtree where the elements need to be
01552      *             searched for.
01553      * @param k number of elements you are looking for
01554      * @param key the point in the n-dimensional space you are looking for
01555      * @param bounds hyperbox where the search is taking place
01556      * @param neighbors contains the pointers to the found elements.  You
01557      *                  should NEVER delete these elements.  As multimap
01558      *                  it is always sorted after the "acc_typed" key,
01559      *                  which is in this case the square distance of the
01560      *                  element to the key.
01561      * @param neighSize the number of the the neighbors found.
01562      * @return true if k elements were found, or false, if the tree contains
01563      *             less than k elements
01564      */
01565     bool searchNearest(const node* nptr,
01566                        const int k,
01567                        const T& key,
01568                        matrix<value_type>& bounds,
01569                        std::multimap<acc_type,element*>& neighbors) const;
01570 
01571     /**
01572      * Search for the nearest element in the tree to the given key point.
01573      * @param nptr pointer to the subtree where the elements need to be
01574      *             searched for.
01575      * @param key the point in the n-dimensional space you are looking for
01576      * @param bounds hyperbox where the search is taking place
01577      * @param neighbors contains the pointers to the found elements.  You
01578      *                  should NEVER delete these elements.  As multimap
01579      *                  it is always sorted after the "acc_typed" key,
01580      *                  which is in this case the square distance of the
01581      *                  element to the key.
01582      * @param neighSize the number of the the neighbors found.
01583      * @return true if k elements were found, or false, if the tree contains
01584      *             less than k elements
01585      *
01586      * \warning This method is not thread safe.  In order to provide a
01587      *          fast search mechanism for the nearest neighbor some
01588      *          temporary variables are stored in the tree class itself,
01589      *          and therefore it is not possible to search the
01590      *          nearest neighbor in the same tree from different
01591      *          threads.
01592      */
01593     bool searchNearest(const node* nptr,
01594                        const T& key,
01595                        std::pair<acc_type,element*>& neighbors) const;
01596 
01597     /**
01598      * Search for the nearest element in the tree to the given key point.
01599      * @param nptr pointer to the node root of the subtree to be evaluated
01600      * @param key the point in the n-dimensional space you are looking for
01601      * @param dist distance radius to search point in
01602      * @param bounds hyperbox where the search is taking place
01603      * @param elems contains pointers to the found elements
01604      * @return true if k elements were found, or false, if the tree contains
01605      *             less than k elements
01606      */
01607     bool searchWithin(const node* nptr,
01608           const T& key,
01609           const acc_type& dist,
01610           matrix<value_type>& bounds,
01611           std::list<element*>& elems) const;
01612 
01613     /**
01614      * Search for the nearest element in the tree to the given key point.
01615      * @param nptr pointer to the node root of the subtree to be evaluated
01616      * @param key the point in the n-dimensional space you are looking for
01617      * @param dist distance radius to search point in
01618      * @param bounds hyperbox where the search is taking place
01619      * @param elems contains pointers to the found elements
01620      * @return true if k elements were found, or false, if the tree contains
01621      *             less than k elements
01622      */
01623     bool searchWithin(const node* nptr,
01624           const T& key,
01625           const acc_type& dist,
01626           matrix<value_type>& bounds,
01627           std::multimap<acc_type,element*>& neighbors) const;
01628 
01629     /**
01630      * Search for all points lying within the given hyperbox.
01631      * @param nptr pointer to the node root of the subtree to be evaluated
01632      * @param boxMin point representing the lowest values at each coordinate
01633      *               building the lower limits of the bounding box.
01634      * @param boxMax point representing the highest values at each coordinate
01635      *               building the upper limits of the bounding box.
01636      * @param neighbors list of pointer to the elements found until now.
01637      * @return true if completed.
01638      */
01639     bool searchRange(const node* nptr,
01640                      const T& boxMin,
01641                      const T& boxMax,
01642                      std::list<element*>& neighbors) const;
01643 
01644     /**
01645      * Check if a point lies withing the given bounding box.
01646      * @return true if point lies within the box, false otherwise.
01647      */
01648     inline bool withinBox(const T& boxMin,
01649                           const T& boxMax,
01650                           const T& key) const;
01651     
01652     /**
01653      * Check if a box lies withing the given bounding box.
01654      * @return true if box lies within the bbox, false otherwise.
01655      */
01656     inline bool withinBox(const matrix<value_type>& bbox,
01657                           const T& boxMin,
01658                           const T& boxMax) const;
01659 
01660     /**
01661      * Get the square of the L2 distance of the given point to the
01662      * node's hyperbox.
01663      *
01664      * If the point lies withing the hyperbox, the distance will be zero.
01665      *
01666      * @param na hyperbox representing the node's covered subspace.
01667      *           The first row represents the minimum and the second the
01668      *           maximum values.  It must be na.columns()==indexPoint.size()
01669      * @param indexPoint the point to be compared with the hyperbox.
01670      */
01671     inline acc_type minDistancePointToBox(const T& indexPoint,
01672                                           const matrix<value_type>& na) const;
01673     
01674     /**
01675      * Search the best-bin-first algorithm of Beis and Lowe.
01676      *
01677      * Use this method only if the dimensionality of your data is high
01678      * enough.  The time savings take effect only if the kd-tree is big
01679      * enough and the dimensionality of the data too.  Make a few tests
01680      * with your data in order to detect if this approximation is good enough
01681      * and fast enough for you.  Otherwise use the traditional search with
01682      * searchNearest()
01683      *
01684      * @param node pointer to the subtree where the elements need to be
01685      *             searched for.
01686      * @param k number of elements you are looking for
01687      * @param key the point in the n-dimensional space you are looking for
01688      * @param neighbors contains the pointers to the found elements.  You
01689      *                  should NEVER delete these elements.
01690      * @param emax maximum number of leaves to be visited.
01691      * @return true if k elements were found, or false, if the tree contains
01692      *             less than k elements
01693      */
01694     bool searchBestBinFirst(const node* root,
01695                             const int k,
01696                             const T& key,
01697                             std::multimap<acc_type,element*>& neighbors,
01698                             const int emax) const;
01699 
01700   private:
01701     /**
01702      * @name searchNearest Temporary variables
01703      *
01704      * The search of the nearest neighbors is optimized avoiding the
01705      * creation of many temporary variables.  
01706      */
01707     //@{
01708     
01709     /**
01710      * Minimum components of the bounding box.
01711      * It shares the memory with the first row of boundsBox.
01712      */
01713     mutable vector<value_type> boundsMin;
01714 
01715     /**
01716      * Maximum components of the bounding box
01717      * It shares the memory with the second row of boundsBox.
01718      */
01719     mutable vector<value_type> boundsMax;
01720 
01721     /**
01722      * Matrix containing the bounding box (first row min, second row max)
01723      */
01724     mutable matrix<value_type> boundsBox;
01725     //@}
01726 
01727   };
01728 
01729 }
01730 
01731 #include "ltiKdTree_template.h"
01732 
01733 #endif

Generated on Sat Apr 10 15:25:41 2010 for LTI-Lib by Doxygen 1.6.1