CVR-Lib last update 20 Sep 2009

cvrKdTree.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1998 - 2005
00003  * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany
00004  *
00005  *
00006  * This file is part of the Computer Vision and Robotics Library (CVR-Lib)
00007  *
00008  * The CVR-Lib is free software; you can redistribute it and/or
00009  * modify it under the terms of the BSD License.
00010  *
00011  * All rights reserved.
00012  *
00013  * Redistribution and use in source and binary forms, with or without
00014  * modification, are permitted provided that the following conditions are met:
00015  *
00016  * 1. Redistributions of source code must retain the above copyright notice,
00017  *    this list of conditions and the following disclaimer.
00018  *
00019  * 2. Redistributions in binary form must reproduce the above copyright notice,
00020  *    this list of conditions and the following disclaimer in the documentation
00021  *    and/or other materials provided with the distribution.
00022  *
00023  * 3. Neither the name of the authors nor the names of its contributors may be
00024  *    used to endorse or promote products derived from this software without
00025  *    specific prior written permission.
00026  *
00027  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00028  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00029  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00030  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00031  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00032  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00033  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00034  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00035  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00036  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00037  * POSSIBILITY OF SUCH DAMAGE.
00038  */
00039 
00040 /**
00041  * \file   cvrKdTree.h
00042  *         This file contains the aggregate type cvr::kdTree, a data
00043  *         structure for fast nearest neighbor search
00044  * \author Frederik Lange
00045  * \author Pablo Alvarado
00046  * \author Jens Rietzschel
00047  * \date   09.01.2003
00048  *
00049  * $Id: cvrKdTree.h,v 1.5 2007/12/19 03:00:15 alvarado Exp $
00050  */
00051 
00052 #ifndef _CVR_KD_TREE_H_
00053 #define _CVR_KD_TREE_H_
00054 
00055 #include "cvrContainer.h"
00056 #include "cvrMath.h"
00057 #include "cvrQuickMedian.h"
00058 #include "cvrEuclideanDistantor.h"
00059 #include "cvrTypeInfo.h"
00060 
00061 #include <list>
00062 #include <map>
00063 
00064 namespace cvr {
00065 
00066   /**
00067    * A class for k-d tree.
00068    *
00069    * A k-d tree is a generalization of the simple binary tree used for
00070    * sorting and searching.  At each level of the tree, a
00071    * n-dimensional subspace is split in two subspaces at a given
00072    * dimension. The leaves of the tree contain a "bucket" of data
00073    * within the described subspace.
00074    *
00075    * You can consider data for building with the add() method. Then
00076    * you can either build() the tree from that data, discarding the
00077    * old data, or rebuild() the tree, which will then contain the data
00078    * added since the last call to build() or rebuild() plus the newly
00079    * added data.
00080    *
00081    * This type allows to search in an efficient way for the
00082    * most similar neighbors of a given point.
00083    *
00084    * The type T describes a point in an n-dimensional space.  Usually,
00085    * you will use vector<float> or vector<double>, but types like
00086    * rgbPixel, trgbPixel<float>, tpoint<float> are also supported.
00087    * The type T MUST provide following methods/operators:
00088    *
00089    * - copy %operator=()
00090    * - access %operator[]()
00091    * - size() method
00092    * - must define the type \a value_type, which describes the
00093    *   type of each element in the container.
00094    * - comparison %operator==()
00095    *
00096    * (cvr::vector, cvr::tpoint, cvr::tpoint3D, cvr::trgbpixel and
00097    * cvr::rgbPixel provide this interface)
00098    *
00099    * The type D describes the data contained at each node, which is by
00100    * default just an integer value.  It must provide following
00101    * methods/operators
00102    * - copy operator=()
00103    *
00104    * The type U specifies a "distantor" policy, i.e. it specifies the
00105    * distance to be used while computing the nearest neighbors. If
00106    * not given, the default value will be euclideanSqrDistantor, which
00107    * provides, as the name says, the square of the euclidean distance.
00108    * Only Minkowski distances are allowed.  If you need your own
00109    * distance measure you can create your policy following the
00110    * interfaces of one of the classes cvr::euclideanDistantor,
00111    * cvr::cityBlockDistantor or euclideanSqrDistantor.
00112    *
00113    * \warning Elements added to the tree after a call to build() or
00114    * rebuild() are not saved when calling write().
00115    *
00116    * The original kd-Tree algorithm for k-neareast neighbors problems was
00117    * introduced in:
00118    * Friedman, J.H., Bentley, J.L. and Finkel, R.A.  An Algorithm for Finding
00119    *     Best Matches in Logarithmic Expected Time. ACM Transaction on
00120    *     Mathematical Software, Vol. 3, No. 3, September 1977, Pages 209-225
00121    *
00122    * @ingroup gAggregate
00123    */
00124   template <typename T,typename D=int,class U=euclideanSqrDistantor<T> >
00125   class kdTree : public container, public status {
00126   public:
00127     /**
00128      * Value type at each dimension of the space
00129      */
00130     typedef typename T::value_type value_type;
00131 
00132     /**
00133      * Type used to accumulate data of value_type elements
00134      */
00135     typedef typename U::distance_type distance_type;
00136 
00137     /**
00138      * At the leave nodes, a list of elements of this type will contain
00139      * the points and their corresponding data.
00140      *
00141      * Implementation must be here due to MS VC++ bug
00142      */
00143     class element : public ioObject {
00144     public:
00145 
00146       /**
00147        * n-dimensional point representint the position of this element
00148        * in the n-dimensional space
00149        */
00150       T point;
00151 
00152       /**
00153        * data contained in this element.
00154        */
00155       D data;
00156 
00157       /**
00158        * Constructor
00159        */
00160       element();
00161 
00162       /**
00163        * Constructor
00164        *
00165        * @param pos n-dimensional vector position of this element
00166        * @param dat data contained in this element
00167        */
00168       element(const T& pos, const D& dat);
00169 
00170       /**
00171        * Copy constructor
00172        */
00173       element(const element& other);
00174 
00175       /**
00176        * destructor
00177        */
00178       ~element();
00179 
00180       /**
00181        * shortcut to access the point value at each dimension
00182        */
00183       inline typename kdTree<T,D,U>::value_type& operator[](const int a);
00184 
00185       /**
00186        * shortcut to access the point value at each dimension
00187        */
00188       inline const typename kdTree<T,D,U>::value_type&
00189       operator[](const int a) const;
00190 
00191       /**
00192        * shortcut to acces the size of the points stored
00193        */
00194       inline int size() const;
00195 
00196       /**
00197        * Returns the name of this class.
00198        */
00199       const std::string& name() const;
00200 
00201       /**
00202        * copy method
00203        */
00204       inline typename kdTree<T,D,U>::element& copy(const element& other);
00205 
00206       /**
00207        * copy operator
00208        */
00209       inline typename kdTree<T,D,U>::element& operator=(const element& other);
00210 
00211       /**
00212        * clone function
00213        */
00214       typename kdTree<T,D,U>::element* clone() const;
00215 
00216       /**
00217        * newInstance function
00218        */
00219       typename kdTree<T,D,U>::element* newInstance() const;
00220 
00221       /**
00222        * read the element from the given ioHandler
00223        * @param handler the ioHandler to be used
00224        * @param complete if true (the default) the enclosing begin/end will
00225        *        be also read, otherwise only the data block will be read.
00226        * @return true if write was successful
00227        */
00228       virtual bool read(ioHandler &handler, const bool complete=true);
00229 
00230       /**
00231        * write the parameters in the given ioHandler
00232        * @param handler the ioHandler to be used
00233        * @param complete if true (the default) the enclosing begin/end will
00234        *        be also written, otherwise only the data block will be
00235        *        written.
00236        * @return true if write was successful
00237        */
00238       virtual bool write(ioHandler& handler,const bool complete=true) const;
00239 
00240     };
00241 
00242     /**
00243      * Class of nodes of the kd-tree
00244      *
00245      * Implementation must be here due to MS VC++ bug
00246      */
00247     class node : public ioObject {
00248       // the enclosing class is a friend of mine.
00249       friend class kdTree<T,D,U>;
00250     public:
00251 
00252       /**
00253        * type used for the container of elements.
00254        * A std::vector is for the search much more appropriate because
00255        * the access through iterators is about a factor 5 faster than the
00256        * std::list type.
00257        */
00258       typedef std::vector<element*> points_type;
00259 
00260       /**
00261        * @name Attributes
00262        */
00263       //@{
00264       /**
00265        * Points stored in this node.  These are pointers to the data
00266        * allocated in the kdTree class, this way the data can be
00267        * "transfered" more efficiently between different nodes.  The
00268        * memory managment is done by this node.
00269        */
00270       points_type points;
00271 
00272       /**
00273        *  the left subtree (lower coordinate) from the split plane
00274        */
00275       node* left;
00276 
00277       /**
00278        *  the right subtree (higher coordinate) from the split plane
00279        */
00280       node* right;
00281 
00282       /**
00283        * the dimension in which the subnodes are split.  This is
00284        * called in the original paper "discriminator"
00285        */
00286       int splitDim;
00287 
00288       /**
00289        * Value at the split dimension where the splitting takes place.
00290        * Usually this value corresponds to the median at the given
00291        * split dimension.
00292        *
00293        */
00294       value_type partition;
00295       //@}
00296 
00297       /**
00298        * constructor
00299        */
00300       node();
00301 
00302       /**
00303        * copy constructor.
00304        * Makes a deep copy, i.e. the pointers will be different
00305        */
00306       node(const node& other);
00307 
00308       /**
00309        * destructor
00310        */
00311       ~node();
00312 
00313       /**
00314        * insert a pointer to an element into the points list.
00315        *
00316        * The pointed element will be inserted as is (without copying), and
00317        * the memory managment is controled by the node itself.
00318        *
00319        * The dimensionality of each element MUST be equal than the one
00320        * of the first element added.
00321        */
00322       inline void add(element* f);
00323 
00324       /**
00325        * return true if this node is a leaf.
00326        */
00327       inline bool isLeaf() const;
00328 
00329       /**
00330        * Returns the name of this class.
00331        */
00332       const std::string& name() const;
00333 
00334       /**
00335        * copy method
00336        */
00337       typename kdTree<T,D,U>::node& copy(const node& other);
00338 
00339       /**
00340        * alias for copy method
00341        */
00342       inline typename kdTree<T,D,U>::node& operator=(const node& other);
00343 
00344       /**
00345        * clone function
00346        */
00347       typename kdTree<T,D,U>::node* clone() const;
00348 
00349       /**
00350        * newInstance function
00351        */
00352       typename kdTree<T,D,U>::node* newInstance() const;
00353 
00354       /**
00355        * read the node from the given ioHandler
00356        * @param handler the ioHandler to be used
00357        * @param complete if true (the default) the enclosing begin/end will
00358        *        be also read, otherwise only the data block will be read.
00359        * @return true if write was successful
00360        */
00361       virtual bool read(ioHandler &handler, const bool complete=true);
00362 
00363       /**
00364        * write the node to the given ioHandler
00365        * @param handler the ioHandler to be used
00366        * @param complete if true (the default) the enclosing begin/end will
00367        *        be also written, otherwise only the data block will be
00368        *        written.
00369        * @return true if write was successful
00370        */
00371       virtual bool write(ioHandler& handler,const bool complete=true) const;
00372 
00373     protected:
00374 
00375       /**
00376        * deep clear points
00377        */
00378       inline void clearPoints();
00379 
00380       /**
00381        * split the data stored at this node considering the axis with
00382        * the highest variance.
00383        *
00384        * @param maxCount maximum bucket size (how many elements are allowed
00385        *                 to be in a leaf node)
00386        * @param levels number of levels required until now for this tree.
00387        * @param leaves at the end this variable (which should be initialized
00388        *        with zero externally) contains the number of leaves in the tree
00389        */
00390       void subdivide(const int maxCount,int& levels,int& leaves);
00391 
00392       /**
00393        * get the dimension of the data with the highest variance.
00394        * We assume the whole data set to be considered is located
00395        * at the points vector.
00396        */
00397       int getDimWithHighestVariance() const;
00398 
00399       /**
00400        * get the median value at the given search dimension
00401        *
00402        * @param searchDim search dimension
00403        * @return the median of the given dimension
00404        */
00405       inline value_type getMedianVal(const int searchDim) const;
00406 
00407       /**
00408        * search for exactly the given key in the list of elements.  If
00409        * found, return true, otherwise return false and leave the
00410        * element instance untouched.
00411        *
00412        * For floating types this method usually returns false, because
00413        * the exact match of the key is very unprobable.  This method is
00414        * therefore used mostly for integer value_types
00415        */
00416       inline bool getPoint(const T& key,element& elem) const;
00417 
00418       /**
00419        * search for exactly the given key in the list of elements.  If
00420        * found, return true, otherwise return false and leave the
00421        * element instance untouched.
00422        *
00423        * For floating types this method usually returns false, because
00424        * the exact match of the key is very unprobable.  This method is
00425        * therefore used mostly for integer value_types
00426        */
00427       inline bool getPoint(const T& key,std::list<element>& elems) const;
00428 
00429       /**
00430        * insert all elements in the given list into the internal
00431        * elements vector.
00432        *
00433        * The pointed elements will be inserted as they are (without copying),
00434        * and the memory managment is controled by this node itself.
00435        *
00436        * The dimensionality of each element MUST be equal than the one
00437        * of the first added element.
00438        */
00439       inline void add(std::list<element*>& pts);
00440 
00441     };  // end of node class
00442 
00443     /**
00444      * Multimap type
00445      */
00446     typedef std::multimap<distance_type,element*> mmap_type;
00447 
00448 
00449     // ----------------------------------------------------------------------
00450     // kdTree Definition
00451     // ----------------------------------------------------------------------
00452 
00453   public:
00454 
00455     /**
00456      * Return type of the size() member
00457      */
00458     typedef int size_type;
00459 
00460     /**
00461      * Default constructor
00462      */
00463     kdTree();
00464 
00465     /**
00466      * Copy constructor
00467      * @param other the object to be copied
00468      */
00469     kdTree(const kdTree<T,D,U>& other);
00470 
00471     /**
00472      * Destructor
00473      */
00474     virtual ~kdTree();
00475 
00476     /**
00477      * Returns the name of this class.
00478      */
00479     const std::string& name() const;
00480 
00481     /**
00482      * Copy data of "other" functor.
00483      * @param other the functor to be copied
00484      * @return a reference to this functor object
00485      */
00486     kdTree<T,D,U>& copy(const kdTree<T,D,U>& other);
00487 
00488     /**
00489      * Alias for copy member
00490      * @param other the functor to be copied
00491      * @return a reference to this functor object
00492      */
00493     kdTree<T,D,U>& operator=(const kdTree<T,D,U>& other);
00494 
00495     /**
00496      * Returns a pointer to a clone of this functor.
00497      */
00498     virtual kdTree<T,D,U>* clone() const;
00499 
00500     /**
00501      * Returns a pointer to a new instance of this functor.
00502      */
00503     virtual kdTree<T,D,U>* newInstance() const;
00504 
00505     /**
00506      * Clear the tree.
00507      *
00508      * All elements belonging to the tree will be removed.  Also all elements
00509      * added until now will be deleted.
00510      */
00511     virtual void clear();
00512 
00513     /**
00514      * Check if the tree is empty
00515      */
00516     virtual bool empty() const;
00517 
00518     /**
00519      * Get the number of elements added to the tree with the function add().
00520      *
00521      * Note that these points are not really \b in the tree until you
00522      * call build() or rebuild(). After calling either the added
00523      * points are flushed and the return value of this function is
00524      * zero.
00525      *
00526      * @see size()
00527      */
00528     virtual int getNumberOfAddedElements() const;
00529 
00530     /**
00531      * Get the number of elements in the built tree.
00532      *
00533      * Note that this value can differ substantially from the value
00534      * returned by getNumberOfAddedElements(). The latter don't belong
00535      * to the tree yet. Thus, adding elements, then calling build and
00536      * then adding more elements, generally results in two different
00537      * values.
00538      *
00539      * The return value is zero if no tree has been built yet.
00540      *
00541      * @see getNumberOfAddedElements()
00542      */
00543     virtual int size() const;
00544 
00545     /**
00546      * Get the number of leaves in the tree.
00547      *
00548      * Return zero if the tree hasn't been build yet.
00549      */
00550     virtual int getNumberOfLeaves() const;
00551 
00552     /**
00553      * Get the number of levels of the tree.
00554      *
00555      * Return zero if the tree hasn't been build yet.
00556      */
00557     virtual int getNumberOfLevels() const;
00558 
00559     /**
00560      * Get pointer to root node
00561      *
00562      * Return a null pointer if the tree hasn't been build yet.
00563      */
00564     virtual node* getRoot();
00565 
00566     /**
00567      * @name Search methods
00568      */
00569     //@{
00570 
00571     /**
00572      * Search for an element with exactly the given position in the
00573      * hyperspace.
00574      *
00575      * This is the classical search in a kd-tree, that assumes that
00576      * a leaf node contains exactly the given point.
00577      * If found, the contents of the element will by copied in the
00578      * elem attributes and true will be returned.   Otherwise false will
00579      * be returned.
00580      *
00581      * If the key is present more than once, only the "first" one will
00582      * be returned, which is the first one the list of points at the
00583      * left-most node containing it.
00584      *
00585      * @param key point in the n-dimensional space you are looking for.
00586      * @param elem the contents of the found point will be left here.
00587      * @return true if key was found, otherwise false.
00588      */
00589     bool searchExactly(const T& key,element& elem) const;
00590 
00591     /**
00592      * Search for all elements with exactly the given position in the
00593      * hyperspace.
00594      *
00595      * This is the classical search in a kd-tree, that assumes that
00596      * a leaf node contains exactly the given point.
00597      * If found, the contents of the element will by copied in the
00598      * elem attributes and true will be returned.   Otherwise false will
00599      * be returned.
00600      *
00601      * @param key point in the n-dimensional space you are looking for.
00602      * @param elems a list containing copies to all found elements with the
00603      *              given keys
00604      * @return true if at least one key was found, otherwise false.
00605      */
00606     bool searchExactly(const T& key,std::list<element>& elems) const;
00607 
00608     /**
00609      * Search for the nearest element in the tree to the given key point.
00610      *
00611      * If found, a pointer to the element will be written in the
00612      * \a elem parameters and true will be returned.   Otherwise false will
00613      * be returned and the pointer will be set to zero.
00614      *
00615      * The pointer is not const to allow you to change the \a data of the
00616      * element, but if you also change the \a point, the tree will be corrupted
00617      * and will not work appropriately.  There is no way to change the search
00618      * keys dynamically in a kd-tree without a heavy load of computation.  If
00619      * that is what you are looking for, you should consider rebuilding the
00620      * entire tree (expensive!).
00621      *
00622      * @param key point in the n-dimensional space you are looking for.
00623      * @param elem pointer to the contents of the point found, or zero if
00624      *             not found.  You should \b never delete the pointed data.
00625      * @return true if key was found, otherwise false (i.e. tree empty).
00626      *
00627      * \warning This method is not thread safe.  In order to provide a
00628      *          fast search mechanism for the nearest neighbor some
00629      *          temporary variables are stored in the tree class itself,
00630      *          and therefore it is not possible to search the
00631      *          nearest neighbor in the same tree from different
00632      *          threads.
00633      */
00634     bool searchNearest(const T& key,element*& elem) const;
00635 
00636     /**
00637      * Search for the nearest element in the tree to the given key point.
00638      *
00639      * If found, a pointer to the element will be written in the
00640      * \a elem parameters and true will be returned.   Otherwise false will
00641      * be returned and the pointer will be set to zero.
00642      *
00643      * The pointer is not const to allow you to change the \a data of the
00644      * element, but if you also change the \a point the tree will be corrupted
00645      * and will not work appropriately.  There is no way to change the search
00646      * keys dynamically in a kd-tree without a heavy load of computation.  If
00647      * that is what you are looking for, you should consider rebuilding the
00648      * entire tree (expensive!).
00649      *
00650      * @param key point in the n-dimensional space you are looking for.
00651      * @param elem pointer to the contents of the point found, or zero if
00652      *             not found.  You should \b never delete the pointed data.
00653      * @param dist distance between the points.  The type of distance is
00654      *             determined by the used distantor (the third template
00655      *             type of the tree, which returns per default the square
00656      *             of the euclidean distance).
00657      * @return true if key was found, otherwise false (i.e. tree empty).
00658      *
00659      * \warning This method is not thread safe.  In order to provide a
00660      *          fast search mechanism for the nearest neighbor some
00661      *          temporary variables are stored in the tree class itself,
00662      *          and therefore it is not possible to search the
00663      *          nearest neighbor in the same tree from different
00664      *          threads.
00665      */
00666     bool searchNearest(const T& key,element*& elem,distance_type& dist) const;
00667 
00668     /**
00669      * Search for the nearest element in the tree to the given key point.
00670      *
00671      * If found, the contents of the element will by copied in the
00672      * elem parameters and true will be returned.   Otherwise false will
00673      * be returned.
00674      * @param key point in the n-dimensional space you are looking for.
00675      * @param elem the contents of the found point will be left here.
00676      * @return true if key was found, otherwise false (i.e. tree empty).
00677      *
00678      * \warning This method is not thread safe.  In order to provide a
00679      *          fast search mechanism for the nearest neighbor some
00680      *          temporary variables are stored in the tree class itself,
00681      *          and therefore it is not possible to search the
00682      *          nearest neighbor in the same tree from different
00683      *          threads.
00684      */
00685     bool searchNearest(const T& key,element& elem) const;
00686 
00687     /**
00688      * Search for the nearest element in the tree to the given key point.
00689      *
00690      * If found, the contents of the element will by copied in the
00691      * elem parameters and true will be returned.   Otherwise false will
00692      * be returned.
00693      * @param key point in the n-dimensional space you are looking for.
00694      * @param elem the contents of the found point will be left here.
00695      * @param dist distance between the points.  The type of distance is
00696      *             determined by the used distanctor (the third template
00697      *             type of the tree, which return per default the square
00698      *             of the euclidean distance).
00699      * @return true if key was found, otherwise false (i.e. tree empty).
00700      *
00701      * \warning This method is not thread safe.  In order to provide a
00702      *          fast search mechanism for the nearest neighbor some
00703      *          temporary variables are stored in the tree class itself,
00704      *          and therefore it is not possible to search the
00705      *          nearest neighbor in the same tree from different
00706      *          threads.
00707      */
00708     bool searchNearest(const T& key,element& elem,distance_type& dist) const;
00709 
00710     /**
00711      * Search for the nearest element in the tree to the given key point.
00712      *
00713      * If found, the contents of the element will by copied in the
00714      * elem parameters and true will be returned.   Otherwise false will
00715      * be returned.
00716      * @param key point in the n-dimensional space you are looking for.
00717      * @param data the contents of the found nearest point will be left here.
00718      * @return true if key was found, otherwise false (i.e. tree empty).
00719      *
00720      * \warning This method is not thread safe.  In order to provide a
00721      *          fast search mechanism for the nearest neighbor some
00722      *          temporary variables are stored in the tree class itself,
00723      *          and therefore it is not possible to search the
00724      *          nearest neighbor in the same tree from different
00725      *          threads.
00726      */
00727     bool searchNearest(const T& key,D& data) const;
00728 
00729     /**
00730      * Search for the nearest k elements in the tree to the given key point.
00731      *
00732      * If you are looking just for the nearest elements (i.e. k=1) use the
00733      * searchNearest(const T&,D&) or searchNearest(const T&,element&) methods
00734      * instead.  They are optimized for this case and are much faster.
00735      *
00736      * @param k number of elements you are looking for
00737      * @param key the point in the n-dimensional space you are looking for
00738      * @param neighbors contains the pointers to the found elements.  You
00739      *                  should NEVER delete these elements.
00740      * @return true if k elements were found, or false, if the tree contains
00741      *             less than k elements
00742      */
00743     bool searchNearest(const int k,
00744                        const T& key,
00745                        std::list<element*>& neighbors) const;
00746 
00747     /**
00748      * Search for the nearest k elements in the tree to the given key point.
00749      *
00750      * If you are looking just for the nearest elements (i.e. k=1) use the
00751      * searchNearest(const T&,D&) or searchNearest(const T&,element&) methods
00752      * instead.  They are optimized for this case and are much faster.
00753      *
00754      * @param k number of elements you are looking for.
00755      * @param key the point in the n-dimensional space you are looking for.
00756      * @param neighbors is a multimap containing as access key the
00757      *                  square of the euclidean distance or the result of
00758      *                  the given distantor between the
00759      *                  corresponding element* and the search key.
00760      *                  Remember that if you iterate the multimap, the
00761      *                  elements will be sorted in increasing order of
00762      *                  the distance (i.e. the nearest element first).
00763      *                  You should NEVER delete the pointed elements.
00764      * @return true if k elements were found, or false, if the tree contains
00765      *         less than k elements
00766      */
00767     bool searchNearest(const int k,
00768                        const T& key,
00769                        mmap_type& neighbors) const;
00770 
00771     /**
00772      * Search for elements in an hyper-spheric neighbourhood of a given key
00773      * point, i.e. search for all elements that reside within a hypersphere
00774      * with the given radius centered at the given key.  Note that the
00775      * hypersphere is always defined using an Euclidean distance, no matter
00776      * of the specified distanctor policy.
00777      *
00778      * The returned list of elements is not sorted.  If you need it sorted
00779      * you should use the searchWithin() method with the multimap result.
00780      *
00781      * @param key point at which the hypersphere must be centered
00782      * @param dist allowed distance from the key point.  Note that this
00783      *             represents exaclty the radius of the hypersphere and not
00784      *             the square of it.
00785      * @param elems list of elements found.  You should NEVER delete the
00786      *              pointed elements.
00787      */
00788     bool searchWithin(const T& key,
00789           const distance_type& dist,
00790           std::list<element*>& elems) const;
00791 
00792 
00793     /**
00794      * Search for elements in an hyper-spheric neighbourhood of a given key
00795      * point, i.e. search for all elements that reside within a hypersphere
00796      * with the given radius centered at the given key.  Note that the
00797      * hypersphere is always defined using an Euclidean distance, no matter
00798      * of the specified distanctor policy.
00799      *
00800      * The returned multimap is always sorted in ascending order of
00801      * the distances (this is a property of all std::multimaps).  If you
00802      * want to save some time and don't need the sorted data consider using
00803      * the other searchWithin() method, which stores the result in a std::list.
00804      *
00805      * @param key point at which the hypersphere must be centered
00806      * @param dist allowed distance from the key point.  Note that this
00807      *             represents exaclty the radius of the hypersphere and not
00808      *             the square of it.
00809      * @param neighbors multimap of elements found.  You should NEVER delete
00810      *              the pointed elements.  Note that the keys used to sort
00811      *              the multimap are the square of the distances to the
00812      *              given key point.  This is done this way to save the
00813      *              time of applying the "sqrt()" function, which takes some
00814      *              time.
00815      */
00816     bool searchWithin(const T& key,
00817           const distance_type& dist,
00818           mmap_type& neighbors) const;
00819 
00820 
00821     /**
00822      * Search the best-bin-first algorithm of Beis and Lowe.
00823      *
00824      * Use this method only if the dimensionality of your data is high
00825      * enough.  The time savings take effect only if the kd-tree is big
00826      * enough and the dimensionality of the data too.  Make a few tests
00827      * with your data in order to detect if this approximation is good enough
00828      * and fast enough for you.  Otherwise use the traditional search with
00829      * searchNearest()
00830      *
00831      * @param k number of elements you are looking for
00832      * @param key the point in the n-dimensional space you are looking for
00833      * @param neighbors contains the pointers to the found elements.  You
00834      *                  should NEVER delete these elements.
00835      * @param emax is the maximal number of visits allowed for leaf nodes.
00836      *             (in the original paper is called \f$E_{max}\f$).  Of course
00837      *             there can be more visits than emax if it is necessary to
00838      *             find at least k neighbors.
00839      * @return true if k elements were found, or false, if the tree contains
00840      *             less than k elements
00841      */
00842     bool searchBestBinFirst(const int k,
00843                             const T& key,
00844                             const int emax,
00845                             std::list<element*>& neighbors) const;
00846 
00847 
00848     /**
00849      * Search the best-bin-first algorithm of Beis and Lowe.
00850      *
00851      * Use this method only if the dimensionality of your data is high
00852      * enough.  The time savings take effect only if the kd-tree is big
00853      * enough and the dimensionality of the data too.  Make a few tests
00854      * with your data in order to detect if this approximation is good enough
00855      * and fast enough for you.  Otherwise use the traditional search with
00856      * searchNearest()
00857      *
00858      * @param k number of elements you are looking for
00859      * @param key the point in the n-dimensional space you are looking for
00860      * @param neighbors contains the pointers to the found elements.  You
00861      *                  should NEVER delete these elements.
00862      * @param emax is the maximal number of visits allowed for leaf nodes.
00863      *             (in the original paper is called \f$E_{max}\f$).
00864      * @return true if k elements were found, or false, if the tree contains
00865      *             less than k elements
00866      */
00867     bool searchBestBinFirst(const int k,
00868                             const T& key,
00869                             const int emax,
00870                             mmap_type& neighbors) const;
00871 
00872     /**
00873      * Search for all points lying within the given hyperbox.
00874      * @param boxMin point representing the lowest values at each coordinate
00875      *               building the lower limits of the bounding box.
00876      * @param boxMax point representing the highest values at each coordinate
00877      *               building the upper limits of the bounding box.
00878      * @param neighbors list of pointer to the elements found until now.
00879      * @return true if any element was found.
00880      */
00881     bool searchRange(const T& boxMin,
00882                      const T& boxMax,
00883                      std::list<element*>& neighbors) const;
00884 
00885     //@}
00886 
00887     /**
00888      * Consider the given element to be inserted in the tree after calling
00889      * the build(const int) method.
00890      *
00891      * The dimensionality of each point MUST be equal than the one
00892      * first added, otherwise an assertion will be thrown when building the
00893      * tree.
00894      *
00895      * @param point n-dimensional point representint the position of
00896      *              this element * in the n-dimensional space
00897      * @param data data contained in this element.
00898      */
00899     void add(const T& point,const D& data);
00900 
00901     /**
00902      * Build the kd-Tree for all nodes added with the add() method, using
00903      * the given bucket size as the maximum number of elements a node
00904      * can contain.  The previous tree will be destroyed before the new one
00905      * is constructed.
00906      *
00907      * @param bucketSize maximum size of elements a node can contain (default
00908      *                   value is 1).
00909      * @return true if successful, false otherwise.
00910      */
00911     bool build(const int bucketSize = 1);
00912 
00913     /**
00914      * Rebuild the kd-Tree for all elements added with the add()
00915      * method and those already present in the tree, using the given
00916      * bucket size as the maximum number of elements a node can
00917      * contain. Although the previous tree will be destroyed before
00918      * the new one is constructed it will contain all elements
00919      * contained in the old one.
00920      *
00921      * Rebuilding the tree is quite slow since the elements have to be
00922      * extracted and copied from the existing tree first. This is
00923      * necessary since a kd-tree needs to know the complete set of
00924      * data for building.
00925      *
00926      * @param bucketSize maximum size of elements a node can contain (default
00927      *                   value is 1).
00928      * @return true if successful, false otherwise.
00929      */
00930     bool rebuild(const int bucketSize = 1);
00931 
00932     /**
00933      * Read the parameters from the given ioHandler
00934      * @param handler the ioHandler to be used
00935      * @param complete if true (the default) the enclosing begin/end will
00936      *        be also read, otherwise only the data block will be read.
00937      * @return true if write was successful
00938      */
00939     virtual bool read(ioHandler &handler, const bool complete=true);
00940 
00941     /**
00942      * Write the parameters in the given ioHandler
00943      * @param handler the ioHandler to be used
00944      * @param complete if true (the default) the enclosing begin/end will
00945      *        be also written, otherwise only the data block will be
00946      *        written.
00947      * @return true if write was successful
00948      */
00949     virtual bool write(ioHandler& handler,const bool complete=true) const;
00950 
00951   protected:
00952     /**
00953      * The root node
00954      */
00955     node* root_;
00956 
00957     /**
00958      * Number of levels in the tree
00959      */
00960     int levels_;
00961 
00962     /**
00963      * Number of elements contained in the tree
00964      */
00965     int numElements_;
00966 
00967     /**
00968      * Number of elements added to the tree (see add())
00969      */
00970     int numAddedElements_;
00971 
00972     /**
00973      * Number of leaf nodes in the tree
00974      */
00975     int numLeaves_;
00976 
00977     /**
00978      * Bounding Box
00979      * After creating the tree with build(), this matrix will be a
00980      * 2 x n matrix containing at the first row the minimum possible values
00981      * for the current type, and the second row the maximum values.
00982      */
00983     matrix<value_type> totalBounds_;
00984 
00985     /**
00986      * Elements that will be contained in the tree.
00987      * All nodes contain pointers to the elements objects, that will be
00988      * transfered to the nodes in the tree with the build method.
00989      * Thereafter, this list will be empty.
00990      */
00991     std::list<element*> treePoints_;
00992 
00993     /**
00994      * Instance of the policy class used for computing the distances.
00995      */
00996     U distantor_;
00997 
00998   private:
00999     /**
01000      * Read recursivelly the points contained in the node
01001      */
01002     void getDataInSubtree(node* nodePtr,std::list<element*>& data) const;
01003 
01004     /**
01005      * Search for an element with exactly the given position in the
01006      * hyperspace.
01007      *
01008      * This is the classical search in a kd-tree, that assumes that
01009      * a leaf node contains exactly the given point.
01010      * If found, the contents of the element will by copied in the
01011      * elem attributes and true will be returned.   Otherwise false will
01012      * be returned, and the elem will be left unchanged.
01013      *
01014      * @param nptr node at which the search begins.
01015      * @param key point in the n-dimensional space you are looking for.
01016      * @param elem the contents of the found point will be left here.
01017      * @return true if key was found, otherwise false.
01018      */
01019     bool searchExactly(const node* nptr,const T& key,element& elem) const;
01020 
01021     /**
01022      * Search for all elements with exactly the given position in the
01023      * hyperspace.
01024      *
01025      * This is the classical search in a kd-tree, that assumes that
01026      * a leaf node contains exactly the given point.
01027      * If found, the contents of the element will by copied in the
01028      * elem attributes and true will be returned.   Otherwise false will
01029      * be returned.
01030      *
01031      * @param nptr node at which the search begins.
01032      * @param key point in the n-dimensional space you are looking for.
01033      * @param elems a list containing copies to all found elements with the
01034      *              given keys
01035      * @return true if at least one key was found, otherwise false.
01036      */
01037     bool searchExactly(const node* nptr,
01038                        const T& key,std::list<element>& elems) const;
01039 
01040 
01041     /**
01042      * Check if the hypersphere is within bounds.  This is called in
01043      * the original paper "ball within bounds).
01044      * It only returns true if the distance at each component between
01045      * the key and the bounds is greater than the given distance.
01046      * (dist expects here the square of the distance, as it has been
01047      * stored in the multimap).
01048      */
01049     inline bool
01050     checkHypersphereWithinBounds(const T& key,
01051                                  const matrix<value_type>& bounds,
01052                                  const distance_type& dist) const;
01053 
01054     /**
01055      * Check if the bounds overlap the hypersphere.  It was called in
01056      * the original paper "bounds overlap ball".
01057      */
01058     inline bool
01059     checkBoundsOverlapHypersphere(const T& key,
01060                                   const matrix<value_type>& bounds,
01061                                   const distance_type& dist) const;
01062 
01063     /**
01064      * Search for the nearest k elements in the tree to the given key point.
01065      * @param nptr pointer to the subtree where the elements need to be
01066      *             searched for.
01067      * @param k number of elements you are looking for
01068      * @param key the point in the n-dimensional space you are looking for
01069      * @param bounds hyperbox where the search is taking place
01070      * @param neighbors contains the pointers to the found elements.  You
01071      *                  should NEVER delete these elements.  As multimap
01072      *                  it is always sorted after the "distance_typed" key,
01073      *                  which is in this case the square distance of the
01074      *                  element to the key.
01075      * @param neighSize the number of the the neighbors found.
01076      * @return true if k elements were found, or false, if the tree contains
01077      *             less than k elements
01078      */
01079     bool searchNearest(const node* nptr,
01080                        const int k,
01081                        const T& key,
01082                        matrix<value_type>& bounds,
01083                        mmap_type& neighbors) const;
01084 
01085     /**
01086      * Search for the nearest element in the tree to the given key point.
01087      * @param nptr pointer to the subtree where the elements need to be
01088      *             searched for.
01089      * @param key the point in the n-dimensional space you are looking for
01090      * @param bounds hyperbox where the search is taking place
01091      * @param neighbors contains the pointers to the found elements.  You
01092      *                  should NEVER delete these elements.  As multimap
01093      *                  it is always sorted after the "distance_typed" key,
01094      *                  which is in this case the square distance of the
01095      *                  element to the key.
01096      * @param neighSize the number of the the neighbors found.
01097      * @return true if k elements were found, or false, if the tree contains
01098      *             less than k elements
01099      *
01100      * \warning This method is not thread safe.  In order to provide a
01101      *          fast search mechanism for the nearest neighbor some
01102      *          temporary variables are stored in the tree class itself,
01103      *          and therefore it is not possible to search the
01104      *          nearest neighbor in the same tree from different
01105      *          threads.
01106      */
01107     bool searchNearest(const node* nptr,
01108                        const T& key,
01109                        std::pair<distance_type,element*>& neighbors) const;
01110 
01111     /**
01112      * Search for the nearest element in the tree to the given key point.
01113      * @param nptr pointer to the node root of the subtree to be evaluated
01114      * @param key the point in the n-dimensional space you are looking for
01115      * @param dist distance radius to search point in
01116      * @param bounds hyperbox where the search is taking place
01117      * @param elems contains pointers to the found elements
01118      * @return true if k elements were found, or false, if the tree contains
01119      *             less than k elements
01120      */
01121     bool searchWithin(const node* nptr,
01122           const T& key,
01123           const distance_type& dist,
01124           matrix<value_type>& bounds,
01125           std::list<element*>& elems) const;
01126 
01127     /**
01128      * Search for the nearest element in the tree to the given key point.
01129      * @param nptr pointer to the node root of the subtree to be evaluated
01130      * @param key the point in the n-dimensional space you are looking for
01131      * @param dist distance radius to search point in
01132      * @param bounds hyperbox where the search is taking place
01133      * @param elems contains pointers to the found elements
01134      * @return true if k elements were found, or false, if the tree contains
01135      *             less than k elements
01136      */
01137     bool searchWithin(const node* nptr,
01138           const T& key,
01139           const distance_type& dist,
01140           matrix<value_type>& bounds,
01141           mmap_type& neighbors) const;
01142 
01143     /**
01144      * Search for all points lying within the given hyperbox.
01145      * @param nptr pointer to the node root of the subtree to be evaluated
01146      * @param boxMin point representing the lowest values at each coordinate
01147      *               building the lower limits of the bounding box.
01148      * @param boxMax point representing the highest values at each coordinate
01149      *               building the upper limits of the bounding box.
01150      * @param neighbors list of pointer to the elements found until now.
01151      * @return true if completed.
01152      */
01153     bool searchRange(const node* nptr,
01154                      const T& boxMin,
01155                      const T& boxMax,
01156                      std::list<element*>& neighbors) const;
01157 
01158     /**
01159      * Check if a point lies withing the given bounding box.
01160      * @return true if point lies within the box, false otherwise.
01161      */
01162     inline bool withinBox(const T& boxMin,
01163                           const T& boxMax,
01164                           const T& key) const;
01165 
01166     /**
01167      * Check if a box lies withing the given bounding box.
01168      * @return true if box lies within the bbox, false otherwise.
01169      */
01170     inline bool withinBox(const matrix<value_type>& bbox,
01171                           const T& boxMin,
01172                           const T& boxMax) const;
01173 
01174     /**
01175      * Get the square of the L2 distance of the given point to the
01176      * node's hyperbox.
01177      *
01178      * If the point lies withing the hyperbox, the distance will be zero.
01179      *
01180      * @param na hyperbox representing the node's covered subspace.
01181      *           The first row represents the minimum and the second the
01182      *           maximum values.  It must be na.columns()==indexPoint.size()
01183      * @param indexPoint the point to be compared with the hyperbox.
01184      */
01185     inline distance_type minDistancePointToBox(const T& indexPoint,
01186                                           const matrix<value_type>& na) const;
01187 
01188     /**
01189      * Search the best-bin-first algorithm of Beis and Lowe.
01190      *
01191      * Use this method only if the dimensionality of your data is high
01192      * enough.  The time savings take effect only if the kd-tree is big
01193      * enough and the dimensionality of the data too.  Make a few tests
01194      * with your data in order to detect if this approximation is good enough
01195      * and fast enough for you.  Otherwise use the traditional search with
01196      * searchNearest()
01197      *
01198      * @param node pointer to the subtree where the elements need to be
01199      *             searched for.
01200      * @param k number of elements you are looking for
01201      * @param key the point in the n-dimensional space you are looking for
01202      * @param neighbors contains the pointers to the found elements.  You
01203      *                  should NEVER delete these elements.
01204      * @param emax maximum number of leaves to be visited.
01205      * @return true if k elements were found, or false, if the tree contains
01206      *             less than k elements
01207      */
01208     bool searchBestBinFirst(const node* root,
01209                             const int k,
01210                             const T& key,
01211                             mmap_type& neighbors,
01212                             const int emax) const;
01213 
01214   private:
01215     /**
01216      * @name searchNearest Temporary variables
01217      *
01218      * The search of the nearest neighbors is optimized avoiding the
01219      * creation of many temporary variables.
01220      */
01221     //@{
01222 
01223     /**
01224      * Minimum components of the bounding box.
01225      * It shares the memory with the first row of boundsBox.
01226      */
01227     mutable vector<value_type> minBounds_;
01228 
01229     /**
01230      * Maximum components of the bounding box
01231      * It shares the memory with the second row of boundsBox.
01232      */
01233     mutable vector<value_type> maxBounds_;
01234 
01235     /**
01236      * Matrix containing the bounding box (first row min, second row max)
01237      */
01238     mutable matrix<value_type> bounds_;
01239     //@}
01240 
01241   };
01242 
01243 }
01244 
01245 #include "cvrKdTree_inline.h"
01246 #include "cvrKdTree_template.h"
01247 
01248 #endif
01249 
01250 

Generated on Sun Sep 20 22:07:59 2009 for CVR-Lib by Doxygen 1.5.8