|
Space-efficient geometric algorithms and data structuresBy Ilya Katz and Hervé Brönnimann |
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.