Space-efficient geometric algorithms and data structures

By Ilya Katz and Hervé Brönnimann    

intersection.hpp

Go to the documentation of this file.
00001 #include <bits/stl_tree.h>
00002 //#include "my_tree.hpp"
00003 #include "explicit_tree_heap.hpp"
00004 #include "cgl.hpp"
00005 #include <queue>
00006 #include <utility>
00007 
00008 using namespace std;
00009 using namespace inplaceds;
00010 //using namespace inplaceds::tree;
00011 
00012 typedef cgl<int> Geometry;
00013 typedef Geometry::line_type line_type;
00014 typedef Geometry::point_type point_type;
00015 typedef Geometry::coord_type coord_type;
00016 typedef DataNode<Geometry> node;
00017 
00018 int SWEEP_LINE_COORD=-100; 
00019 
00020 template <class Geometry>
00021 struct PQComp
00022 {
00023         typedef DataNode<Geometry>*     node_type;
00024         typedef typename Geometry::line_type    line_type;
00025 
00026         bool operator()(const node_type& a, const node_type& b){
00027                 return !geom.less_x_object()(a->point,b->point);
00028         }
00029 
00030         Geometry geom;
00031 
00032 };
00033 
00034 template <class type>
00035 struct kov
00036 {
00037 
00038         const type& operator()(const type& a)const{return a;}
00039         type& operator()( type& a){return a;}
00040 };
00041 
00046 #define slope(x1,y1,x2,y2) ( (y2-y1)/(x2-x1) )
00047 
00048 template <class Geometry>
00049 struct BSTComp
00050 {
00051         typedef typename Geometry::line_type    line_type;
00052         typedef typename Geometry::coord_type   coord_type;
00053         typedef DataNode<Geometry>                              node;
00054 
00055         bool operator()(const node& a, const node& b){
00056                 return operator()(a.line, b.line);
00057         }
00058 
00059         bool operator()( const node* const& a, const node* const& b){
00060                 return operator()(a->line, b->line);
00061         }
00062 
00063         bool operator()(const line_type& a, const line_type& b){
00064 
00065                 //two lines are equal
00066                 if(a[0][0]==b[0][0] && a[0][1]==b[0][1] &&
00067                         a[1][0]==b[1][0] && a[1][1]==b[1][1]){
00068                                 return false;
00069                         }
00070 
00071                 //else, need to check which line is has higher
00072                 //y-coordinate at the current sweepline position
00073 
00074                 coord_type currentY1 =
00075                         slope(a[0][0],a[0][1], a[1][0], a[1][1])*SWEEP_LINE_COORD + a[0][0],
00076                                          currentY2 =
00077                         slope(b[0][0],b[0][1], b[1][0], b[1][1])*SWEEP_LINE_COORD + b[0][0];
00078 
00079                 return currentY1<currentY2;
00080 
00081         }
00082 
00083         Geometry geom;
00084 };
00085 
00086 typedef _Rb_tree<node*, node*, kov<node*>, BSTComp<Geometry> > tree_type;
00087 typedef priority_queue<node*, vector<node*>, PQComp<Geometry> > priority_queue_type;
00088 
00089 std::pair<bool, point_type> intersection(const line_type& l1, const line_type& l2);
00090 void update_event(node*,node*,priority_queue_type&);
00091 void intersection(vector<line_type>);
00092 
00093 /*
00094  * temporary, for convience
00095  */
00096 
00097 ostream& operator<<(ostream& os, node* x)
00098 {
00099         os<<x->line<<" E:"<<int(x->myEvent);
00100         return os;
00101 }
00102 
00109 void intersection(vector<line_type> all_lines){
00110 
00111         Geometry geom;
00112 
00113         //initialize T and Q
00114         tree_type T;
00115         priority_queue_type Q;
00116 
00117         tree_type::iterator tree_it, tree_it_prev, tree_it_next;
00118 
00119         for(vector<line_type>::iterator it = all_lines.begin(); it!=all_lines.end(); it++){
00120                 Q.push(new node(*it,LEFT_EVENT));
00121         }
00122 
00123         //move sweepline to e (leftmost event)
00124 
00125 
00126         node* current = Q.top();
00127         cerr<<"Q size "<<Q.size()<<endl;
00128         SWEEP_LINE_COORD = current->point[0];
00129 
00130 
00131         //the problem with this code is that
00132         //T.find is using the BSTComp functor that
00133         //compares using the current value of the sweep_line
00134                 while(!Q.empty()){
00135                 Q.pop();
00136                 switch(current->myEvent){
00137                         case(LEFT_EVENT):
00138                                 tree_it = T.insert_equal(current);              //insert line into T
00139                                 tree_it_next=tree_it_prev=tree_it;
00140                                 cerr<<"Inserted in T"<<*tree_it<<endl;
00141 
00142                                 tree_it_next++;
00143                                 if(!(tree_it_next==T.end())){
00144                                         update_event(*tree_it, *tree_it_next, Q);
00145                                 }else{
00146                                         (*tree_it)->right_event();
00147                                         Q.push(*tree_it);
00148                                 }
00149 
00150                                 if(!(tree_it==T.begin())){
00151                                         tree_it_prev--;
00152                                         cerr<<"Updating previous:"<<*tree_it_prev<<endl;
00153                                         update_event(*tree_it_prev, *tree_it, Q);       //update previous line event
00154                                 }
00155                                 break;
00156                         case(RIGHT_EVENT):
00157                                 tree_it = T.find(current);
00158                                 if(tree_it==T.end()){
00159                                         cerr<<"Couldnt find "<<current;
00160                                         exit(-1);
00161                                 }
00162                                 tree_it_next =tree_it;
00163                                 tree_it_next++;
00164                                 cerr<<"Removing from T:"<<*tree_it<<endl;
00165                                 T.erase(tree_it, tree_it_next);                 //remove line from T
00166                                 cerr<<"Removed from T"<<endl;
00167                                 if(!(tree_it==T.begin())){
00168                                         tree_it_prev = tree_it;
00169                                         tree_it_prev--;
00170                                         update_event(*tree_it_prev, *tree_it,Q);        //update previous line event
00171                                 }
00172                                 break;
00173                         case(INTERSECTION_EVENT):
00174                                 cout<<"Got one!"<<endl;
00175                                 cout<<current->line<<" and "<<current->intersecting->line<<endl;
00176                                 tree_it = T.find(current);
00177                                 cerr<<"T is now:"<<endl;
00178                                 copy(T.begin(), T.end(), ostream_iterator<node*>(cerr, " "));
00179                                 cerr<<endl;
00180                                 if(tree_it==T.end()){
00181                                         cerr<<"Couldnt find "<<current;
00182                                         exit(-1);
00183                                 }
00184 
00185                                 tree_it_prev = tree_it_next = tree_it;
00186 
00187 
00188 
00189                                 tree_it_next++;
00190                                 if(tree_it_next!=T.end()){
00191                                         std::swap(*tree_it, *tree_it_next);                     //switch order of current and next - check if this is correct!
00192                                         cerr<<"Swapped"<<endl;
00193                                 }
00194 
00195 
00196 
00197                                 if(!(tree_it==T.begin())){
00198                                         cerr<<"Updating prev "<<endl;
00199                                         tree_it_prev--;
00200                                         update_event(*tree_it_prev, *tree_it,Q);                //update previous line event
00201                                         cerr<<"Updated prev "<<endl;
00202                                 }
00203                                 cerr<<(tree_it_next==T.end())<<(tree_it==T.end());
00204                                 if(tree_it_next!=T.end()){
00205                                         cerr<<"Updating curr "<<endl;//<<*tree_it<<" "<<endl;
00206                                         update_event(*tree_it, *tree_it_next,Q);                //update current line event
00207                                         cerr<<"Updated curr "<<endl;
00208                                 }
00209 
00210                                 tree_it = tree_it_next;
00211                                 tree_it_next++;
00212                                 if(!(tree_it==T.end() || tree_it_next==T.end())){
00213                                         cerr<<"Updating next "<<endl;
00214                                         update_event(*tree_it, *(tree_it_next),Q);      //update next line event
00215                                         cerr<<"Updated next "<<endl;
00216                                 }
00217                                 cerr<<"ended intersection case"<<endl;
00218                                 break;
00219                 }
00220                 current = Q.top();
00221                 SWEEP_LINE_COORD = current->point[0];
00222         }
00223 
00224 }
00225 
00232 void update_event(node* current, node* next, priority_queue_type& Q){
00233 
00234         //if there is an intersection point and it is to the right of the sweepline,
00235         // enter it here, otherwise right-end point
00236 
00237         std::pair<bool, point_type> inter = intersection(current->line, next->line);
00238 
00239         if(!inter.first){ //right-end
00240                 current->right_event();
00241         }
00242         else if(inter.second[0]>=SWEEP_LINE_COORD){ 
00243                 current->intersection_event(inter.second, next);
00244         }
00245         Q.push(current);
00246 }
00247 
00248 
00260 std::pair<bool, point_type> intersection(const line_type& l1, const line_type& l2){
00261 
00262         std::pair<bool, point_type> ret(false, point_type());
00263 
00264         int m1 = slope(l1[0][0], l1[0][1], l1[1][0], l1[1][1]),
00265                         m2 = slope(l2[0][0], l2[0][1], l2[1][0], l2[1][1]);
00266 
00267         if(m1 == m2){  //lines are parallel
00268                 return ret;
00269         }
00270 
00271         coord_type b1 = l1[0][1]-m1*l1[0][0],
00272                                  b2 = l2[0][1]-m2*l2[0][0];
00273 
00274         coord_type x = (b2-b1)/(m1-m2);
00275 
00276 
00277         //originally, the left end point is at position [0]
00278         //but, beacuse of encoding intersection, these positions
00279         //may have changed
00280         if(x<std::min(l1[0][0],l1[1][0]) || x>std::max(l1[0][0],l1[1][0]) ||
00281                  x<std::min(l2[0][0],l2[1][0]) || x>std::max(l2[0][0],l2[1][0])){
00282                 return ret;
00283         }
00284 
00285         coord_type y1 = m1 * x + b1;
00286         coord_type y2 = m2 * x + b2;
00287 
00288         if(!(y1==y2)){
00289                 return ret;
00290         }
00291         ret.second[0]=x;
00292         ret.second[1]=y1;
00293         ret.first=true;
00294 
00295         return ret;
00296 
00297 }

Code Documentation generated Using Doxygen

Copyright © Ilya Katz and Hervé Brönnimann, 2005.