BWAPI
|
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