|
BWAPI
|
00001 // Copyright (c) 1997-2000 Max-Planck-Institute Saarbruecken (Germany). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under 00005 // the terms of the Q Public License version 1.0. 00006 // See the file LICENSE.QPL distributed with CGAL. 00007 // 00008 // Licensees holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Nef_2/include/CGAL/Nef_2/Segment_overlay_traits.h $ 00015 // $Id: Segment_overlay_traits.h 43817 2008-06-27 10:02:41Z hachenb $ 00016 // 00017 // 00018 // Author(s) : Michael Seel <seel@mpi-sb.mpg.de> 00019 #ifndef CGAL_SEGMENT_OVERLAY_TRAITS_H 00020 #define CGAL_SEGMENT_OVERLAY_TRAITS_H 00021 00022 #undef CGAL_NEF_DEBUG 00023 #define CGAL_NEF_DEBUG 23 00024 #include <CGAL/Nef_2/debug.h> 00025 00026 #if defined(CGAL_USE_LEDA) 00027 #include <CGAL/LEDA_basic.h> 00028 #if CGAL_LEDA_VERSION < 500 00029 #include <LEDA/tuple.h> 00030 #include <LEDA/slist.h> 00031 #include <LEDA/list.h> 00032 #include <LEDA/map.h> 00033 #include <LEDA/map2.h> 00034 #include <LEDA/sortseq.h> 00035 #include <LEDA/p_queue.h> 00036 #include <LEDA/impl/ab_tree.h> 00037 #include <LEDA/impl/bb_tree.h> 00038 #include <LEDA/impl/rb_tree.h> 00039 #include <LEDA/impl/rs_tree.h> 00040 #include <LEDA/impl/skiplist.h> 00041 #else 00042 #include <LEDA/core/tuple.h> 00043 #include <LEDA/core/slist.h> 00044 #include <LEDA/core/list.h> 00045 #include <LEDA/core/map.h> 00046 #include <LEDA/core/map2.h> 00047 #include <LEDA/core/sortseq.h> 00048 #include <LEDA/core/p_queue.h> 00049 #include <LEDA/core/impl/ab_tree.h> 00050 #include <LEDA/core/impl/bb_tree.h> 00051 #include <LEDA/core/impl/rb_tree.h> 00052 #include <LEDA/core/impl/rs_tree.h> 00053 #include <LEDA/core/impl/skiplist.h> 00054 #endif 00055 #include <utility> 00056 #include <sstream> 00057 00058 namespace CGAL { 00059 #ifdef CGAL_NEF_DEBUG 00060 #define PIS(s) (s->first()) 00061 #endif 00062 00063 template <typename IT, typename PMDEC, typename GEOM> 00064 class leda_seg_overlay_traits { 00065 public: 00066 typedef IT ITERATOR; 00067 typedef std::pair<IT,IT> INPUT; 00068 typedef PMDEC OUTPUT; 00069 typedef typename PMDEC::Vertex_handle Vertex_handle; 00070 typedef typename PMDEC::Halfedge_handle Halfedge_handle; 00071 typedef GEOM GEOMETRY; 00072 typedef typename GEOMETRY::Point_2 Point_2; 00073 typedef typename GEOMETRY::Segment_2 Segment_2; 00074 00075 typedef leda_two_tuple<Segment_2,ITERATOR> seg_pair; 00076 typedef seg_pair* ISegment; 00077 typedef leda_list<seg_pair> IList; 00078 typedef typename IList::iterator ilist_iterator; 00079 00080 00081 // types interfacing the generic sweep frame: 00082 ITERATOR its, ite; 00083 OUTPUT& GO; 00084 const GEOMETRY& K; 00085 00086 class cmp_segs_at_sweepline : public CGAL_LEDA_SCOPE::leda_cmp_base<ISegment> 00087 { const Point_2& p; 00088 ISegment s_bottom, s_top; // sentinel segments 00089 const GEOMETRY& K; 00090 public: 00091 cmp_segs_at_sweepline(const Point_2& pi, 00092 ISegment s1, ISegment s2, const GEOMETRY& k) : 00093 p(pi), s_bottom(s1), s_top(s2), K(k) {} 00094 00095 int operator()(const ISegment& is1, const ISegment& is2) const 00096 { // Precondition: p is identical to the left endpoint of s1 or s2. 00097 if ( is2 == s_top || is1 == s_bottom ) return -1; 00098 if ( is1 == s_top || is2 == s_bottom ) return 1; 00099 if ( is1 == is2 ) return 0; 00100 const Segment_2& s1 = is1->first(); 00101 const Segment_2& s2 = is2->first(); 00102 int s = 0; 00103 if ( p == K.source(s1) ) s = K.orientation(s2,p); 00104 else if ( p == K.source(s2) ) s = - K.orientation(s1,p); 00105 else CGAL_error_msg("compare error in sweep."); 00106 if ( s || K.is_degenerate(s1) || K.is_degenerate(s2) ) 00107 return s; 00108 00109 s = K.orientation(s2,K.target(s1)); 00110 if (s==0) return ( is1 - is2 ); 00111 // overlapping segments are not equal 00112 return s; 00113 } 00114 }; 00115 00116 struct cmp_pnts_xy : public CGAL_LEDA_SCOPE::leda_cmp_base<Point_2> 00117 { const GEOMETRY& K; 00118 public: 00119 cmp_pnts_xy(const GEOMETRY& k) : K(k) {} 00120 int operator()(const Point_2& p1, const Point_2& p2) const 00121 { return K.compare_xy(p1,p2); } 00122 }; 00123 00124 // typedef CGAL_LEDA_SCOPE::skiplist SearchTree; 00125 // typedef typename SearchTree::item ST_item; 00126 typedef CGAL_LEDA_SCOPE::seq_item ST_item; 00127 typedef leda_sortseq<Point_2, ST_item> EventQueue; 00128 typedef leda_sortseq<ISegment, ST_item> SweepStatus; 00129 typedef leda_p_queue<Point_2,ISegment> SegQueue; 00130 typedef leda_map<ST_item,Halfedge_handle> AssocEdgeMap; 00131 typedef leda_slist<ITERATOR> IsoList; 00132 typedef typename IsoList::item slist_item; 00133 typedef leda_map<ST_item, IsoList* > AssocIsoMap; 00134 typedef leda_map2<ISegment,ISegment,ST_item> EventHash; 00135 00136 00137 ST_item event; 00138 Point_2 p_sweep; 00139 cmp_pnts_xy cmp; 00140 EventQueue XS; 00141 seg_pair sl,sh; 00142 cmp_segs_at_sweepline SLcmp; 00143 SweepStatus YS; 00144 SegQueue SQ; 00145 00146 EventHash IEvent; 00147 IList Internal; 00148 AssocEdgeMap Edge_of; 00149 AssocIsoMap Isos_of; 00150 00151 leda_seg_overlay_traits(const INPUT& in, OUTPUT& G, 00152 const GEOMETRY& k) : 00153 its(in.first), ite(in.second), GO(G), K(k), 00154 cmp(K), XS(cmp), SLcmp(p_sweep,&sl,&sh,K), YS(SLcmp), SQ(cmp), 00155 IEvent(0), Edge_of(0), Isos_of(0) {} 00156 00157 00158 leda_string dump_structures() const 00159 { 00160 std::ostringstream out; 00161 out << "SQ= "; 00162 CGAL_LEDA_SCOPE::pq_item pqit; 00163 forall_items(pqit,SQ) { 00164 if (SQ.prio(pqit)==XS.key(XS.succ(XS.min_item()))) 00165 { out << SQ.inf(pqit)->first(); } 00166 pqit = SQ.next_item(pqit); 00167 } 00168 ST_item sit; 00169 out << "\nXS=\n"; 00170 forall_items(sit,XS) 00171 out << " " << XS.key(sit) << " " << XS.inf(sit) 00172 <<std::endl; 00173 out << "YS=\n"; 00174 for( sit = YS.max_item(); sit; sit=YS.pred(sit) ) 00175 out << " "<<YS.key(sit)->first()<<" "<<YS.inf(sit)<<std::endl; 00176 leda_string res(out.str().c_str()); 00177 return res; 00178 } 00179 00180 00181 Point_2 source(ISegment is) const 00182 { return K.source(is->first()); } 00183 Point_2 target(ISegment is) const 00184 { return K.target(is->first()); } 00185 ITERATOR original(ISegment s) const 00186 { return s->second(); } 00187 00188 int orientation(ST_item sit, const Point_2& p) const 00189 { return K.orientation(YS.key(sit)->first(),p); } 00190 00191 bool collinear(ST_item sit1, 00192 ST_item sit2) const 00193 { Point_2 ps = source(YS.key(sit2)), pt = target(YS.key(sit2)); 00194 return ( orientation(sit1,ps)==0 && 00195 orientation(sit1,pt)==0 ); 00196 } 00197 00198 00199 void compute_intersection(ST_item sit0) 00200 { 00201 ST_item sit1 = YS.succ(sit0); 00202 if ( sit0 == YS.min_item() || sit1 == YS.max_item() ) return; 00203 ISegment s0 = YS.key(sit0); 00204 ISegment s1 = YS.key(sit1); 00205 int or0 = K.orientation(s0->first(),target(s1)); 00206 int or1 = K.orientation(s1->first(),target(s0)); 00207 if ( or0 <= 0 && or1 >= 0 ) { 00208 ST_item it = IEvent(YS.key(sit0),YS.key(sit1)); 00209 if ( it==0 ) { 00210 Point_2 q = K.intersection(s0->first(),s1->first()); 00211 it = XS.insert(q,sit0); 00212 } 00213 YS.change_inf(sit0, it); 00214 } 00215 } 00216 00217 void initialize_structures() 00218 { 00219 CGAL_NEF_TRACEN("initialize_structures"); 00220 ITERATOR it_s; 00221 for ( it_s=its; it_s != ite; ++it_s ) { 00222 Segment_2 s = *it_s; 00223 ST_item it1 = 00224 XS.insert( K.source(s), ST_item(nil)); 00225 ST_item it2 = 00226 XS.insert( K.target(s), ST_item(nil)); 00227 if (it1 == it2) { 00228 if ( Isos_of[it1] == 0 ) Isos_of[it1] = new IsoList; 00229 Isos_of[it1]->push(it_s); 00230 continue; // ignore zero-length segments in SQ/YS 00231 } 00232 00233 Point_2 p = XS.key(it1); 00234 Point_2 q = XS.key(it2); 00235 00236 Segment_2 s1; 00237 if ( K.compare_xy(p,q) < 0 ) 00238 s1 = K.construct_segment(p,q); 00239 else 00240 s1 = K.construct_segment(q,p); 00241 00242 Internal.append(seg_pair(s1,it_s)); 00243 SQ.insert(K.source(s1),&Internal[Internal.last()]); 00244 } 00245 00246 // insert a lower and an upper sentinel segment 00247 YS.insert(&sl,ST_item(nil)); 00248 YS.insert(&sh,ST_item(nil)); 00249 CGAL_NEF_TRACEN("end of initialization\n"<<YS.size()); 00250 } 00251 00252 bool event_exists() 00253 { 00254 if (!XS.empty()) { 00255 // event is set at end of loop and in init 00256 event = (XS.min)(); 00257 p_sweep = XS.key(event); 00258 return true; 00259 } 00260 return false; 00261 } 00262 00263 void procede_to_next_event() 00264 { XS.del_item(event); } 00265 00266 void process_event() 00267 { 00268 CGAL_NEF_TRACEN("\n\n >>> process_event: "<<p_sweep<<" "<<XS[event]<<" "<<event); 00269 00270 Vertex_handle v = GO.new_vertex(p_sweep); 00271 ST_item sit = XS.inf(event); 00272 00273 ST_item sit_succ(0), sit_pred(0), sit_pred_succ(0), sit_first(0); 00274 if (sit == nil) 00275 { 00276 Segment_2 s_sweep = K.construct_segment(p_sweep,p_sweep); 00277 seg_pair sp(s_sweep, ite); 00278 sit_succ = YS.locate( &sp ); 00279 if ( sit_succ != YS.max_item() && 00280 orientation(sit_succ,p_sweep) == 0 ) 00281 sit = sit_succ; 00282 else { 00283 sit_pred = YS.pred(sit_succ); 00284 sit_pred_succ = sit_succ; 00285 } 00286 CGAL_NEF_TRACEN("looked up p_sweep "<<PIS(YS.key(sit_succ))); 00287 } 00288 00289 00290 00291 /* If no segment contains p_sweep then sit_pred and sit_succ are 00292 correctly set after the above locate operation, if a segment 00293 contains p_sweep sit_pred and sit_succ are set below when 00294 determining the bundle.*/ 00295 00296 if (sit != nil) { // key(sit) is an ending or passing segment 00297 CGAL_NEF_TRACEN("ending/passing segs"); 00298 while ( YS.inf(sit) == event || 00299 YS.inf(sit) == YS.succ(sit) ) // overlapping 00300 sit = YS.succ(sit); 00301 sit_succ = YS.succ(sit); 00302 ST_item sit_last = sit; 00303 00304 ST_item xit = YS.inf(sit_last); 00305 if (xit) { 00306 ISegment s1 = YS.key(sit_last); 00307 ISegment s2 = YS.key(sit_succ); 00308 IEvent(s1,s2) = xit; 00309 CGAL_NEF_TRACEN("hashing "<<PIS(s1)<<PIS(s2)<<xit); 00310 } 00311 00312 bool overlapping; 00313 do { 00314 ISegment s = YS.key(sit); 00315 ST_item sit_next = YS.pred(sit); 00316 overlapping = (YS.inf(sit_next) == sit); 00317 Halfedge_handle e = Edge_of[sit]; 00318 if ( !overlapping ) { 00319 CGAL_NEF_TRACEN("connecting edge to node "<<PIS(s)<<" "<<sit); 00320 GO.link_as_target_and_append(v,e); 00321 } 00322 GO.supporting_segment(e,original(s)); 00323 if ( target(s) == p_sweep ) { // ending segment 00324 CGAL_NEF_TRACEN("ending segment "<<PIS(s)); 00325 if ( overlapping ) 00326 YS.change_inf(sit_next,YS.inf(sit)); 00327 YS.del_item(sit); 00328 GO.ending_segment(v,original(s)); 00329 } else { // passing segment 00330 CGAL_NEF_TRACEN("passing segment "<<PIS(s)); 00331 if ( YS.inf(sit) != YS.succ(sit) ) 00332 YS.change_inf(sit, ST_item(0)); 00333 GO.passing_segment(v,original(s)); 00334 } 00335 sit = sit_next; 00336 } 00337 while ( YS.inf(sit) == event || overlapping || 00338 YS.inf(sit) == YS.succ(sit) ); 00339 00340 sit_pred = sit; 00341 sit_first = sit_pred_succ = YS.succ(sit_pred); // first item of bundle 00342 00343 CGAL_NEF_TRACE("event bundles between\n "<<PIS(YS.key(sit_succ))); 00344 CGAL_NEF_TRACEN("\n "<<PIS(YS.key(sit_pred))); 00345 00346 while ( sit != sit_succ ) { 00347 ST_item sub_first = sit; 00348 ST_item sub_last = sub_first; 00349 00350 while (YS.inf(sub_last) == YS.succ(sub_last)) 00351 sub_last = YS.succ(sub_last); 00352 00353 if (sub_last != sub_first) 00354 YS.reverse_items(sub_first, sub_last); 00355 00356 sit = YS.succ(sub_first); 00357 } 00358 00359 // reverse the entire bundle 00360 if (sit_first != sit_succ) 00361 YS.reverse_items(YS.succ(sit_pred),YS.pred(sit_succ)); 00362 00363 00364 } // if (sit != nil) 00365 00366 CGAL_assertion(sit_pred); 00367 GO.halfedge_below(v,Edge_of[sit_pred]); 00368 if ( Isos_of[event] != 0 ) { 00369 const IsoList& IL = *(Isos_of[event]); 00370 slist_item iso_it; 00371 for (iso_it = IL.first(); iso_it; iso_it=IL.succ(iso_it) ) 00372 GO.trivial_segment(v,IL[iso_it] ); 00373 delete (Isos_of[event]); // clean up the list 00374 } 00375 00376 00377 ISegment next_seg; 00378 CGAL_LEDA_SCOPE::pq_item next_it = SQ.find_min(); 00379 while ( next_it && 00380 (next_seg = SQ.inf(next_it), p_sweep == source(next_seg)) ) { 00381 ST_item s_sit = YS.locate_succ(next_seg); 00382 ST_item p_sit = YS.pred(s_sit); 00383 00384 CGAL_NEF_TRACEN("inserting "<<PIS(next_seg)<<" at "<<PIS(YS.key(s_sit))); 00385 if ( YS.max_item() != s_sit && 00386 orientation(s_sit, source(next_seg) ) == 0 && 00387 orientation(s_sit, target(next_seg) ) == 0 ) 00388 sit = YS.insert_at(s_sit, next_seg, s_sit); 00389 else 00390 sit = YS.insert_at(s_sit, next_seg, ST_item(nil)); 00391 CGAL_assertion(YS.succ(sit)==s_sit); 00392 00393 if ( YS.min_item() != p_sit && 00394 orientation(p_sit, source(next_seg) ) == 0 && 00395 orientation(p_sit, target(next_seg) ) == 0 ) 00396 YS.change_inf(p_sit, sit); 00397 CGAL_assertion(YS.succ(p_sit)==sit); 00398 00399 XS.insert(target(next_seg), sit); 00400 GO.starting_segment(v,original(next_seg)); 00401 00402 // delete minimum and assign new minimum to next_seg 00403 SQ.del_min(); 00404 next_it = SQ.find_min(); 00405 } 00406 00407 for( ST_item sitl = YS.pred(sit_succ); sitl != sit_pred; 00408 sitl = YS.pred(sitl) ) { 00409 if ( YS.inf(sitl) != YS.succ(sitl) ) { // non-overlapping 00410 CGAL_NEF_TRACEN("non-overlapping "<<PIS(YS.key(sitl))<<" "<<sitl); 00411 Edge_of[sitl] = GO.new_halfedge_pair_at_source(v); 00412 } else { 00413 CGAL_NEF_TRACEN("overlapping "<<PIS(YS.key(sitl))); 00414 Edge_of[sitl] = Edge_of[ YS.succ(sitl) ]; 00415 } 00416 } 00417 sit_first = YS.succ(sit_pred); 00418 00419 00420 CGAL_assertion(sit_pred); CGAL_assertion(sit_pred_succ); 00421 ST_item xit = YS.inf(sit_pred); 00422 if ( xit ) { 00423 ISegment s1 = YS.key(sit_pred); 00424 ISegment s2 = YS.key(sit_pred_succ); 00425 IEvent(s1,s2) = xit; 00426 CGAL_NEF_TRACEN("hashing "<<PIS(s1)<<PIS(s2)<<xit); 00427 YS.change_inf(sit_pred, ST_item(0)); 00428 } 00429 00430 compute_intersection(sit_pred); 00431 sit = YS.pred(sit_succ); 00432 if (sit != sit_pred) 00433 compute_intersection(sit); 00434 00435 00436 } 00437 00438 void complete_structures() {} 00439 void check_invariants() {CGAL_NEF_TRACEN("check_invariants\n"<<dump_structures());} 00440 void check_final() {} 00441 00442 }; // leda_seg_overlay_traits 00443 00444 } // namespace CGAL 00445 00446 #endif // defined(CGAL_USE_LEDA) 00447 #if !defined(CGAL_USE_LEDA) 00448 #include <list> 00449 #include <string> 00450 #include <sstream> 00451 #include <map> 00452 #include <CGAL/Multiset.h> 00453 #include <CGAL/Unique_hash_map.h> 00454 00455 namespace CGAL { 00456 00457 template <typename IT, typename PMDEC, typename GEOM> 00458 class stl_seg_overlay_traits { 00459 public: 00460 typedef IT ITERATOR; 00461 typedef std::pair<IT,IT> INPUT; 00462 typedef PMDEC OUTPUT; 00463 typedef typename PMDEC::Vertex_handle Vertex_handle; 00464 typedef typename PMDEC::Halfedge_handle Halfedge_handle; 00465 typedef GEOM GEOMETRY; 00466 typedef typename GEOMETRY::Point_2 Point_2; 00467 typedef typename GEOMETRY::Segment_2 Segment_2; 00468 00469 typedef std::pair<Segment_2,ITERATOR> seg_pair; 00470 typedef seg_pair* ISegment; 00471 typedef std::list<seg_pair> IList; 00472 typedef typename IList::const_iterator ilist_iterator; 00473 00474 00475 // types interfacing the generic sweep frame 00476 ITERATOR its, ite; 00477 OUTPUT& GO; 00478 const GEOMETRY& K; 00479 00480 00481 class lt_segs_at_sweepline 00482 { 00483 const Point_2& p; 00484 ISegment s_bottom, s_top; // sentinel segments 00485 const GEOMETRY& K; 00486 00487 public: 00488 lt_segs_at_sweepline(const Point_2& pi, 00489 ISegment s1, ISegment s2, 00490 const GEOMETRY& k) 00491 : p(pi), s_bottom(s1), s_top(s2), K(k) 00492 {} 00493 00494 lt_segs_at_sweepline(const lt_segs_at_sweepline& lt) 00495 : p(lt.p), s_bottom(lt.s_bottom), s_top(lt.s_top), K(lt.K) 00496 {} 00497 00498 template <typename ss_pair> 00499 bool 00500 operator()(const ISegment& is1, const ss_pair& ss2) const 00501 { 00502 return operator()(is1, ss2.first); 00503 } 00504 00505 bool 00506 operator()(const ISegment& is1, const ISegment& is2) const 00507 { 00508 if ( is2 == s_top || is1 == s_bottom ) return true; 00509 if ( is1 == s_top || is2 == s_bottom ) return false; 00510 if ( is1 == is2 ) return false; 00511 // Precondition: p is contained in s1 or s2. 00512 const Segment_2& s1 = is1->first; 00513 const Segment_2& s2 = is2->first; 00514 00515 CGAL_assertion_msg(( K.orientation(s1,p) == 0 ) || ( K.orientation(s2,p) == 0 ) ,"compare error in sweep."); 00516 00517 int s = 0; 00518 if( p == K.source(s1) ) 00519 s = K.orientation(s2,p); 00520 else 00521 s = - K.orientation(s1,p); 00522 if ( s || K.is_degenerate(s1) || K.is_degenerate(s2) ) 00523 return ( s < 0 ); 00524 00525 s = K.orientation(s2,K.target(s1)); 00526 if (s==0) return ( is1 - is2 ) < 0; 00527 // overlapping segments are not equal 00528 return ( s < 0 ); 00529 } 00530 }; 00531 00532 00533 class compare_segs_at_sweepline 00534 { 00535 const Point_2& p; 00536 ISegment s_bottom, s_top; // sentinel segments 00537 const GEOMETRY& K; 00538 00539 CGAL::Comparison_result o2c(int o) const { 00540 if(o > 0) return CGAL::LARGER; 00541 if(o < 0) return CGAL::SMALLER; 00542 return CGAL::EQUAL; 00543 } 00544 00545 public: 00546 compare_segs_at_sweepline(const Point_2& pi, 00547 ISegment s1, ISegment s2, 00548 const GEOMETRY& k) 00549 : p(pi), s_bottom(s1), s_top(s2), K(k) 00550 {} 00551 00552 compare_segs_at_sweepline(const compare_segs_at_sweepline& lt) 00553 : p(lt.p), s_bottom(lt.s_bottom), s_top(lt.s_top), K(lt.K) 00554 {} 00555 00556 template <typename ss_pair> 00557 bool 00558 operator()(const ISegment& is1, const ss_pair& ss2) const 00559 { 00560 return operator()(is1, ss2.first); 00561 } 00562 00563 CGAL::Comparison_result 00564 operator()(const ISegment& is1, const ISegment& is2) const 00565 { 00566 if ( is2 == s_top || is1 == s_bottom ) return CGAL::SMALLER; 00567 if ( is1 == s_top || is2 == s_bottom ) return CGAL::LARGER; 00568 if ( is1 == is2 ) return CGAL::EQUAL; 00569 // Precondition: p is contained in s1 or s2. 00570 const Segment_2& s1 = is1->first; 00571 const Segment_2& s2 = is2->first; 00572 00573 CGAL_assertion_msg(( K.orientation(s1,p) == 0 ) || ( K.orientation(s2,p) == 0 ) ,"compare error in sweep."); 00574 00575 int s = 0; 00576 if(K.is_degenerate(s1)) 00577 return o2c(K.orientation(s2,p)); 00578 if(K.is_degenerate(s2)) 00579 return o2c(-K.orientation(s1,p)); 00580 00581 s = - K.orientation(s1,p); 00582 if(s!=0) 00583 return o2c(s); 00584 s = K.orientation(s2,p); 00585 if(s!=0) 00586 return o2c(s); 00587 return o2c(K.orientation(s2,K.target(s1))); 00588 /* 00589 if( p == K.source(s1) ) 00590 s = K.orientation(s2,p); 00591 else 00592 s = - K.orientation(s1,p); 00593 if ( s || K.is_degenerate(s1) || K.is_degenerate(s2) ) 00594 if(s < 0) return CGAL::SMALLER; 00595 else if(s > 0) return CGAL::LARGER; 00596 else return CGAL::EQUAL; 00597 00598 s = K.orientation(s2,K.target(s1)); 00599 // if (s==0) { 00600 // if(is1 < is2) return CGAL::SMALLER; 00601 // if (is1 > is2) return CGAL::LARGER; 00602 // return CGAL::EQUAL; 00603 // } 00604 00605 // overlapping segments are not equal 00606 if(s < 0) return CGAL::SMALLER; 00607 if(s > 0) return CGAL::LARGER; 00608 return CGAL::EQUAL; 00609 */ 00610 } 00611 }; 00612 00613 class compare_pnts_xy { 00614 const GEOMETRY& K; 00615 00616 public: 00617 compare_pnts_xy(const GEOMETRY& k) 00618 : K(k) 00619 {} 00620 00621 compare_pnts_xy(const compare_pnts_xy& lt) 00622 : K(lt.K) 00623 {} 00624 00625 CGAL::Comparison_result 00626 operator()(const Point_2& p1, const Point_2& p2) const 00627 { 00628 int c = K.compare_xy(p1,p2); 00629 if(c < 0) return CGAL::SMALLER; 00630 if(c > 0) return CGAL::LARGER; 00631 return CGAL::EQUAL; 00632 } 00633 }; 00634 00635 struct lt_pnts_xy { 00636 const GEOMETRY& K; 00637 00638 public: 00639 lt_pnts_xy(const GEOMETRY& k) 00640 : K(k) 00641 {} 00642 00643 lt_pnts_xy(const lt_pnts_xy& lt) 00644 : K(lt.K) 00645 {} 00646 00647 int 00648 operator()(const Point_2& p1, const Point_2& p2) const 00649 { 00650 return K.compare_xy(p1,p2) < 0; 00651 } 00652 }; 00653 00654 typedef std::list<ITERATOR> IsoList; 00655 typedef CGAL::Multiset<Point_2, compare_pnts_xy> EventQueue; 00656 typedef typename EventQueue::iterator event_iterator; 00657 typedef Unique_hash_map<Point_2*, IsoList*> X2iso; 00658 00659 typedef CGAL::Multiset<ISegment, compare_segs_at_sweepline> SweepStatus; 00660 typedef typename SweepStatus::iterator ss_iterator; 00661 typedef typename SweepStatus::const_iterator ss_const_iterator; 00662 typedef CGAL::Unique_hash_map<ISegment, event_iterator> Y2X; 00663 typedef CGAL::Unique_hash_map<ISegment, ISegment> Y2Y; 00664 typedef CGAL::Unique_hash_map<Point_2*, ss_iterator> X2Y; 00665 typedef CGAL::Unique_hash_map<ISegment, Halfedge_handle> AssocEdgeMap; 00666 00667 typedef std::pair<ISegment,ISegment> is_pair; 00668 00669 struct lt_ssi_pair { 00670 00671 public: 00672 lt_ssi_pair() {} 00673 bool operator()(const is_pair& s0, const is_pair& s1) const { 00674 if(s0.second == s1.second) 00675 return s0.first < s1.first; 00676 return s0.second < s1.second; 00677 } 00678 }; 00679 00680 typedef std::map<is_pair, event_iterator, lt_ssi_pair> EventHash; 00681 00682 typedef std::multimap<Point_2, ISegment, lt_pnts_xy> SegQueue; 00683 typedef typename SegQueue::iterator seg_iterator; 00684 typedef typename SegQueue::value_type ps_pair; 00685 00686 event_iterator event; 00687 Point_2 p_sweep; 00688 EventQueue XS; 00689 seg_pair sl,sh; 00690 compare_segs_at_sweepline SLcmp; 00691 SweepStatus YS; 00692 Y2X y2x; 00693 X2Y x2y; 00694 X2iso x2iso; 00695 Y2Y y2y; 00696 SegQueue SQ; 00697 IList Internal; 00698 AssocEdgeMap Edge_of; 00699 EventHash IEvent; 00700 00701 stl_seg_overlay_traits(const INPUT& in, OUTPUT& G, const GEOMETRY& k) 00702 : its(in.first), ite(in.second), GO(G), K(k), 00703 XS(compare_pnts_xy(K)), SLcmp(p_sweep,&sl,&sh,K), YS(SLcmp), 00704 y2x(XS.end()), x2y(YS.end()), x2iso(0), y2y(&sl), 00705 SQ(lt_pnts_xy(K)), Edge_of(0) 00706 {} 00707 00708 std::string dump_structures() 00709 { 00710 std::ostringstream out; 00711 out << "EventQueue:\n"; 00712 typename EventQueue::const_iterator sit1; 00713 for(sit1 = XS.begin(); sit1 != XS.end(); ++sit1) 00714 out << " " << *sit1 << std::endl; 00715 00716 out << "SegQueue:\n"; 00717 typename SegQueue::const_iterator sit2; 00718 for(sit2 = SQ.begin(); sit2 != SQ.end(); ++sit2) 00719 out << " " << sit2->first << " " << sit2->second 00720 << " " << sit2->first << std::endl; 00721 00722 out << "SweepStatus:\n"; 00723 typename SweepStatus::iterator sit3; 00724 for( sit3 = YS.begin(); *sit3 != &sh; ++sit3 ) { 00725 int b = orientation(sit3, p_sweep); 00726 if(*sit3 == &sl) out << " 1"; 00727 else if(*sit3 == &sh) out <<"-1"; 00728 else if(b >= 0) out << " " << b; 00729 else out << b; 00730 out << " " << *sit3 << ": "; 00731 // if(y2x[*sit3] != XS.end()) 00732 // out << *y2x[*sit3]; 00733 // out << " | "; 00734 out << (*sit3)->first; 00735 if(y2y[*sit3] != &sl) 00736 out << " y2y: " << y2y[*sit3]; 00737 out << std::endl; 00738 } 00739 return out.str(); 00740 } 00741 00742 bool check_bundle(ss_iterator pred, 00743 ss_iterator succ) { 00744 CGAL_NEF_TRACEN("check bundle"); 00745 00746 check_invariants(); 00747 00748 CGAL_assertion(*pred == &sl || 00749 orientation(pred, p_sweep) > 0); 00750 ++pred; 00751 while(*pred != *succ) { 00752 CGAL_assertion(orientation(pred, p_sweep) == 0); 00753 ss_iterator next(pred); 00754 ++next; 00755 if(*pred != &sl && 00756 *next != &sh) { 00757 bool b1 = orientation(pred, K.source((*next)->first)) == 0; 00758 b1 &= orientation(pred, K.target((*next)->first)) == 0; 00759 b1 &= orientation(next, K.source((*pred)->first)) == 0; 00760 b1 &= orientation(next, K.target((*pred)->first)) == 0; 00761 CGAL_warning(b1 == (y2y[*pred] == *next)); 00762 } 00763 ++pred; 00764 } 00765 CGAL_assertion(*succ == &sh || 00766 orientation(succ, p_sweep) < 0); 00767 00768 return true; 00769 } 00770 00771 Point_2 source(ISegment is) const 00772 { return K.source(is->first); } 00773 Point_2 target(ISegment is) const 00774 { return K.target(is->first); } 00775 00776 ITERATOR original(ISegment s) const 00777 { return s->second; } 00778 00779 int orientation(ss_iterator sit, const Point_2& p) const 00780 { return K.orientation((*sit)->first,p); } 00781 00782 bool collinear(ss_iterator sit1, ss_iterator sit2) const 00783 { if( *sit1 == &sl || 00784 *sit1 == &sh || 00785 *sit2 == &sl || 00786 *sit2 == &sh) return false; 00787 Point_2 ps = source(*sit2), pt = target(*sit2); 00788 return ( orientation(sit1,ps)==0 && 00789 orientation(sit1,pt)==0 ); 00790 } 00791 00792 event_iterator insertXS(const Point_2& p) { 00793 event_iterator upper = XS.upper_bound(p); 00794 if(upper == XS.begin()) 00795 return XS.insert_before(upper, p); 00796 event_iterator pred = upper; --pred; 00797 if(K.compare_xy(*pred, p) == CGAL::SMALLER) 00798 return XS.insert_before(upper, p); 00799 return pred; 00800 } 00801 00802 void compute_intersection(ss_iterator sit0) 00803 { 00804 // Given an item |sit0| in the Y-structure compute the point of 00805 // intersection with its successor and (if existing) insert it into 00806 // the event queue and do all necessary updates. 00807 ss_iterator sit1 = sit0; ++sit1; 00808 CGAL_NEF_TRACEN("compute_intersection "<< *sit0 <<" "<< *sit1); 00809 if ( *sit0 == &sl || *sit1 == &sh ) return; 00810 const Segment_2& s0 = (*sit0)->first; 00811 const Segment_2& s1 = (*sit1)->first; 00812 int or0 = K.orientation(s0,K.target(s1)); 00813 int or1 = K.orientation(s1,K.target(s0)); 00814 if ( or0 <= 0 && or1 >= 0 ) { 00815 event_iterator it = 00816 IEvent[std::make_pair(*sit0, *sit1)]; 00817 if(it == event_iterator()) { 00818 Point_2 q = K.intersection(s0,s1); 00819 event_iterator er = insertXS(q); // only done if none existed!!! 00820 x2y[&*er] = sit0; 00821 y2x[*sit0] = er; 00822 CGAL_assertion(sit0 != YS.end()); 00823 } else { 00824 CGAL_NEF_TRACEN(" intersection has been found previously"); 00825 y2x[*sit0] = it; 00826 } 00827 } 00828 } 00829 00830 void initialize_structures() 00831 { 00832 /* INITIALIZATION 00833 - insert all vertices into the x-structure 00834 - insert sentinels into y-structure 00835 - exploit the fact that insert operations into the x-structure 00836 leave previously inserted points unchanged to achieve that 00837 any pair of endpoints $p$ and $q$ with |p == q| are identical 00838 */ 00839 CGAL_NEF_TRACEN("initialize_structures"); 00840 00841 ITERATOR it_s; 00842 for ( it_s=its; it_s != ite; ++it_s ) { 00843 const Segment_2& s = *it_s; 00844 event_iterator it1, it2, upper; 00845 00846 if(XS.empty()) 00847 it1 = XS.insert(K.source(s)); 00848 else 00849 it1 = insertXS(K.source(s)); 00850 it2 = insertXS(K.target(s)); 00851 00852 if (it1 == it2) { 00853 if ( x2iso[&*it1] == 0 ) x2iso[&*it1] = new IsoList; 00854 x2iso[&*it1]->push_front(it_s); 00855 continue; // ignore zero-length segments regarding YS 00856 } 00857 00858 Point_2 p = *it1; 00859 Point_2 q = *it2; 00860 00861 Segment_2 s1; 00862 if ( K.compare_xy(p,q) < 0 ) 00863 s1 = K.construct_segment(p,q); 00864 else 00865 s1 = K.construct_segment(q,p); 00866 00867 Internal.push_back(seg_pair(s1,it_s)); 00868 SQ.insert(ps_pair(K.source(s1),&Internal.back())); 00869 } 00870 00871 // insert a lower and an upper sentinel segment to avoid special 00872 // cases when traversing the Y-structure 00873 YS.insert(&sl); 00874 YS.insert(&sh); 00875 CGAL_NEF_TRACEN("end of initialization\n"); 00876 } 00877 00878 00879 bool event_exists() 00880 { 00881 if (!XS.empty()) { 00882 // event is set at end of loop and in init 00883 event = XS.begin(); 00884 p_sweep = *event; 00885 return true; 00886 } 00887 return false; 00888 } 00889 00890 void procede_to_next_event() 00891 { XS.erase(event); } 00892 00893 void process_event() 00894 { 00895 CGAL_NEF_TRACEN("\n\n >>> process_event: "<<p_sweep); 00896 00897 Vertex_handle v = GO.new_vertex(p_sweep); 00898 ss_iterator sit = x2y[&*event]; 00899 ss_iterator sit_succ, sit_pred, sit_first, sit_pred_succ; 00900 00901 if(sit == YS.end()) { 00902 CGAL_NEF_TRACEN("search for upper bound in YS"); 00903 Segment_2 s_sweep = K.construct_segment(p_sweep,p_sweep); 00904 seg_pair sp(s_sweep, ite); 00905 sit_succ = YS.upper_bound(&sp); 00906 sit = sit_succ; 00907 --sit; 00908 CGAL_NEF_TRACEN("upper bound: " << *sit_succ); 00909 if(*sit == &sl || 00910 orientation(sit, p_sweep) != 0) { 00911 sit_pred_succ = sit_succ; 00912 sit_pred = sit; 00913 sit = YS.end(); 00914 } 00915 } 00916 00917 /* |sit| is determined by upper bounding the search for the 00918 segment (p_sweep,p_sweep) and taking its predecessor. 00919 if the segment associated to |sit| contains |p_sweep| then 00920 there's a bundle of segments containing |p_sweep|. 00921 We compute the successor (|sit_succ)|) and 00922 predecessor (|sit_pred|) items. */ 00923 00924 00925 /* If no segments contain p_sweep then sit_pred and sit_succ are 00926 correctly set after the above locate operation, if a segment 00927 contains p_sweep sit_pred and sit_succ are set below when 00928 determining the bundle.*/ 00929 00930 if (sit != YS.end() ) { // sit->first is ending or passing segment 00931 CGAL_NEF_TRACEN("ending/passing segs " << *sit); 00932 sit_succ = sit; ++sit_succ; 00933 00934 while ( y2x[*sit] == event || 00935 y2y[*sit] == *sit_succ ) { // overlapping 00936 sit = sit_succ; 00937 ++sit_succ; 00938 } 00939 CGAL_NEF_TRACEN("ending/passing segs " << *sit); 00940 00941 ss_iterator sit_last = sit; 00942 00943 event_iterator xit = y2x[*sit_last]; 00944 if (xit != XS.end() && 00945 *sit_last != &sl && 00946 *sit_succ != &sh) { 00947 IEvent[std::make_pair(*sit_last, *sit_succ)] = xit; 00948 } 00949 00950 bool overlapping; 00951 do { 00952 ISegment s = *sit; 00953 ss_iterator sit_next(sit); --sit_next; 00954 00955 if(*sit_next == &sl) 00956 overlapping = false; 00957 else 00958 overlapping = y2y[*sit_next] == *sit; 00959 Halfedge_handle e = Edge_of[*sit]; 00960 if ( overlapping ) { 00961 CGAL_NEF_TRACEN("overlapping segment "<<s); 00962 } else { 00963 CGAL_NEF_TRACEN("connecting edge to node "<<s); 00964 GO.link_as_target_and_append(v,e); 00965 /* in this case we close the output edge |e| associated to 00966 |sit| by linking |v| as its target and by appending the 00967 twin edge to |v|'s adjacency list. */ 00968 } 00969 GO.supporting_segment(e,original(s)); 00970 if ( target(s) == p_sweep ) { 00971 CGAL_NEF_TRACEN("ending segment "<<s); 00972 if(overlapping) 00973 y2y[*sit_next] = y2y[*sit]; 00974 YS.erase(sit); 00975 GO.ending_segment(v,original(s)); 00976 } else { // passing segment, take care of the node here! 00977 CGAL_NEF_TRACEN("passing segment "<<s); 00978 ss_iterator sst(sit); ++sst; 00979 if(y2y[*sit] != *sst) 00980 y2y[*sit] = &sl; 00981 y2x[*sit] = XS.end(); 00982 GO.passing_segment(v,original(s)); 00983 } 00984 00985 ss_iterator sss(sit_next); ++sss; 00986 if(*sit_next != &sl) 00987 overlapping |= (y2y[*sit_next] == *sss); 00988 00989 sit = sit_next; 00990 } 00991 while (*sit != &sl && 00992 (y2x[*sit] == event || overlapping)); 00993 00994 00995 sit_pred = sit; 00996 sit_first = sit_pred; 00997 ++sit_first; // first item of the bundle 00998 sit_pred_succ = sit_first; 00999 01000 CGAL_NEF_TRACE("event bundles between\n "<< *sit_succ); 01001 CGAL_NEF_TRACEN("\n "<< *sit_pred); 01002 01003 CGAL_assertion(check_bundle(sit_pred, sit_succ)); 01004 01005 while( *sit != *sit_succ) { 01006 ss_iterator sub_first(sit), 01007 sub_last(sub_first), 01008 succ_sub_last(sub_last); 01009 ++succ_sub_last; 01010 01011 while(y2y[*sub_last] == *succ_sub_last) { 01012 ++sub_last; ++succ_sub_last; 01013 } 01014 01015 sit = sub_first; 01016 while(*sub_first != *sub_last) { 01017 YS.swap(sub_first, sub_last); 01018 std::swap(sub_first, sub_last); 01019 ++sub_first; 01020 if(*sub_first == *sub_last) break; 01021 --sub_last; 01022 } 01023 ++sit; 01024 } 01025 01026 if(*sit_first != *sit_succ) { 01027 ss_iterator sfirst(sit_pred); ++sfirst; 01028 ss_iterator slast(sit_succ); --slast; 01029 while(*sfirst != *slast) { 01030 YS.swap(sfirst, slast); 01031 std::swap(sfirst, slast); 01032 ++sfirst; 01033 if(*sfirst == *slast) break; 01034 --slast; 01035 } 01036 } 01037 } // if (sit != ss_iterator() ) 01038 01039 // CGAL_assertion( sit_pred != YS.end() ); 01040 GO.halfedge_below(v,Edge_of[*sit_pred]); 01041 if ( x2iso[&*event] != 0 ) { 01042 IsoList* IL = x2iso[&*event]; 01043 typename IsoList::const_iterator iso_it; 01044 for (iso_it = IL->begin(); iso_it != IL->end(); ++iso_it) 01045 GO.trivial_segment(v,*iso_it); 01046 delete IL; 01047 x2iso[&*event] = 0; 01048 } 01049 01050 ISegment next_seg; 01051 seg_iterator next_it = SQ.begin(); 01052 while ( next_it != SQ.end() && 01053 ( next_seg = next_it->second, p_sweep == source(next_seg)) ) { 01054 CGAL_NEF_TRACEN("inserting "<<next_seg); 01055 01056 ss_iterator s_sit = YS.upper_bound(next_seg); 01057 ss_iterator p_sit(s_sit); --p_sit; 01058 01059 sit = YS.insert_before(s_sit, next_seg); 01060 01061 ss_iterator ys2_tmp = sit; 01062 ++ys2_tmp; 01063 CGAL_assertion(*s_sit == *ys2_tmp); 01064 01065 if(*s_sit != &sh && 01066 orientation(s_sit, source(next_seg)) == 0 && 01067 orientation(s_sit, target(next_seg)) == 0) { 01068 y2y[*sit] = *s_sit; 01069 } 01070 01071 if ( &sl != *p_sit && 01072 orientation(p_sit, source(next_seg) ) == 0 && 01073 orientation(p_sit, target(next_seg) ) == 0 ) { 01074 y2y[*p_sit] = *sit; 01075 } 01076 01077 x2y[&*XS.find(target(next_seg))] = sit; 01078 GO.starting_segment(v,original(next_seg)); 01079 01080 // delete minimum and assign new minimum to next_seg 01081 SQ.erase(SQ.begin()); 01082 next_it = SQ.begin(); 01083 } 01084 01085 // we insert new edge stubs, non-linked at target 01086 ss_iterator sit_curr = sit_succ, sit_prev = sit_succ; 01087 for( --sit_curr; *sit_curr != *sit_pred; 01088 sit_prev = sit_curr, --sit_curr ) { 01089 CGAL_NEF_TRACEN("checking outedge "<< *sit_curr <<"\n "<< *sit_prev); 01090 if (y2y[*sit_curr] == *sit_prev) { // overlapping 01091 CGAL_assertion(collinear(sit_curr, sit_prev)); 01092 Edge_of[*sit_curr] = Edge_of[*sit_prev]; 01093 } else { 01094 CGAL_NEF_TRACEN("creating new edge "); 01095 Edge_of[*sit_curr] = GO.new_halfedge_pair_at_source(v); 01096 } 01097 } 01098 sit_first = sit_prev; 01099 01100 event_iterator xxit = y2x[*sit_pred]; 01101 if(xxit != XS.end() && 01102 *sit_pred != &sl && 01103 *sit_pred_succ != &sh) { 01104 IEvent[std::make_pair(*sit_pred, *sit_pred_succ)] = xxit; 01105 y2y[*sit_pred] = &sl; 01106 y2x[*sit_pred] = XS.end(); 01107 } 01108 01109 CGAL_NEF_TRACEN("pred,succ = "<< *sit_pred <<" "<< *sit_succ); 01110 compute_intersection(sit_pred); 01111 sit = sit_succ; --sit; 01112 if (*sit != *sit_pred) 01113 compute_intersection(sit); 01114 } 01115 01116 void complete_structures() {} 01117 void check_invariants() {CGAL_NEF_TRACEN("check_invariants\n"<<dump_structures());} 01118 void check_final() {} 01119 01120 01121 }; // stl_seg_overlay_traits 01122 01123 } // namespace CGAL 01124 01125 #endif // !defined(CGAL_USE_LEDA) 01126 01127 namespace CGAL { 01128 #if defined(CGAL_USE_LEDA) 01129 #define Segment_overlay_traits leda_seg_overlay_traits 01130 static const char* const sweepversion = "LEDA segment overlay sweep"; 01131 #else 01132 #define Segment_overlay_traits stl_seg_overlay_traits 01133 static const char* const sweepversion = "STL segment overlay sweep"; 01134 #endif 01135 } // namespace CGAL 01136 01137 #include <CGAL/generic_sweep.h> 01138 #endif // CGAL_SEGMENT_OVERLAY_TRAITS_H 01139
1.7.6.1