BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Orthogonal_k_neighbor_search.h
Go to the documentation of this file.
00001 // Copyright (c) 2002 Utrecht University (The Netherlands).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00005 // the terms of the Q Public License version 1.0.
00006 // See the file LICENSE.QPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h $
00015 // $Id: Orthogonal_k_neighbor_search.h 44494 2008-07-27 16:46:13Z ophirset $
00016 // 
00017 //
00018 // Author(s)     : Hans Tangelder (<hanst@cs.uu.nl>)
00019 
00020 #ifndef CGAL_ORTHOGONAL_K_NEIGHBOR_SEARCH_H
00021 #define CGAL_ORTHOGONAL_K_NEIGHBOR_SEARCH_H
00022 
00023 #include <cstring>
00024 #include <list>
00025 #include <queue>
00026 #include <set>
00027 #include <memory>
00028 #include <CGAL/Kd_tree_node.h>
00029 #include <CGAL/Kd_tree.h>
00030 #include <CGAL/Euclidean_distance.h>
00031 #include <CGAL/Splitters.h>
00032 
00033 namespace CGAL {
00034 
00035 template <class SearchTraits, 
00036           class Distance_= Euclidean_distance<SearchTraits>,
00037           class Splitter_= Sliding_midpoint<SearchTraits> ,
00038           class Tree_= Kd_tree<SearchTraits, Splitter_, Tag_true> >
00039 class Orthogonal_k_neighbor_search {
00040 
00041 public:
00042 
00043   typedef Splitter_ Splitter;
00044   typedef Tree_  Tree;
00045   typedef Distance_ Distance;
00046   typedef typename SearchTraits::Point_d Point_d;
00047   typedef typename Distance::Query_item Query_item;
00048 
00049   typedef typename SearchTraits::FT FT;
00050   typedef std::pair<Point_d,FT> Point_with_transformed_distance;
00051 
00052   typedef typename Tree::Node_handle Node_handle;
00053 
00054   typedef typename Tree::Point_d_iterator Point_d_iterator;
00055 
00056 private:
00057 
00058   // Comparison functor to sort a set of points
00059   // in increasing or decreasing order (key is distance).
00060   class Distance_larger 
00061   {
00062     bool search_nearest;
00063 
00064   public:
00065 
00066     Distance_larger(bool search_the_nearest_neighbour) 
00067       : search_nearest(search_the_nearest_neighbour)
00068     {}
00069 
00070     bool operator()(const Point_with_transformed_distance& p1, 
00071                     const Point_with_transformed_distance& p2) const  
00072     {
00073       if (search_nearest)
00074         return (p1.second < p2.second);
00075       else
00076         return (p2.second < p1.second);
00077     }
00078   };
00079   
00080   // Set of points, sorted by distance, in increasing or decreasing order.
00081   typedef std::set<Point_with_transformed_distance, Distance_larger> NN_list;
00082 
00083 public:
00084 
00085   typedef typename NN_list::const_iterator iterator;
00086 
00087 private:
00088 
00089   int number_of_internal_nodes_visited;
00090   int number_of_leaf_nodes_visited;
00091   int number_of_items_visited;
00092 
00093   bool search_nearest;
00094 
00095   FT multiplication_factor;
00096   Query_item query_object;
00097   int total_item_number;
00098   FT distance_to_root;   
00099 
00100   NN_list l; // Set of points, sorted by distance
00101   unsigned int max_k;
00102   
00103   Distance distance_instance;
00104 
00105 private:
00106 
00107   // Test if we should continue searching 
00108   inline bool branch(FT distance) 
00109   {
00110     if (l.size()<max_k) 
00111       return true;
00112     else 
00113       if (search_nearest) 
00114         return (distance*multiplication_factor < (--l.end())->second);
00115       else 
00116         return (distance > l.begin()->second*multiplication_factor);
00117   }
00118 
00119   // Try to insert point *I
00120   void insert(Point_d* I, FT dist) 
00121   {
00122     // Shall we insert I?
00123     bool insert;
00124     if (l.size()<max_k) 
00125       insert=true;
00126     else if (search_nearest) 
00127       insert = ( dist < (--l.end())->second ); 
00128     else 
00129       insert=(dist > (--l.end())->second);
00130       
00131     if (insert) 
00132     {
00133       Point_with_transformed_distance NN_Candidate(*I,dist);
00134       l.insert(NN_Candidate);
00135       if (l.size() > max_k)
00136         l.erase(--l.end()); 
00137     }
00138   }
00139 
00140 
00141 public:
00142 
00143   iterator begin() const
00144   {
00145     return l.begin();
00146   }
00147 
00148   iterator end() const
00149   {
00150     return l.end();
00151   }
00152 
00153 
00154   // constructor
00155   Orthogonal_k_neighbor_search(Tree& tree, const Query_item& q,  
00156     unsigned int k=1, FT Eps=FT(0.0), bool Search_nearest=true, const Distance& d=Distance())
00157     : number_of_internal_nodes_visited(0), number_of_leaf_nodes_visited(0), number_of_items_visited(0), 
00158     search_nearest(Search_nearest), multiplication_factor(d.transformed_distance(1.0+Eps)), query_object(q), 
00159     total_item_number(tree.size()), l(Distance_larger(Search_nearest)), max_k(k), distance_instance(d) 
00160 
00161   {
00162     if (search_nearest) 
00163       distance_to_root = d.min_distance_to_rectangle(q, tree.bounding_box());
00164     else 
00165       distance_to_root = d.max_distance_to_rectangle(q, tree.bounding_box());
00166 
00167     compute_neighbors_orthogonally(tree.root(), distance_to_root);
00168 
00169   }
00170 
00171 
00172   // Print statistics of the k_neighbor search process.
00173   std::ostream& statistics (std::ostream& s) 
00174   {
00175     s << "K_Neighbor search statistics:" << std::endl;
00176     s << "Number of internal nodes visited:" 
00177       << number_of_internal_nodes_visited << std::endl;
00178     s << "Number of leaf nodes visited:" 
00179       << number_of_leaf_nodes_visited << std::endl;
00180     s << "Number of items visited:" 
00181       << number_of_items_visited << std::endl;
00182     return s;
00183   }
00184 
00185 
00186 
00187 private:
00188 
00189   void compute_neighbors_orthogonally(Node_handle N, FT rd)
00190   {
00191     typename SearchTraits::Construct_cartesian_const_iterator_d construct_it;
00192     typename SearchTraits::Cartesian_const_iterator_d query_object_it = construct_it(query_object);
00193     if (!(N->is_leaf())) 
00194     {
00195       number_of_internal_nodes_visited++;
00196       int new_cut_dim=N->cutting_dimension();
00197       FT old_off, new_rd;
00198       FT new_off = *(query_object_it + new_cut_dim) - N->cutting_value();
00199       if ( ((new_off <  FT(0.0)) && (search_nearest)) ||
00200            ((new_off >= FT(0.0)) && (!search_nearest)) ) 
00201       {
00202         compute_neighbors_orthogonally(N->lower(),rd);
00203         if (search_nearest) {
00204           old_off= *(query_object_it + new_cut_dim) - N->low_value();
00205           if (old_off>FT(0.0)) 
00206             old_off=FT(0.0);
00207         }
00208         else {  
00209           old_off= *(query_object_it + new_cut_dim) - N->high_value();
00210           if (old_off<FT(0.0)) 
00211             old_off=FT(0.0);
00212         }
00213         new_rd = distance_instance.new_distance(rd,old_off,new_off,new_cut_dim);
00214         if (branch(new_rd)) 
00215           compute_neighbors_orthogonally(N->upper(), new_rd);                               
00216       }
00217       else // compute new distance
00218       {
00219         compute_neighbors_orthogonally(N->upper(),rd); 
00220         if (search_nearest) {
00221           old_off= N->high_value() - *(query_object_it + new_cut_dim);
00222           if (old_off>FT(0.0)) 
00223             old_off=FT(0.0);
00224         }
00225         else  {       
00226           old_off= N->low_value() - *(query_object_it + new_cut_dim);
00227           if (old_off<FT(0.0)) 
00228             old_off=FT(0.0);
00229         }  
00230         new_rd = distance_instance. new_distance(rd,old_off,new_off,new_cut_dim);
00231         if (branch(new_rd)) 
00232           compute_neighbors_orthogonally(N->lower(), new_rd);       
00233       }
00234     }
00235     else
00236     {
00237       // n is a leaf
00238       number_of_leaf_nodes_visited++;
00239       if (N->size() > 0)
00240       {
00241         for (Point_d_iterator it=N->begin(); it != N->end(); it++) 
00242         {
00243           number_of_items_visited++;
00244           FT distance_to_query_object=
00245             distance_instance.transformed_distance(query_object,**it);
00246           insert(*it,distance_to_query_object);
00247         }
00248       }
00249     }
00250   }
00251 
00252 }; // class 
00253 
00254 } // namespace CGAL
00255 
00256 #endif  // CGAL_ORTHOGONAL_K_NEIGHBOR_SEARCH_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines