Space-efficient geometric algorithms and data structures

By Ilya Katz and Hervé Brönnimann    

static_kd_tree.hpp

Go to the documentation of this file.
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.