|
Space-efficient geometric algorithms and data structuresBy Ilya Katz and Hervé Brönnimann |
00001 #ifndef STATIC_KD_TREE_HPP 00002 #define STATIC_KD_TREE_HPP 00003 00004 #include <iostream> 00005 #include <algorithm> 00006 00007 #include <boost/array.hpp> 00008 #include "cgl.hpp" 00009 00010 namespace inplaceds 00011 { 00012 00014 typedef cgl<int>::point_type point_type; 00016 00017 #define STATIC_KD_TREE_CUTOFF 16 00018 00022 template <class RandomAccessIterator, class AxisAlignedGeometry> 00023 void 00024 build_static_kdtree(RandomAccessIterator first, RandomAccessIterator last, AxisAlignedGeometry geom) 00025 { 00026 //stop recursing if minimum size is reached 00027 if(last - first < STATIC_KD_TREE_CUTOFF) 00028 { 00029 return; 00030 } 00031 00032 RandomAccessIterator mid = first + (last-first+1)/2 ; 00033 RandomAccessIterator Lmid = first + (mid-first+1)/2; 00034 RandomAccessIterator Rmid = mid + (last-mid+1)/2; 00035 00036 00037 //split by x coordinate 00038 std::nth_element (first, mid, last, geom.less_x_object() ); 00039 00040 00041 //split left half by y-coordniate 00042 std::nth_element (first, Lmid ,mid, geom.less_y_object() ); 00043 00044 //split right half by y-coordinate 00045 std::nth_element (mid+1, Rmid, last, geom.less_y_object() ); 00046 00047 //----recursive calls---- 00048 00049 //recursively partition Lbot 00050 build_static_kdtree(first, Lmid, geom); 00051 00052 //recursively partition Ltop 00053 build_static_kdtree(Lmid+1, mid, geom); 00054 00055 //recursively partition Rbot 00056 build_static_kdtree(mid+1, Rmid, geom); 00057 00058 //recursively partition Rtop 00059 build_static_kdtree(Rmid+1, last, geom); 00060 00061 } 00062 00072 template <class Box, class RandomAccessIterator, class OutputIterator, class AxisAlignedGeometry> 00073 OutputIterator 00074 window_query_static_kdtree(RandomAccessIterator first, RandomAccessIterator last, AxisAlignedGeometry geom, Box Q, OutputIterator result) 00075 { 00076 //if reached the lower limit, check each point individually 00077 if(last-first<STATIC_KD_TREE_CUTOFF) 00078 { 00079 for(RandomAccessIterator it = first; it!=last; it++) 00080 { 00081 if(geom.point_in_box(*it,Q)) 00082 { 00083 result = std::copy(it, it+1, result); 00084 } 00085 } 00086 return result; 00087 } 00088 00089 RandomAccessIterator mid = first + (last-first+1)/2 ; 00090 RandomAccessIterator Lmid = first + (mid-first+1)/2; 00091 RandomAccessIterator Rmid = mid + (last-mid+1)/2; 00092 00093 //in all of the following cases we need to use >= or <= because 00094 //it is possible that points that have the same coordinates 00095 //appear in different regions (eg. Lbot and Rbot) since the division 00096 //into region is done by sizes of each region 00097 //simple example, is when all points in input are the same 00098 00099 00100 //check if need to search quadrant Ltop 00101 //if the left x coordinate of Q is to the left of intersection point 00102 //and the y coordinate is above the intersection point 00103 if(geom.get_x_coordinate(*mid)>=geom.get_left(Q) && geom.get_y_coordinate(*Lmid)<=geom.get_top(Q)) 00104 { 00105 result = window_query_static_kdtree(Lmid+1, mid, geom, Q, result); 00106 } 00107 00108 //check if need to search quadrant Rtop 00109 //if the right x coordniate of Q is to the right of intersection point 00110 //and the top y coordinate is above the intersection point 00111 if(geom.get_x_coordinate(*mid)<= geom.upper_right(Q)[0] && geom.get_y_coordinate(*Rmid)<=geom.upper_right(Q)[1]) 00112 { 00113 result = window_query_static_kdtree(Rmid+1, last, geom, Q, result); 00114 } 00115 00116 //check if need to search quadrant Lbottom 00117 //if the left x coordniate of Q is to the left of intersection point 00118 //and the bottom y coordinate is below the interscation point 00119 if(geom.get_x_coordinate(*mid)>=geom.get_left(Q) && geom.get_y_coordinate(*Lmid)>=geom.get_bottom(Q)) 00120 { 00121 result = window_query_static_kdtree(first, Lmid, geom,Q, result); 00122 } 00123 00124 //check if need to search quadrant Rbottom 00125 //if the right of Q is to the right of intersection point 00126 //and the bottom of Q is below the intersection point 00127 if(geom.get_x_coordinate(*mid)<=geom.get_right(Q) && geom.get_y_coordinate(*Rmid)>=geom.get_bottom(Q)) 00128 { 00129 result = window_query_static_kdtree(mid+1, Rmid, geom,Q, result); 00130 } 00131 00132 //mid, Lmid, and Rmid are considered independently 00133 //because these points are the immovable roots of the corresponding regions 00134 if(geom.point_in_box(*mid, Q)) 00135 { 00136 result = std::copy(mid, mid+1, result); 00137 } 00138 if(geom.point_in_box(*Rmid, Q)) 00139 { 00140 result = std::copy(Rmid, Rmid+1, result); 00141 } 00142 if(geom.point_in_box(*Lmid, Q)) 00143 { 00144 result = std::copy(Lmid, Lmid+1, result); 00145 } 00146 00147 return result; 00148 } 00149 00159 template <class Halfplane, class RandomAccessIterator, class OutputIterator, class AxisAlignedGeometry> 00160 OutputIterator 00161 halfplane_query_static_kdtree(RandomAccessIterator first, RandomAccessIterator last, 00162 AxisAlignedGeometry geom, Halfplane H, OutputIterator result) 00163 { 00164 00165 #define H_p1 geom.get_halfplane_points(H)[0] 00166 #define H_p2 geom.get_halfplane_points(H)[1] 00167 00168 00169 //if reached the lower limit, check each point individually 00170 00171 00172 if(last-first<STATIC_KD_TREE_CUTOFF) 00173 { 00174 for(RandomAccessIterator it = first; it!=last; it++) 00175 { 00176 //cout<<geom.get_x_coordinate(*it)<<","<< geom.get_y_coordinate(*it)<<") - "<<it-first; 00177 00178 if(geom.point_in_halfplane(*it,H)) 00179 { 00180 result = std::copy(it, it+1, result); 00181 //cout<<"#"; 00182 } 00183 //cout<<endl; 00184 } 00185 //cout<<endl; 00186 return result; 00187 } 00188 00189 RandomAccessIterator mid = first + (last-first+1)/2 ; 00190 RandomAccessIterator Lmid = first + (mid-first+1)/2; 00191 RandomAccessIterator Rmid = mid + (last-mid+1)/2; 00192 00193 #define left_intersection_point geom.make_point(geom.get_x_coordinate(*mid), geom.get_y_coordinate(*Lmid)) 00194 #define right_intersection_point geom.make_point(geom.get_x_coordinate(*mid), geom.get_y_coordinate(*Rmid)) 00195 00196 //check if need to search quadrant Ltop 00197 //if the point is not in the plane and the plane is poiting down 00198 //do not needs to check Ltop if the first point is lower then the 00199 //second points 00200 if( !( 00201 !geom.point_in_halfplane(left_intersection_point, H) && 00202 geom.is_BOTTOM(H) && 00203 geom.less_y_object()(H_p1,H_p2) 00204 ) 00205 ) 00206 { 00207 result = halfplane_query_static_kdtree(Lmid+1, mid, geom, H, result); 00208 } 00209 00210 //check if need to search quadrant Rtop 00211 if(!( 00212 !geom.point_in_halfplane(right_intersection_point, H) && 00213 geom.is_BOTTOM(H) && 00214 geom.less_y_object()(H_p2,H_p1) 00215 ) 00216 ) 00217 { 00218 result = halfplane_query_static_kdtree(Rmid+1, last, geom, H, result); 00219 } 00220 00221 //check if need to search quadrant Lbottom 00222 if( !( 00223 !geom.point_in_halfplane(left_intersection_point, H) && 00224 geom.is_TOP(H) && 00225 geom.less_y_object()(H_p2,H_p1) 00226 ) 00227 ) 00228 { 00229 result = halfplane_query_static_kdtree(first+1, Lmid, geom,H, result); 00230 } 00231 00232 //check if need to search quadrant Rbottom 00233 if(!( 00234 !geom.point_in_halfplane(right_intersection_point, H) && 00235 geom.is_TOP(H) && 00236 geom.less_y_object()(H_p1,H_p2) 00237 ) 00238 ) 00239 { 00240 result = halfplane_query_static_kdtree(mid+1, Rmid, geom, H, result); 00241 } 00242 //critical points are considered independently 00243 //because these points are the immovable roots of the corresponding regions 00244 if(geom.point_in_halfplane(*mid, H)) 00245 { 00246 result = std::copy(mid, mid+1, result); 00247 } 00248 if(geom.point_in_halfplane(*first, H)) 00249 { 00250 result = std::copy(first, first+1, result); 00251 } 00252 if(geom.point_in_halfplane(*Rmid, H)) 00253 { 00254 result = std::copy(Rmid, Rmid+1, result); 00255 } 00256 if(geom.point_in_halfplane(*Lmid, H)) 00257 { 00258 result = std::copy(Lmid, Lmid+1, result); 00259 } 00260 00261 #undef H_p1 00262 #undef H_p2 00263 #undef left_intersection_point 00264 #undef right_intersection_point 00265 00266 return result; 00267 00268 } 00269 00280 template <class Box, class RandomAccessIterator, class OutputIterator, class AxisAlignedGeometry> 00281 OutputIterator 00282 closed_triangle_query_static_kdtree(RandomAccessIterator first, RandomAccessIterator last, AxisAlignedGeometry geom, Box Q, OutputIterator result) 00283 { 00284 //if reached the lower limit, check each point individually 00285 if(last-first<STATIC_KD_TREE_CUTOFF) 00286 { 00287 for(RandomAccessIterator it = first; it!=last; it++) 00288 { 00289 if(geom.point_in_closed_triangle(*it,T)) 00290 { 00291 result = std::copy(it, it+1, result); 00292 } 00293 } 00294 return result; 00295 } 00296 00297 RandomAccessIterator mid = first + (last-first+1)/2 ; 00298 RandomAccessIterator Lmid = first + (mid-first+1)/2; 00299 RandomAccessIterator Rmid = mid + (last-mid+1)/2; 00300 00301 //check if need to search quadrant Ltop 00302 if() 00303 { 00304 result = closed_triangle_query_static_kdtree(Lmid, mid, geom, Q, result); 00305 } 00306 00307 //check if need to search quadrant Rtop 00308 if() 00309 { 00310 result = window_query_static_kdtree(Rmid, last, geom, Q, result); 00311 } 00312 00313 //check if need to search quadrant Lbottom 00314 if() 00315 { 00316 result = window_query_static_kdtree(first, Lmid, geom,Q, result); 00317 } 00318 00319 //check if need to search quadrant Rbottom 00320 if() 00321 { 00322 result = window_query_static_kdtree(mid, Rmid, geom,Q, result); 00323 } 00324 00325 return result; 00326 } 00327 00328 }//namespace 00329 #endif
Code Documentation generated Using Doxygen
Copyright © Ilya Katz and Hervé Brönnimann, 2005, 2006.