BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Nef_2/Segment_overlay_traits.h
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines