last update 20 Sep 2009 |
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