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_S2/include/CGAL/Nef_S2/SM_constrained_triang_traits.h $ 00015 // $Id: SM_constrained_triang_traits.h 40851 2007-11-09 15:27:44Z ameyer $ 00016 // 00017 // 00018 // Author(s) : Michael Seel <seel@mpi-sb.mpg.de> 00019 #ifndef CGAL_SM_CONSTRAINED_TRIANG_TRAITS_H 00020 #define CGAL_SM_CONSTRAINED_TRIANG_TRAITS_H 00021 00022 #include <CGAL/basic.h> 00023 #include <CGAL/Unique_hash_map.h> 00024 #include <CGAL/generic_sweep.h> 00025 //#include <CGAL/Nef_S2/SM_checker.h> 00026 #include <string> 00027 #include <map> 00028 #include <set> 00029 #undef CGAL_NEF_DEBUG 00030 #define CGAL_NEF_DEBUG 139 00031 #include <CGAL/Nef_2/debug.h> 00032 00033 CGAL_BEGIN_NAMESPACE 00034 00035 /* For a detailed documentation see the MPI research report 2001-1-003 00036 which documents the planar flavor of this baby; only minor deviations 00037 are included in this code */ 00038 00039 template <typename Decorator_, typename Kernel_> 00040 class SM_constrained_triang_traits : public Decorator_ { 00041 public: 00042 typedef SM_constrained_triang_traits<Decorator_,Kernel_> Self; 00043 typedef Decorator_ Base; 00044 00045 00046 typedef typename Kernel_::Point_2 Point; 00047 typedef typename Kernel_::Segment_2 Segment; 00048 00049 typedef typename Base::SHalfedge_handle SHalfedge_handle; 00050 typedef typename Base::SVertex_handle SVertex_handle; 00051 typedef typename Base::SFace_handle SFace_handle; 00052 typedef typename Base::SHalfedge_iterator SHalfedge_iterator; 00053 typedef typename Base::SVertex_iterator SVertex_iterator; 00054 typedef typename Base::SFace_iterator SFace_iterator; 00055 typedef typename Base::SHalfedge_around_svertex_circulator 00056 SHalfedge_around_svertex_circulator; 00057 00058 // the types interfacing the sweep: 00059 typedef std::pair<SVertex_iterator,SVertex_iterator> INPUT; 00060 typedef Decorator_ OUTPUT; 00061 typedef Kernel_ GEOMETRY; 00062 00063 00064 class lt_edges_in_sweepline : public Decorator_ 00065 { const Point& p; 00066 const SHalfedge_handle& e_bottom; 00067 const SHalfedge_handle& e_top; 00068 const Kernel_& K; 00069 public: 00070 lt_edges_in_sweepline(const Point& pi, 00071 const SHalfedge_handle& e1, const SHalfedge_handle& e2, 00072 const Decorator_& D, const Kernel_& k) : 00073 Decorator_(D), p(pi), e_bottom(e1), e_top(e2), K(k) {} 00074 00075 lt_edges_in_sweepline(const lt_edges_in_sweepline& lt) : 00076 Decorator_(lt), p(lt.p), 00077 e_bottom(lt.e_bottom), e_top(lt.e_top), K(lt.K) {} 00078 00079 Segment seg(const SHalfedge_handle& e) const 00080 { return K.construct_segment(point(source(e)),point(target(e))); } 00081 00082 int orientation(SHalfedge_handle e, const Point& p) const 00083 { return K.orientation(e->source()->point(),e->twin()->source()->point(),p); } 00084 00085 bool operator()(const SHalfedge_handle& e1, const SHalfedge_handle& e2) const 00086 { // Precondition: 00087 // [[p]] is identical to the source of either [[e1]] or [[e2]]. 00088 if (e1 == e_bottom || e2 == e_top) return true; 00089 if (e2 == e_bottom || e1 == e_top) return false; 00090 if ( e1 == e2 ) return 0; 00091 int s = 0; 00092 if ( p == e1->source()->point() ) 00093 s = orientation(e2,p); 00094 else if ( p == e2->source()->point() ) 00095 s = - orientation(e1,p); 00096 else CGAL_error_msg("compare error in sweep."); 00097 if ( s || e1->source() == e1->twin()->source() || 00098 e2->source() == e2->twin()->source()) 00099 return ( s < 0 ); 00100 s = orientation(e2,e1->twin()->source()->point()); 00101 if (s==0) CGAL_error_msg("parallel edges not allowed."); 00102 return ( s < 0 ); 00103 } 00104 00105 00106 }; // lt_edges_in_sweepline 00107 00108 class lt_pnts_xy : public Decorator_ 00109 { const Kernel_& K; 00110 public: 00111 lt_pnts_xy(const Decorator_& D, const Kernel_& k) : Decorator_(D), K(k) {} 00112 lt_pnts_xy(const lt_pnts_xy& lt) : Decorator_(lt), K(lt.K) {} 00113 int operator()(const SVertex_handle& v1, const SVertex_handle& v2) const 00114 { return K.compare_xy(v1->point(),v2->point()) < 0; } 00115 }; // lt_pnts_xy 00116 00117 00118 typedef std::map<SHalfedge_handle, SHalfedge_handle, lt_edges_in_sweepline> 00119 Sweep_status_structure; 00120 typedef typename Sweep_status_structure::iterator ss_iterator; 00121 typedef typename Sweep_status_structure::value_type ss_pair; 00122 typedef std::set<SVertex_iterator,lt_pnts_xy> Event_Q; 00123 typedef typename Event_Q::const_iterator event_iterator; 00124 00125 const GEOMETRY& K; 00126 Event_Q event_Q; 00127 event_iterator event_it; 00128 SVertex_handle event; 00129 Point p_sweep; 00130 Sweep_status_structure SL; 00131 CGAL::Unique_hash_map<SHalfedge_handle,ss_iterator> SLItem; 00132 SHalfedge_handle e_low,e_high; // framing edges ! 00133 SHalfedge_handle e_search; 00134 SVertex_iterator v_first, v_beyond; 00135 00136 SM_constrained_triang_traits(const INPUT& in, OUTPUT& out, 00137 const GEOMETRY& k) 00138 : Base(out), K(k), event_Q(lt_pnts_xy(*this,K)), 00139 SL(lt_edges_in_sweepline(p_sweep,e_low,e_high,*this,K)), 00140 SLItem(SL.end()), v_first(in.first), v_beyond(in.second) 00141 { CGAL_NEF_TRACEN("Constrained Triangulation Sweep"); } 00142 00143 /* |treat_new_sedge| is used to forward information that exists 00144 at input edges of the triangulation as such it spreads input 00145 information to the newly created edges of the triangulation; 00146 the used operation incident_mark refers to the base class of 00147 |*this| */ 00148 void treat_new_edge(SHalfedge_handle e) 00149 { assoc_info(e); 00150 e->mark() = incident_mark(e) = incident_mark(e->twin()) = 00151 incident_mark(e->snext()); 00152 CGAL_NEF_TRACEN(" treat_new_edge "<<PH(e)); 00153 } 00154 00155 SHalfedge_handle new_bi_edge(SVertex_handle v1, SVertex_handle v2) 00156 { // appended at v1 and v2 adj list 00157 SHalfedge_handle e = Base::new_shalfedge_pair(v1,v2); 00158 treat_new_edge(e); 00159 return e; 00160 } 00161 00162 SHalfedge_handle new_bi_edge(SHalfedge_handle e_bf, SHalfedge_handle e_af) 00163 { // ccw before e_bf and after e_af 00164 SHalfedge_handle e = 00165 Base::new_shalfedge_pair(e_bf,e_af,Base::BEFORE, Base::AFTER); 00166 treat_new_edge(e); 00167 return e; 00168 } 00169 00170 SHalfedge_handle new_bi_edge(SVertex_handle v, SHalfedge_handle e_bf) 00171 { // appended at v's adj list and before e_bf 00172 SHalfedge_handle e = Base::new_shalfedge_pair(v,e_bf,Base::BEFORE); 00173 treat_new_edge(e); 00174 return e; 00175 } 00176 00177 Segment segment(SHalfedge_handle e) const 00178 { return K.construct_segment(e->source()->point(),e->twin()->source()->point()); } 00179 00180 bool is_forward(SHalfedge_handle e) const 00181 { return K.compare_xy(point(source(e)),point(target(e))) < 0; } 00182 00183 bool edge_is_visible_from(SVertex_handle v, SHalfedge_handle e) 00184 { 00185 Point p = v->point(); 00186 Point p1 = e->source()->point(); 00187 Point p2 = e->twin()->source()->point(); 00188 return ( K.orientation(p1,p2,p) > 0 ); // left_turn 00189 } 00190 00191 void triangulate_up(SHalfedge_handle& e_apex) 00192 { 00193 CGAL_NEF_TRACEN("triangulate_up "<<segment(e_apex)); 00194 SVertex_handle v_apex = e_apex->source(); 00195 while (true) { 00196 SHalfedge_handle e_vis = e_apex->twin()->sprev(); 00197 bool in_sweep_line = (SLItem[e_vis] != SL.end()); 00198 bool not_visible = !edge_is_visible_from(v_apex,e_vis); 00199 CGAL_NEF_TRACEN(" checking "<<in_sweep_line<<not_visible<<" "<<segment(e_vis)); 00200 if ( in_sweep_line || not_visible) { 00201 CGAL_NEF_TRACEN(" STOP"); return; 00202 } 00203 SHalfedge_handle e_back = new_bi_edge(e_apex,e_vis); 00204 e_apex = e_back; 00205 CGAL_NEF_TRACEN(" produced " << segment(e_apex)); 00206 } 00207 } 00208 00209 void triangulate_down(SHalfedge_handle& e_apex) 00210 { 00211 CGAL_NEF_TRACEN("triangulate_down "<<segment(e_apex)); 00212 SVertex_handle v_apex = e_apex->source(); 00213 while (true) { 00214 SHalfedge_handle e_vis = e_apex->snext(); 00215 bool in_sweep_line = (SLItem[e_vis] != SL.end()); 00216 bool not_visible = !edge_is_visible_from(v_apex,e_vis); 00217 CGAL_NEF_TRACEN(" checking "<<in_sweep_line<<not_visible<<" "<<segment(e_vis)); 00218 if ( in_sweep_line || not_visible) { 00219 CGAL_NEF_TRACEN(" STOP"); return; 00220 } 00221 SHalfedge_handle e_vis_rev = e_vis->twin(); 00222 SHalfedge_handle e_forw = new_bi_edge(e_vis_rev,e_apex); 00223 e_apex = e_forw->twin(); 00224 CGAL_NEF_TRACEN(" produced " << segment(e_apex)); 00225 } 00226 } 00227 00228 void triangulate_between(SHalfedge_handle e_upper, SHalfedge_handle e_lower) 00229 { 00230 // we triangulate the interior of the whole chain between 00231 // target(e_upper) and target(e_lower) 00232 CGAL_assertion(e_upper->source()==e_lower->source()); 00233 CGAL_NEF_TRACE("triangulate_between\n "<<segment(e_upper)); 00234 CGAL_NEF_TRACEN("\n "<<segment(e_lower)); 00235 SHalfedge_handle e_end = e_lower->twin(); 00236 while (true) { 00237 SHalfedge_handle e_vis = e_upper->snext(); 00238 SHalfedge_handle en_vis = e_vis->snext(); 00239 CGAL_NEF_TRACEN(" working on base e_vis " << segment(e_vis)); 00240 CGAL_NEF_TRACEN(" next is " << segment(en_vis)); 00241 if (en_vis == e_end) return; 00242 e_upper = new_bi_edge(e_vis->twin(),e_upper)->twin(); 00243 CGAL_NEF_TRACEN(" produced " << segment(e_upper)); 00244 } 00245 } 00246 00247 void process_event() 00248 { 00249 CGAL_NEF_TRACEN("\nPROCESS_EVENT " << p_sweep); 00250 SHalfedge_handle e, ep, eb_low, eb_high, e_end; 00251 if ( !is_isolated(event) ) { 00252 e = last_out_edge(event); 00253 ep = first_out_edge(event); 00254 } 00255 ss_iterator sit_pred, sit; 00256 /* PRECONDITION: 00257 only ingoing => e is lowest in ingoing bundle 00258 only outgoing => e is highest in outgoing bundle 00259 ingoing and outgoing => e is lowest in ingoing bundle */ 00260 eb_high = e_end = ep; 00261 eb_low = e; 00262 CGAL_NEF_TRACEN("determining handle in SL"); 00263 if ( e != SHalfedge_handle() ) { 00264 e_search->twin()->source()->point() = p_sweep; // degenerate loop edge 00265 sit_pred = SLItem[e]; 00266 if ( sit_pred != SL.end()) sit = --sit_pred; 00267 else sit = sit_pred = --SL.upper_bound(e_search); 00268 } else { // event is isolated vertex 00269 e_search->twin()->source()->point() = p_sweep; // degenerate loop edge 00270 sit_pred = --SL.upper_bound(e_search); 00271 } 00272 00273 bool ending_edges(0), starting_edges(0); 00274 while ( e != SHalfedge_handle() ) { // walk adjacency list clockwise 00275 if ( SLItem[e] != SL.end() ) 00276 { 00277 CGAL_NEF_TRACEN("ending " << segment(e)); 00278 if (ending_edges) triangulate_between(e,cyclic_adj_succ(e)); 00279 ending_edges = true; 00280 SL.erase(SLItem[e]); 00281 link_bi_edge_to(e,SL.end()); 00282 // not in SL anymore 00283 } 00284 else 00285 { 00286 CGAL_NEF_TRACEN("starting "<<segment(e)); 00287 sit = SL.insert(sit,ss_pair(e,e)); 00288 link_bi_edge_to(e,sit); 00289 if ( !starting_edges ) eb_high = cyclic_adj_succ(e); 00290 starting_edges = true; 00291 } 00292 00293 if (e == e_end) break; 00294 e = cyclic_adj_pred(e); 00295 } 00296 if (!ending_edges) 00297 { 00298 SHalfedge_handle e_vis = sit_pred->second; 00299 SHalfedge_handle e_vis_n = cyclic_adj_succ(e_vis); 00300 eb_low = eb_high = new_bi_edge(event,e_vis_n); 00301 CGAL_NEF_TRACEN(" producing link "<<segment(eb_low)<< 00302 "\n before "<<segment(e_vis_n)); 00303 } 00304 00305 triangulate_up(eb_high); 00306 triangulate_down(eb_low); 00307 sit_pred->second = eb_low; 00308 } 00309 00310 bool event_exists() 00311 { if ( event_it != event_Q.end() ) { 00312 // event is set at end of loop and in init 00313 event = *event_it; 00314 p_sweep = event->point(); 00315 return true; 00316 } 00317 return false; 00318 } 00319 00320 void procede_to_next_event() 00321 { ++event_it; } 00322 00323 void link_bi_edge_to(SHalfedge_handle e, ss_iterator sit) { 00324 SLItem[e] = SLItem[e->twin()] = sit; 00325 } 00326 00327 void initialize_structures() 00328 { 00329 CGAL_NEF_TRACEN("initialize_structures "); 00330 00331 for ( event = v_first; event != v_beyond; ++event ) 00332 event_Q.insert(event); // sorted order of vertices 00333 00334 event_it = event_Q.begin(); 00335 if ( event_Q.empty() ) return; 00336 event = *event_it; 00337 p_sweep = event->point(); 00338 if ( !is_isolated(event) ) { 00339 SHalfedge_around_svertex_circulator 00340 e(first_out_edge(event)), eend(e); 00341 CGAL_For_all(e,eend) { 00342 CGAL_NEF_TRACEN("init with "<<PH(e)); 00343 ss_iterator sit = SL.insert(ss_pair(e,e)).first; 00344 link_bi_edge_to(e,sit); 00345 } 00346 } 00347 00348 00349 SVertex_handle v_tmp = new_svertex(Point()); 00350 e_high = Base::new_shalfedge_pair(event,v_tmp); 00351 e_low = Base::new_shalfedge_pair(event,v_tmp); 00352 // this are two symbolic edges just accessed as sentinels 00353 // they carry no geometric information 00354 e_search = Base::new_shalfedge_pair(v_tmp,v_tmp); 00355 // this is just a loop used for searches in SL 00356 00357 ss_iterator sit_high = SL.insert(ss_pair(e_high,e_high)).first; 00358 ss_iterator sit_low = SL.insert(ss_pair(e_low,e_low)).first; 00359 // inserting sentinels into SL 00360 link_bi_edge_to(e_high, sit_high); 00361 link_bi_edge_to(e_low , sit_low); 00362 // we mark them being in the sweepline, which they will never leave 00363 00364 00365 // we move to the second vertex: 00366 procede_to_next_event(); 00367 event_exists(); // sets p_sweep for check invariants 00368 CGAL_NEF_TRACEN("EOF initialization"); 00369 } 00370 00371 void complete_structures() 00372 { 00373 if (e_low != SHalfedge_handle()) { 00374 delete_vertex(e_search->twin()->source()); 00375 } // removing sentinels and e_search 00376 } 00377 00378 00379 void check_ccw_local_embedding() const 00380 { 00381 #ifdef CGAL_CHECK_EXPENSIVEXXX 00382 PM_checker<Decorator_,Kernel_> C(*this,K); 00383 C.check_order_preserving_embedding(event); 00384 #endif 00385 } 00386 00387 void check_invariants() 00388 { 00389 #ifdef CGAL_CHECK_EXPENSIVEXXX 00390 if ( event_it == event_Q.end() ) return; 00391 check_ccw_local_embedding(); 00392 #endif 00393 } 00394 00395 void check_final() 00396 { 00397 #ifdef CGAL_CHECK_EXPENSIVEXXX 00398 PM_checker<Decorator_,Kernel_> C(*this,K); C.check_is_triangulation(); 00399 #endif 00400 } 00401 00402 }; // SM_constrained_triang_traits<Decorator_,Kernel_,New_edge_> 00403 00404 00405 CGAL_END_NAMESPACE 00406 #endif // CGAL_SM_CONSTRAINED_TRIANG_TRAITS_H 00407