Bentley-Otmann Algorithm 2.0
An implementation of Bentley-Ottmann algorithm in order to count the m,n-cubes
|
00001 00101 #include "structures.hpp" 00102 #include "geometry.hpp" 00103 #include "bentley_ottmann.hpp" 00104 #include <iostream> 00105 #include <utility> 00106 #include <iterator> 00107 #include <algorithm> 00108 00118 map_event bentley_ottmann(std::vector<Segment>& set) { 00119 map_event inter; 00120 //std::cout << "Map : declared\n"; 00121 // priority queue : insert all endpoints 00122 PriorityQueue<Event, Segment*> queue; 00123 00124 std::vector<Segment>::iterator it; 00125 for(it = set.begin(); it != set.end(); it++) { 00126 Event e_left(it->get_left()), e_right(it->get_right()); 00127 queue.push(e_left, &(*it)), queue.push(e_right); 00128 } 00129 00130 // binary search tree : empty 00131 Point p_sweep(rat(I(0)),rat(I(0))); 00132 compare<Segment,Point> comp(&p_sweep); 00133 BST<Segment,Point>::Type btree(comp); 00134 00135 // treatment of events 00136 while(queue.size()) { 00137 // current event : p event on top of set 00138 Event p = queue.top(); 00139 Point point = p.get_point(); 00140 vector_seg l_set = queue.begin()->second; 00141 queue.pop(); 00142 00143 p_sweep.assign(point.get_abscissa(), point.get_ordinate()); 00144 00145 //checking for intersection 00146 std::pair<vector_seg, vector_seg> ir_set = get_sets(point, btree); 00147 00148 if(l_set.size() + ir_set.first.size() + ir_set.second.size() > 1) { 00149 map_event::iterator it_ev = (inter.insert(pair_event(p, vector_seg()))).first; 00150 00151 //it_ev->second : union of l_set, ir_set.first and ir_set.second 00152 vector_seg::iterator it_seg = l_set.begin(); 00153 for(; it_seg != l_set.end(); it_ev->second.push_back(*it_seg++)); 00154 for(it_seg = ir_set.first.begin(); it_seg != ir_set.first.end(); 00155 it_ev->second.push_back(*it_seg++)); 00156 for(it_seg = ir_set.second.begin(); it_seg != ir_set.second.end(); 00157 it_ev->second.push_back(*it_seg++)); 00158 //std::cout << it_ev->second << "\n"; 00159 } 00160 00161 00162 //delete ir_set.first and ir_set.second from btree 00163 vector_seg::iterator it_seg = ir_set.first.begin(); 00164 for(; it_seg != ir_set.first.end(); btree.erase(*it_seg++)); 00165 for(it_seg = ir_set.second.begin(); it_seg != ir_set.second.end(); 00166 btree.erase(*it_seg++)); 00167 00168 //update sl 00169 p_sweep.assign(point.get_abscissa(), point.get_ordinate()); 00170 00171 //insert l_set and ir_set.first in btree 00172 for(it_seg = l_set.begin(); it_seg != l_set.end(); 00173 btree.insert(*it_seg++)); 00174 for(it_seg = ir_set.first.begin(); it_seg != ir_set.first.end(); 00175 btree.insert(*it_seg++)); 00176 00177 //treat new events 00178 if(l_set.size() + ir_set.first.size() == 0) { 00179 //p is only the rightpoint of several segments 00180 Segment* s_a, * s_b; 00181 find_neighboors(point, btree, s_a, s_b); 00182 00183 compute_new_events(s_a, s_b, p, queue); 00184 } 00185 00186 else { 00187 vector_seg v(l_set.size() + ir_set.first.size()); 00188 set_union(l_set.begin(), l_set.end(), 00189 ir_set.first.begin(), ir_set.first.end(), v.begin()); 00190 Segment* sl = find_leftmost(v, point), * sr = find_rightmost(v, point); 00191 Segment* s_b = find_left_neighboor(sl, btree), * s_a = find_right_neighboor(sr, btree); 00192 00193 compute_new_events(sl, s_b, p, queue); compute_new_events(sr, s_a, p, queue); 00194 } 00195 } 00196 00197 return inter; 00198 } 00199 00213 void find_neighboors(const Point& p, BST<Segment,Point>::Type& btree, 00214 Segment*& above, Segment*& below) { 00215 //create a segment of length 0 representing p : 00216 rat x = p.get_abscissa(), y = p.get_ordinate(); 00217 Segment s(x, y, x, y); 00218 00219 //search for upper neighboor 00220 BST<Segment,Point>::Type::iterator it = btree.upper_bound(&s); 00221 00222 if(it == btree.end()) 00223 above = NULL; 00224 else 00225 above = *it; 00226 if(it == btree.begin()) 00227 below = NULL; 00228 else 00229 below = *--it; 00230 } 00231 00240 Segment* find_leftmost(vector_seg& v, const Point& p) { 00241 //asuming v isn't empty 00242 vector_seg::iterator it = v.begin(); 00243 Segment* min = *v.begin(); 00244 00245 while(++it != v.end()) { 00246 if((*it)->less(*min,p)) 00247 min = *it; 00248 } 00249 return min; 00250 } 00251 00260 Segment* find_rightmost(vector_seg& v, const Point& p) { 00261 //assuming v isn't empty 00262 vector_seg::iterator it = v.begin(); 00263 Segment* max = *v.begin(); 00264 00265 while(++it != v.end()) { 00266 if(max->less(**it,p)) 00267 max = *it; 00268 } 00269 return max; 00270 } 00271 00278 Segment* find_left_neighboor(Segment* s, BST<Segment,Point>::Type& btree) { 00279 BST<Segment,Point>::Type::iterator it = btree.find(s); 00280 if(it == btree.begin()) 00281 return NULL; 00282 else 00283 return *--it; 00284 } 00285 00292 Segment* find_right_neighboor(Segment* s, BST<Segment,Point>::Type& btree) { 00293 BST<Segment,Point>::Type::iterator it = btree.find(s); 00294 if(++it == btree.end()) 00295 return NULL; 00296 else 00297 return *it; 00298 } 00299 00320 std::pair<vector_seg, vector_seg> get_sets(const Point& p, BST<Segment,Point>::Type& btree) { 00321 vector_seg i,r; 00322 if(btree.empty()) 00323 return std::pair<vector_seg, vector_seg> (i,r); 00324 //create a segment of lentgh zero representing p : 00325 rat x = p.get_abscissa(), y = p.get_ordinate(); 00326 Segment* s = new Segment(x, y, x, y); 00327 00328 00329 BST<Segment,Point>::Type::iterator it = btree.upper_bound(s); 00330 std::reverse_iterator<BST<Segment,Point>::Type::iterator> rit(it); 00331 00332 Point q; 00333 while(rit != btree.rend() && (*rit)->high(p) == y) { 00334 if((*rit)->is_in(p)) 00335 i.push_back(*rit); 00336 else if((*rit)->is_rend(p)) 00337 r.push_back(*rit); 00338 rit++; 00339 } 00340 00341 return std::pair<vector_seg, vector_seg> (i,r); 00342 } 00343 00357 void compute_new_events(Segment* s0, Segment* s1, const Event& p, 00358 PriorityQueue<Event,Segment*>& q) { 00359 Point i; 00360 00361 if(s0 && s1 && s0->intersect(*s1, i)) { 00362 Event ev_i(i); 00363 if(p < ev_i && ! q.mem(ev_i)) 00364 q.push(ev_i); 00365 } 00366 }