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/PM_const_decorator.h $ 00015 // $Id: PM_const_decorator.h 28567 2006-02-16 14:30:13Z lsaboret $ 00016 // 00017 // 00018 // Author(s) : Michael Seel <seel@mpi-sb.mpg.de> 00019 00020 #ifndef CGAL_PM_CONST_DECORATOR_H 00021 #define CGAL_PM_CONST_DECORATOR_H 00022 00023 #include <CGAL/basic.h> 00024 #include <CGAL/Unique_hash_map.h> 00025 #include <string> 00026 #include <list> 00027 #include <sstream> 00028 #include <CGAL/Nef_2/Object_index.h> 00029 #include <CGAL/Nef_2/iterator_tools.h> 00030 #undef CGAL_NEF_DEBUG 00031 #define CGAL_NEF_DEBUG 7 00032 #include <CGAL/Nef_2/debug.h> 00033 00034 CGAL_BEGIN_NAMESPACE 00035 00036 template <typename Iter, typename Move> 00037 inline CGAL::Circulator_tag 00038 query_circulator_or_iterator(const CircFromIt<Iter,Move>& ) 00039 { return CGAL::Circulator_tag(); } 00040 00041 00042 template <typename HE> 00043 class move_halfedge_around_vertex { 00044 public: 00045 void forward(HE& e) const { e = (e->prev()->opposite()); } 00046 void backward(HE& e) const { e = (e->opposite()->next()); } 00047 }; 00048 00049 template <typename HE> 00050 struct move_halfedge_around_face { 00051 void forward(HE& e) const { e = (e->next()); } 00052 void backward(HE& e) const { e = (e->prev()); } 00053 }; 00054 00055 00056 /*{\Moptions print_title=yes}*/ 00057 /*{\Moptions constref=yes}*/ 00058 /*{\Msubst 00059 PM_const_decorator#PMConstDecorator 00060 PM_decorator#PMDecorator 00061 }*/ 00062 /*{\Moptions outfile=PMConstDecorator.man }*/ 00063 /*{\Manpage {PMConstDecorator}{}{Topological plane map exploration}{D}}*/ 00064 00065 template <typename HDS> class PM_decorator; 00066 00067 template <typename HDS> 00068 class PM_const_decorator 00069 { typedef PM_const_decorator<HDS> Self; 00070 /*{\Mdefinition An instance |\Mvar| of the data type |\Mname| is a 00071 decorator for interfacing the topological structure of a plane map |P| 00072 (read-only). 00073 00074 A plane map |P| consists of a triple $(V, E, F)$ of vertices, edges, and 00075 faces. We collectively call them objects. An edge |e| is a pair of 00076 vertices |(v,w)| with incidence operations |v = source(e)|, |w = 00077 target(e)|. The list of all edges with source |v| is called the 00078 adjacency list |A(v)|. 00079 00080 Edges are paired into twins. For each edge |e = (v,w)| there's an edge 00081 |twin(e) = (w,v)| and |twin(twin(e)) == e|\footnote{The existence of 00082 the edge pairs makes |P| a bidirected graph, the |twin| links make 00083 |P| a map.}. 00084 00085 An edge |e = (v,w)| knows two adjacent edges |en = next(e)| and |ep 00086 = previous(e)| where |source(en) = w|, |previous(en) = e| and 00087 |target(ep) = v| and |next(ep) = e|. By this symmetric |previous-next| 00088 relationship all edges are partitioned into face cycles. Two edges 00089 $e$ and $e'$ are in the same face cycle if $e = |next|^*(e')$. All 00090 edges |e| in the same face cycle have the same incident face $f = 00091 |face|(e)$. The cyclic order on the adjacency list of a vertex |v = 00092 source(e)| is given by |cyclic_adj_succ(e) = twin(previous(e))| and 00093 |cyclic_adj_pred(e) = next(twin(e))|. 00094 00095 A vertex |v| is embedded via coordinates |point(v)|. By the 00096 embedding of its source and target an edge corresponds to a 00097 segment. |P| has the property that the embedding is always 00098 \emph{order-preserving}. This means a ray fixed in |point(v)| of a 00099 vertex |v| and swept around counterclockwise meets the embeddings of 00100 |target(e)| ($e \in A(v)$) in the cyclic order defined by the list 00101 order of |A|. 00102 00103 The embedded face cycles partition the plane into maximal connected 00104 subsets of points. Each such set corresponds to a face. A face is 00105 bounded by its incident face cycles. For all the edges in the 00106 non-trivial face cycles it holds that the face is left of the edges. 00107 There can also be trivial face cycles in form of isolated vertices in 00108 the interior of a face. Each such vertex |v| knows its surrounding 00109 face |f = face(v)|. 00110 00111 We call the embedded map |(V,E)| also the $1$-skeleton of |P|. 00112 00113 Plane maps are attributed. To each object $u \in V \cup E \cup F$ 00114 we attribute a value |mark(u)| of type |Mark|. |Mark| fits the 00115 concepts assignable, default-constructible, and equal-comparable.}*/ 00116 00117 protected: 00118 HDS* phds; 00119 friend class PM_decorator<HDS>; 00120 00121 public: 00122 /*{\Mtypes 6}*/ 00123 typedef HDS Plane_map; 00124 /*{\Mtypemember The underlying plane map type}*/ 00125 00126 typedef typename HDS::Traits Traits; 00127 00128 typedef typename Traits::Point Point; 00129 /*{\Mtypemember The point type of vertices.}*/ 00130 typedef typename Traits::Mark Mark; 00131 /*{\Mtypemember All objects (vertices, edges, faces) are attributed by a 00132 |Mark| object.}*/ 00133 typedef size_t Size_type; 00134 /*{\Mtypemember The size type.}*/ 00135 typedef void* GenPtr; 00136 00137 00138 typedef typename HDS::Vertex Vertex; 00139 typedef typename HDS::Vertex_base Vertex_base; 00140 typedef typename HDS::Vertex_handle Vertex_handle; 00141 typedef typename HDS::Vertex_const_handle Vertex_const_handle; 00142 typedef typename HDS::Vertex_const_iterator Vertex_const_iterator; 00143 typedef typename HDS::Halfedge Halfedge ; 00144 typedef typename HDS::Halfedge_base Halfedge_base ; 00145 typedef typename HDS::Halfedge_handle Halfedge_handle; 00146 typedef typename HDS::Halfedge_const_handle Halfedge_const_handle; 00147 typedef typename HDS::Halfedge_const_iterator Halfedge_const_iterator; 00148 typedef typename HDS::Face Face; 00149 typedef typename HDS::Face_base Face_base; 00150 typedef typename HDS::Face_handle Face_handle; 00151 typedef typename HDS::Face_const_handle Face_const_handle; 00152 typedef typename HDS::Face_const_iterator Face_const_iterator; 00153 00154 00155 /*{\Mtext Local types are handles, iterators and circulators of the 00156 following kind: |Vertex_const_handle|, 00157 |Vertex_const_iterator|, |Halfedge_const_handle|, 00158 |Halfedge_const_iterator|, |Face_const_handle|, |Face_\-const_\-ite\-rator|. 00159 Additionally the following circulators are defined.}*/ 00160 00161 typedef CircFromIt< 00162 Halfedge_const_iterator, 00163 move_halfedge_around_vertex<Halfedge_const_iterator> > 00164 Halfedge_around_vertex_const_circulator; 00165 /*{\Mtypemember circulating the outgoing halfedges in $A(v)$.}*/ 00166 00167 typedef CircFromIt< 00168 Halfedge_const_iterator, 00169 move_halfedge_around_face<Halfedge_const_iterator> > 00170 Halfedge_around_face_const_circulator; 00171 /*{\Mtypemember circulating the halfedges in the face cycle of a 00172 face |f|.}*/ 00173 00174 typedef typename Face::Hole_const_iterator Hole_const_iterator; 00175 /*{\Mtypemember iterating all holes of a face |f|. The type is 00176 convertible to |Halfedge_const_handle|.}*/ 00177 00178 typedef typename Face::Isolated_vertex_const_iterator 00179 Isolated_vertex_const_iterator; 00180 /*{\Mtypemember iterating all isolated vertices of a face |f|. 00181 The type generalizes |Vertex_const_handle|.}*/ 00182 00183 typedef PntItFromVertIt<Vertex_const_iterator,Point> 00184 Point_const_iterator; 00185 00186 /*{\Mcreation 3}*/ 00187 00188 PM_const_decorator() : phds(0) {} 00189 PM_const_decorator(const PM_const_decorator<HDS>& D) : 00190 phds(D.phds) {} 00191 PM_const_decorator& operator=( 00192 const PM_const_decorator<HDS>& D) 00193 { phds=D.phds; return *this; } 00194 00195 PM_const_decorator(const Plane_map& P) 00196 /*{\Mcreate constructs a plane map decorator exploring |P|.}*/ 00197 : phds(const_cast<HDS*>(&P)) {} 00198 00199 /*{\Moperations 4 4}*/ 00200 00201 Vertex_const_handle source(Halfedge_const_handle e) const 00202 /*{\Mop returns the source of |e|.}*/ 00203 { return e->opposite()->vertex(); } 00204 00205 Vertex_const_handle target(Halfedge_const_handle e) const 00206 /*{\Mop returns the target of |e|.}*/ 00207 { return e->vertex(); } 00208 00209 Halfedge_const_handle twin(Halfedge_const_handle e) const 00210 /*{\Mop returns the twin of |e|.}*/ 00211 { return e->opposite(); } 00212 00213 bool is_isolated(Vertex_const_handle v) const 00214 /*{\Mop returns |true| iff $A(v) = \emptyset$.}*/ 00215 { return v->is_isolated(); } 00216 00217 Halfedge_const_handle first_out_edge(Vertex_const_handle v) const 00218 /*{\Mop returns one halfedge with source |v|. It's the starting point for 00219 the circular iteration over the halfedges with source |v|. 00220 \precond |!is_isolated(v)|.}*/ 00221 { return v->halfedge()->opposite(); } 00222 00223 Halfedge_const_handle last_out_edge(Vertex_const_handle v) const 00224 /*{\Mop returns the halfedge with source |v| that is the last 00225 in the circular iteration before encountering |first_out_edge(v)| 00226 again. \precond |!is_isolated(v)|.}*/ 00227 { return v->halfedge()->next(); } 00228 00229 Halfedge_const_handle cyclic_adj_succ( 00230 Halfedge_const_handle e) const 00231 /*{\Mop returns the edge after |e| in the cyclic ordered adjacency list of 00232 |source(e)|.}*/ 00233 { return e->prev()->opposite(); } 00234 00235 Halfedge_const_handle cyclic_adj_pred( 00236 Halfedge_const_handle e) const 00237 /*{\Mop returns the edge before |e| in the cyclic ordered adjacency list of 00238 |source(e)|.}*/ 00239 { return e->opposite()->next(); } 00240 00241 00242 Halfedge_const_handle next(Halfedge_const_handle e) const 00243 /*{\Mop returns the next edge in the face cycle containing |e|.}*/ 00244 { return e->next(); } 00245 00246 Halfedge_const_handle previous(Halfedge_const_handle e) const 00247 /*{\Mop returns the previous edge in the face cycle containing |e|.}*/ 00248 { return e->prev(); } 00249 00250 Face_const_handle face(Halfedge_const_handle e) const 00251 /*{\Mop returns the face incident to |e|.}*/ 00252 { return e->face(); } 00253 00254 Face_const_handle face(Vertex_const_handle v) const 00255 /*{\Mop returns the face incident to |v|. 00256 \precond |is_isolated(v)|.}*/ 00257 { return v->face(); } 00258 00259 Halfedge_const_handle halfedge(Face_const_handle f) const 00260 /*{\Mop returns a halfedge in the bounding face cycle of |f| 00261 (|Halfedge_const_handle()| if there is no bounding face cycle).}*/ 00262 { return f->halfedge(); } 00263 00264 00265 /*{\Mtext \headerline{Iteration} \setopdims{7.5cm}{0cm}}*/ 00266 00267 Vertex_const_iterator vertices_begin() const 00268 { return phds->vertices_begin(); } 00269 Halfedge_const_iterator halfedges_begin() const 00270 { return phds->halfedges_begin(); } 00271 Face_const_iterator faces_begin() const 00272 { return phds->faces_begin(); } 00273 Vertex_const_iterator vertices_end() const 00274 { return phds->vertices_end(); } 00275 Halfedge_const_iterator halfedges_end() const 00276 { return phds->halfedges_end(); } 00277 Face_const_iterator faces_end() const 00278 { return phds->faces_end(); } 00279 Point_const_iterator points_begin() const 00280 { return Point_const_iterator(vertices_begin()); } 00281 Point_const_iterator points_end() const 00282 { return Point_const_iterator(vertices_end()); } 00283 00284 Halfedge_around_vertex_const_circulator 00285 out_edges(Vertex_const_handle v) const 00286 /*{\Mop returns a circulator for the cyclic adjacency list of |v|.}*/ 00287 { return Halfedge_around_vertex_const_circulator(first_out_edge(v)); } 00288 00289 Halfedge_around_face_const_circulator 00290 face_cycle(Face_const_handle f) const 00291 /*{\Mop returns a circulator for the outer face cycle of |f|.}*/ 00292 { return Halfedge_around_face_const_circulator(f->halfedge()); } 00293 00294 Hole_const_iterator holes_begin(Face_const_handle f) const 00295 /*{\Mop returns an iterator for all holes in the interior of |f|. 00296 A |Hole_iterator| can be assigned to a 00297 |Halfedge_around_face_const_circulator|.}*/ 00298 { return f->fc_begin(); } 00299 00300 Hole_const_iterator holes_end(Face_const_handle f) const 00301 /*{\Mop returns the past-the-end iterator of |f|.}*/ 00302 { return f->fc_end(); } 00303 00304 Isolated_vertex_const_iterator 00305 isolated_vertices_begin(Face_const_handle f) const 00306 /*{\Mop returns an iterator for all isolated vertices in the interior 00307 of |f|.}*/ 00308 { return f->iv_begin(); } 00309 00310 Isolated_vertex_const_iterator 00311 isolated_vertices_end(Face_const_handle f) const 00312 /*{\Mop returns the past the end iterator of |f|.}*/ 00313 { return f->iv_end(); } 00314 00315 00316 /*{\Mtext \headerline{Associated Information}\setopdims{2.5cm}{4cm} 00317 The type |Mark| is the general attribute of an object. The type 00318 |GenPtr| is equal to type |void*|.}*/ 00319 00320 const Point& point(Vertex_const_handle v) const 00321 /*{\Mop returns the embedding of |v|.}*/ 00322 { return v->point(); } 00323 00324 const Mark& mark(Vertex_const_handle v) const 00325 /*{\Mop returns the mark of |v|.}*/ 00326 { return v->mark(); } 00327 00328 const Mark& mark(Halfedge_const_handle e) const 00329 /*{\Mop returns the mark of |e|.}*/ 00330 { if (&*e < &*(e->opposite())) return e->mark(); 00331 else return e->opposite()->mark(); 00332 } // we store the mark in the container with smaller memory address ! 00333 00334 const Mark& mark(Face_const_handle f) const 00335 /*{\Mop returns the mark of |f|.}*/ 00336 { return f->mark(); } 00337 00338 const GenPtr& info(Vertex_const_handle v) const 00339 /*{\Mop returns a generic information slot.}*/ 00340 { return v->info(); } 00341 00342 const GenPtr& info(Halfedge_const_handle e) const 00343 /*{\Mop returns a generic information slot.}*/ 00344 { return e->info(); } 00345 00346 const GenPtr& info(Face_const_handle f) const 00347 /*{\Mop returns a generic information slot.}*/ 00348 { return f->info(); } 00349 00350 00351 /*{\Mtext \headerline{Statistics and Integrity}}*/ 00352 00353 Size_type number_of_vertices() const 00354 /*{\Mop returns the number of vertices.}*/ 00355 { return phds->size_of_vertices(); } 00356 00357 Size_type number_of_halfedges() const 00358 /*{\Mop returns the number of halfedges.}*/ 00359 { return phds->size_of_halfedges(); } 00360 00361 Size_type number_of_edges() const 00362 /*{\Mop returns the number of halfedge pairs.}*/ 00363 { return phds->size_of_halfedges()/2; } 00364 00365 Size_type number_of_faces() const 00366 /*{\Mop returns the number of faces.}*/ 00367 { return phds->size_of_faces(); } 00368 00369 Size_type number_of_face_cycles() const; 00370 /*{\Mop returns the number of face cycles.}*/ 00371 00372 Size_type number_of_connected_components() const; 00373 /*{\Mop calculates the number of connected components of |P|.}*/ 00374 00375 void print_statistics(std::ostream& os = std::cout) const 00376 /*{\Mop print the statistics of |P|: the number of vertices, edges, and 00377 faces.}*/ 00378 { 00379 os << "Plane Map - Statistics\n"; 00380 os << "|V| = " << number_of_vertices() << std::endl; 00381 os << "|E| = " << number_of_edges() 00382 << " (" << 2*number_of_edges() << ")" << std::endl; 00383 os << "|F| = " << number_of_faces() << std::endl; 00384 os << "|Fcs| = " << number_of_face_cycles() << std::endl << std::endl; 00385 } 00386 00387 void check_integrity_and_topological_planarity(bool faces=true) const; 00388 /*{\Mop checks the link structure and the genus of |P|.}*/ 00389 00390 }; // PM_const_decorator 00391 00392 template <class VH> 00393 std::string PV(VH v) 00394 { std::ostringstream os; CGAL::set_pretty_mode(os); 00395 if (v != VH()) os << v->point(); 00396 else os << "nil"; 00397 return os.str(); 00398 } 00399 00400 template <class HH> 00401 std::string PE(HH e) 00402 { std::ostringstream os; 00403 if (e==HH()) return "nil"; 00404 os << "[" << PV(e->opposite()->vertex()) << "," 00405 << PV(e->vertex()) << " " << e->info() << "]"; 00406 return os.str(); 00407 } 00408 00409 template <typename HDS> 00410 void PM_const_decorator<HDS>:: 00411 check_integrity_and_topological_planarity(bool faces) const 00412 { 00413 CGAL_NEF_TRACEN("check_integrity_and_topological_planarity:"); 00414 using CGAL::Object_index; 00415 Object_index<Vertex_const_iterator> 00416 VI(vertices_begin(),vertices_end(),'v'); 00417 Object_index<Halfedge_const_iterator> 00418 EI(halfedges_begin(),halfedges_end(),'e'); 00419 Object_index<Face_const_iterator> 00420 FI(faces_begin(),faces_end(),'f'); 00421 typedef Halfedge_around_vertex_const_circulator hvc_circulator; 00422 typedef Halfedge_around_face_const_circulator hfc_circulator; 00423 Vertex_const_handle vit, vend = phds->vertices_end(); 00424 int iso_vert_num=0; 00425 /* check the source links of out edges and count isolated vertices */ 00426 for (vit = vertices_begin() ; vit != vend; ++vit) { 00427 if ( is_isolated(vit) ) { 00428 if ( faces ) 00429 CGAL_assertion_msg( vit->face() != Face_const_handle(), 00430 VI(vit).c_str()); 00431 ++iso_vert_num; 00432 } else { 00433 CGAL_assertion_msg( vit->halfedge() != Halfedge_const_handle(), 00434 VI(vit).c_str()); 00435 CGAL_assertion_msg( vit->halfedge()->vertex() == vit ,VI(vit).c_str()); 00436 } 00437 } 00438 00439 /* check the bidirected links and the face pointer init */ 00440 Halfedge_const_iterator eit, eend = phds->halfedges_end(); 00441 for (eit = phds->halfedges_begin() ; eit != eend; ++eit) { 00442 CGAL_assertion( twin(twin(eit)) == eit ); 00443 CGAL_assertion( eit->vertex() != Vertex_const_handle() ); 00444 CGAL_assertion( next(eit) != Halfedge_const_handle() ); 00445 CGAL_assertion( previous(next(eit)) == eit ); 00446 CGAL_assertion( target(eit) == source(next(eit)) ); 00447 CGAL_assertion( previous(eit) != Halfedge_const_handle() ); 00448 CGAL_assertion( next(previous(eit)) == eit ); 00449 CGAL_assertion( target(previous(eit)) == source(eit) ); 00450 if ( !faces ) continue; 00451 CGAL_assertion( face(eit) != Face_const_handle() ); 00452 CGAL_assertion( face(next(eit)) == face(eit) ); 00453 CGAL_assertion( face(previous(eit)) == face(eit) ); 00454 } 00455 00456 bool first=true; 00457 int fc_num(0),iv_num(0); 00458 Face_const_iterator fit; 00459 for (fit = faces_begin(); fit != faces_end(); ++fit) { 00460 if (!first) { 00461 CGAL_assertion( face(halfedge(fit))==fit ); ++fc_num; 00462 } 00463 Hole_const_iterator fcit; 00464 for( fcit = holes_begin(fit); fcit != holes_end(fit); ++fcit) { 00465 CGAL_assertion( face(fcit)==fit ); ++fc_num; 00466 } 00467 Isolated_vertex_const_iterator ivit; 00468 for(ivit = isolated_vertices_begin(fit); 00469 ivit != isolated_vertices_end(fit); ++ivit) { 00470 CGAL_assertion( face(ivit)==fit ); ++iv_num; 00471 } 00472 first=false; 00473 } 00474 00475 int v_num = number_of_vertices() - iso_vert_num; 00476 int e_num = number_of_edges(); 00477 int c_num = number_of_connected_components() - iso_vert_num; 00478 int f_num = number_of_face_cycles() - c_num + 1; 00479 CGAL_NEF_TRACEV(fc_num);CGAL_NEF_TRACEV(iv_num);CGAL_NEF_TRACEV(iso_vert_num); 00480 CGAL_NEF_TRACEV(v_num);CGAL_NEF_TRACEV(e_num);CGAL_NEF_TRACEV(c_num);CGAL_NEF_TRACEV(f_num); 00481 // CGAL_assertion(fc_num == f_num && iv_num == iso_vert_num); 00482 /* this means all face cycles and all isolated vertices are 00483 indeed referenced from a face */ 00484 /* every isolated vertex increases the component count 00485 one face cycle per component is redundent except one 00486 finally check the Euler formula: */ 00487 CGAL_assertion( v_num - e_num + f_num == 1 + c_num ); 00488 } 00489 00490 template <typename HDS> 00491 typename PM_const_decorator<HDS>::Size_type 00492 PM_const_decorator<HDS>:: 00493 number_of_face_cycles() const 00494 { 00495 unsigned int fc_num=0; 00496 CGAL::Unique_hash_map<Halfedge_const_handle,bool> visited; 00497 // init with bool() == false 00498 Halfedge_const_iterator eit = phds->halfedges_begin(); 00499 Halfedge_const_iterator eend = phds->halfedges_end(); 00500 for ( ; eit != eend; ++eit) { 00501 if (visited[eit]) continue; 00502 Halfedge_around_face_const_circulator hfc(eit), hend(hfc); 00503 CGAL_For_all(hfc,hend) visited[hfc]=true; 00504 ++fc_num; 00505 } 00506 return fc_num; 00507 } 00508 00509 template <typename HDS> 00510 size_t PM_const_decorator<HDS>:: 00511 number_of_connected_components() const 00512 { 00513 typedef Vertex_const_iterator vc_handle; 00514 typedef Halfedge_around_vertex_const_circulator hvc_circulator; 00515 int comp_num=0; 00516 CGAL::Unique_hash_map< vc_handle, bool> handled(false); 00517 vc_handle vit = vertices_begin(), vend = vertices_end(); 00518 for ( ; vit != vend; ++vit) { 00519 if (handled[vit]) continue; 00520 std::list<vc_handle> L; 00521 L.push_back(vit); handled[vit]=true; 00522 /* we keep the invariant that all nodes which have been stacked 00523 are marked handled */ 00524 while (!L.empty()) { 00525 vc_handle v=L.front(); L.pop_front(); 00526 if ( is_isolated(v) ) continue; 00527 hvc_circulator havc(first_out_edge(v)), hend(havc); 00528 CGAL_For_all(havc,hend) { 00529 if (!handled[target(havc)]) { 00530 L.push_back(target(havc)); handled[target(havc)]=true; 00531 } 00532 } 00533 } 00534 ++comp_num; 00535 } 00536 return comp_num; 00537 } 00538 00539 struct KERNELPNT { 00540 template <typename PNT> 00541 std::string operator() (const PNT& p) const 00542 { std::ostringstream os; 00543 os << "(" << CGAL::to_double(p.x()) << "," 00544 << CGAL::to_double(p.y()) << ")"; 00545 return os.str(); 00546 } 00547 }; 00548 00549 template <typename PMCDEC, typename POINTDA> 00550 void print_as_leda_graph(std::ostream& os, const PMCDEC& D, 00551 const POINTDA& P) 00552 { 00553 typedef typename PMCDEC::Vertex_const_iterator 00554 Vertex_const_iterator; 00555 typedef typename PMCDEC::Halfedge_const_iterator 00556 Halfedge_const_iterator; 00557 int vn(1), en(1); 00558 CGAL::Unique_hash_map<Vertex_const_iterator,int> v_num; 00559 CGAL::Unique_hash_map<Halfedge_const_iterator,int> e_num; 00560 os << "LEDA.GRAPH\n" << "point\n" << "int\n"; 00561 os << D.number_of_vertices() << std::endl; 00562 Vertex_const_iterator vit; 00563 for (vit = D.vertices_begin(); vit != D.vertices_end(); ++vit) { 00564 v_num[vit] = vn++; 00565 os << "|{(" << P(D.point(vit)) << ")}|\n"; 00566 typename PMCDEC::Halfedge_around_vertex_const_circulator 00567 ecirc(D.first_out_edge(vit)),ecend(ecirc); 00568 int l=0; 00569 CGAL_For_all(ecirc,ecend) e_num[ecirc]=l++; 00570 } 00571 os << 2* D.number_of_edges() << std::endl; 00572 Halfedge_const_iterator eit; 00573 for (eit = D.halfedges_begin(); eit != D.halfedges_end(); ++eit) { 00574 e_num[eit] = en++; 00575 } 00576 for (eit = D.halfedges_begin(); eit != D.halfedges_end(); ++eit) { 00577 os << v_num[D.source(eit)] << " " 00578 << v_num[D.target(eit)] << " " 00579 << e_num[D.twin(eit)] << " "; 00580 os << "|{" << e_num[eit] << "}|\n"; 00581 } 00582 os << std::flush; 00583 } 00584 00585 00586 00587 CGAL_END_NAMESPACE 00588 #endif // CGAL_PM_CONST_DECORATOR_H 00589