1 // Copyright (c) 1997-2000 Max-Planck-Institute Saarbruecken (Germany).
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org).
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Nef_2/include/CGAL/Nef_2/PM_const_decorator.h $
7 // $Id: PM_const_decorator.h 4e519a3 2021-05-05T13:15:37+02:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 //
11 // Author(s) : Michael Seel <seel@mpi-sb.mpg.de>
12
13 #ifndef CGAL_PM_CONST_DECORATOR_H
14 #define CGAL_PM_CONST_DECORATOR_H
15
16 #include <CGAL/license/Nef_2.h>
17
18
19 #include <CGAL/basic.h>
20 #include <CGAL/Unique_hash_map.h>
21 #include <string>
22 #include <list>
23 #include <sstream>
24 #include <CGAL/Nef_2/Object_index.h>
25 #include <CGAL/Nef_2/iterator_tools.h>
26 #undef CGAL_NEF_DEBUG
27 #define CGAL_NEF_DEBUG 7
28 #include <CGAL/Nef_2/debug.h>
29
30 #ifndef CGAL_I_DO_WANT_TO_USE_GENINFO
31 #include <boost/any.hpp>
32 #endif
33
34 #include <CGAL/use.h>
35
36 namespace CGAL {
37
38 template <typename Iter, typename Move>
39 inline CGAL::Circulator_tag
query_circulator_or_iterator(const CircFromIt<Iter,Move> &)40 query_circulator_or_iterator(const CircFromIt<Iter,Move>& )
41 { return CGAL::Circulator_tag(); }
42
43
44 template <typename HE>
45 class move_halfedge_around_vertex {
46 public:
forward(HE & e)47 void forward(HE& e) const { e = (e->prev()->opposite()); }
backward(HE & e)48 void backward(HE& e) const { e = (e->opposite()->next()); }
49 };
50
51 template <typename HE>
52 struct move_halfedge_around_face {
forwardmove_halfedge_around_face53 void forward(HE& e) const { e = (e->next()); }
backwardmove_halfedge_around_face54 void backward(HE& e) const { e = (e->prev()); }
55 };
56
57
58 /*{\Moptions print_title=yes}*/
59 /*{\Moptions constref=yes}*/
60 /*{\Msubst
61 PM_const_decorator#PMConstDecorator
62 PM_decorator#PMDecorator
63 }*/
64 /*{\Moptions outfile=PMConstDecorator.man }*/
65 /*{\Manpage {PMConstDecorator}{}{Topological plane map exploration}{D}}*/
66
67 template <typename HDS> class PM_decorator;
68
69 template <typename HDS>
70 class PM_const_decorator
71 { typedef PM_const_decorator<HDS> Self;
72 /*{\Mdefinition An instance |\Mvar| of the data type |\Mname| is a
73 decorator for interfacing the topological structure of a plane map |P|
74 (read-only).
75
76 A plane map |P| consists of a triple $(V, E, F)$ of vertices, edges, and
77 faces. We collectively call them objects. An edge |e| is a pair of
78 vertices |(v,w)| with incidence operations |v = source(e)|, |w =
79 target(e)|. The list of all edges with source |v| is called the
80 adjacency list |A(v)|.
81
82 Edges are paired into twins. For each edge |e = (v,w)| there's an edge
83 |twin(e) = (w,v)| and |twin(twin(e)) == e|\cgalFootnote{The existence of
84 the edge pairs makes |P| a bidirected graph, the |twin| links make
85 |P| a map.}.
86
87 An edge |e = (v,w)| knows two adjacent edges |en = next(e)| and |ep
88 = previous(e)| where |source(en) = w|, |previous(en) = e| and
89 |target(ep) = v| and |next(ep) = e|. By this symmetric |previous-next|
90 relationship all edges are partitioned into face cycles. Two edges
91 $e$ and $e'$ are in the same face cycle if $e = |next|^*(e')$. All
92 edges |e| in the same face cycle have the same incident face $f =
93 |face|(e)$. The cyclic order on the adjacency list of a vertex |v =
94 source(e)| is given by |cyclic_adj_succ(e) = twin(previous(e))| and
95 |cyclic_adj_pred(e) = next(twin(e))|.
96
97 A vertex |v| is embedded via coordinates |point(v)|. By the
98 embedding of its source and target an edge corresponds to a
99 segment. |P| has the property that the embedding is always
100 \emph{order-preserving}. This means a ray fixed in |point(v)| of a
101 vertex |v| and swept around counterclockwise meets the embeddings of
102 |target(e)| ($e \in A(v)$) in the cyclic order defined by the list
103 order of |A|.
104
105 The embedded face cycles partition the plane into maximal connected
106 subsets of points. Each such set corresponds to a face. A face is
107 bounded by its incident face cycles. For all the edges in the
108 non-trivial face cycles it holds that the face is left of the edges.
109 There can also be trivial face cycles in form of isolated vertices in
110 the interior of a face. Each such vertex |v| knows its surrounding
111 face |f = face(v)|.
112
113 We call the embedded map |(V,E)| also the $1$-skeleton of |P|.
114
115 Plane maps are attributed. To each object $u \in V \cup E \cup F$
116 we attribute a value |mark(u)| of type |Mark|. |Mark| fits the
117 concepts assignable, default-constructible, and equal-comparable.}*/
118
119 protected:
120 HDS* phds;
121 friend class PM_decorator<HDS>;
122
123 public:
124 /*{\Mtypes 6}*/
125 typedef HDS Plane_map;
126 /*{\Mtypemember The underlying plane map type}*/
127
128 typedef typename HDS::Traits Traits;
129
130 typedef typename Traits::Point Point;
131 /*{\Mtypemember The point type of vertices.}*/
132 typedef typename Traits::Mark Mark;
133 /*{\Mtypemember All objects (vertices, edges, faces) are attributed by a
134 |Mark| object.}*/
135 typedef size_t Size_type;
136 #ifdef CGAL_I_DO_WANT_TO_USE_GENINFO
137 /*{\Mtypemember The size type.}*/
138 typedef void* GenPtr;
139 #else
140 typedef boost::any GenPtr;
141 #endif
142
143
144
145 typedef typename HDS::Vertex Vertex;
146 typedef typename HDS::Vertex_base Vertex_base;
147 typedef typename HDS::Vertex_handle Vertex_handle;
148 typedef typename HDS::Vertex_const_handle Vertex_const_handle;
149 typedef typename HDS::Vertex_const_iterator Vertex_const_iterator;
150 typedef typename HDS::Halfedge Halfedge ;
151 typedef typename HDS::Halfedge_base Halfedge_base ;
152 typedef typename HDS::Halfedge_handle Halfedge_handle;
153 typedef typename HDS::Halfedge_const_handle Halfedge_const_handle;
154 typedef typename HDS::Halfedge_const_iterator Halfedge_const_iterator;
155 typedef typename HDS::Face Face;
156 typedef typename HDS::Face_base Face_base;
157 typedef typename HDS::Face_handle Face_handle;
158 typedef typename HDS::Face_const_handle Face_const_handle;
159 typedef typename HDS::Face_const_iterator Face_const_iterator;
160
161
162 /*{\Mtext Local types are handles, iterators and circulators of the
163 following kind: |Vertex_const_handle|,
164 |Vertex_const_iterator|, |Halfedge_const_handle|,
165 |Halfedge_const_iterator|, |Face_const_handle|, |Face_\-const_\-ite\-rator|.
166 Additionally the following circulators are defined.}*/
167
168 typedef CircFromIt<
169 Halfedge_const_iterator,
170 move_halfedge_around_vertex<Halfedge_const_iterator> >
171 Halfedge_around_vertex_const_circulator;
172 /*{\Mtypemember circulating the outgoing halfedges in $A(v)$.}*/
173
174 typedef CircFromIt<
175 Halfedge_const_iterator,
176 move_halfedge_around_face<Halfedge_const_iterator> >
177 Halfedge_around_face_const_circulator;
178 /*{\Mtypemember circulating the halfedges in the face cycle of a
179 face |f|.}*/
180
181 typedef typename Face::Hole_const_iterator Hole_const_iterator;
182 /*{\Mtypemember iterating all holes of a face |f|. The type is
183 convertible to |Halfedge_const_handle|.}*/
184
185 typedef typename Face::Isolated_vertex_const_iterator
186 Isolated_vertex_const_iterator;
187 /*{\Mtypemember iterating all isolated vertices of a face |f|.
188 The type generalizes |Vertex_const_handle|.}*/
189
190 typedef PntItFromVertIt<Vertex_const_iterator,Point>
191 Point_const_iterator;
192
193 /*{\Mcreation 3}*/
194
PM_const_decorator()195 PM_const_decorator() : phds(0) {}
PM_const_decorator(const PM_const_decorator<HDS> & D)196 PM_const_decorator(const PM_const_decorator<HDS>& D) :
197 phds(D.phds) {}
198 PM_const_decorator& operator=(
199 const PM_const_decorator<HDS>& D)
200 { phds=D.phds; return *this; }
201
PM_const_decorator(const Plane_map & P)202 PM_const_decorator(const Plane_map& P)
203 /*{\Mcreate constructs a plane map decorator exploring |P|.}*/
204 : phds(const_cast<HDS*>(&P)) {}
205
206 /*{\Moperations 4 4}*/
207
source(Halfedge_const_handle e)208 Vertex_const_handle source(Halfedge_const_handle e) const
209 /*{\Mop returns the source of |e|.}*/
210 { return e->opposite()->vertex(); }
211
target(Halfedge_const_handle e)212 Vertex_const_handle target(Halfedge_const_handle e) const
213 /*{\Mop returns the target of |e|.}*/
214 { return e->vertex(); }
215
twin(Halfedge_const_handle e)216 Halfedge_const_handle twin(Halfedge_const_handle e) const
217 /*{\Mop returns the twin of |e|.}*/
218 { return e->opposite(); }
219
is_isolated(Vertex_const_handle v)220 bool is_isolated(Vertex_const_handle v) const
221 /*{\Mop returns |true| iff $A(v) = \emptyset$.}*/
222 { return v->is_isolated(); }
223
first_out_edge(Vertex_const_handle v)224 Halfedge_const_handle first_out_edge(Vertex_const_handle v) const
225 /*{\Mop returns one halfedge with source |v|. It's the starting point for
226 the circular iteration over the halfedges with source |v|.
227 \precond |!is_isolated(v)|.}*/
228 { return v->halfedge()->opposite(); }
229
last_out_edge(Vertex_const_handle v)230 Halfedge_const_handle last_out_edge(Vertex_const_handle v) const
231 /*{\Mop returns the halfedge with source |v| that is the last
232 in the circular iteration before encountering |first_out_edge(v)|
233 again. \precond |!is_isolated(v)|.}*/
234 { return v->halfedge()->next(); }
235
cyclic_adj_succ(Halfedge_const_handle e)236 Halfedge_const_handle cyclic_adj_succ(
237 Halfedge_const_handle e) const
238 /*{\Mop returns the edge after |e| in the cyclic ordered adjacency list of
239 |source(e)|.}*/
240 { return e->prev()->opposite(); }
241
cyclic_adj_pred(Halfedge_const_handle e)242 Halfedge_const_handle cyclic_adj_pred(
243 Halfedge_const_handle e) const
244 /*{\Mop returns the edge before |e| in the cyclic ordered adjacency list of
245 |source(e)|.}*/
246 { return e->opposite()->next(); }
247
248
next(Halfedge_const_handle e)249 Halfedge_const_handle next(Halfedge_const_handle e) const
250 /*{\Mop returns the next edge in the face cycle containing |e|.}*/
251 { return e->next(); }
252
previous(Halfedge_const_handle e)253 Halfedge_const_handle previous(Halfedge_const_handle e) const
254 /*{\Mop returns the previous edge in the face cycle containing |e|.}*/
255 { return e->prev(); }
256
face(Halfedge_const_handle e)257 Face_const_handle face(Halfedge_const_handle e) const
258 /*{\Mop returns the face incident to |e|.}*/
259 { return e->face(); }
260
face(Vertex_const_handle v)261 Face_const_handle face(Vertex_const_handle v) const
262 /*{\Mop returns the face incident to |v|.
263 \precond |is_isolated(v)|.}*/
264 { return v->face(); }
265
halfedge(Face_const_handle f)266 Halfedge_const_handle halfedge(Face_const_handle f) const
267 /*{\Mop returns a halfedge in the bounding face cycle of |f|
268 (|Halfedge_const_handle()| if there is no bounding face cycle).}*/
269 { return f->halfedge(); }
270
271
272 /*{\Mtext \headerline{Iteration} \setopdims{7.5cm}{0cm}}*/
273
vertices_begin()274 Vertex_const_iterator vertices_begin() const
275 { return phds->vertices_begin(); }
halfedges_begin()276 Halfedge_const_iterator halfedges_begin() const
277 { return phds->halfedges_begin(); }
faces_begin()278 Face_const_iterator faces_begin() const
279 { return phds->faces_begin(); }
vertices_end()280 Vertex_const_iterator vertices_end() const
281 { return phds->vertices_end(); }
halfedges_end()282 Halfedge_const_iterator halfedges_end() const
283 { return phds->halfedges_end(); }
faces_end()284 Face_const_iterator faces_end() const
285 { return phds->faces_end(); }
points_begin()286 Point_const_iterator points_begin() const
287 { return Point_const_iterator(vertices_begin()); }
points_end()288 Point_const_iterator points_end() const
289 { return Point_const_iterator(vertices_end()); }
290
291 Halfedge_around_vertex_const_circulator
out_edges(Vertex_const_handle v)292 out_edges(Vertex_const_handle v) const
293 /*{\Mop returns a circulator for the cyclic adjacency list of |v|.}*/
294 { return Halfedge_around_vertex_const_circulator(first_out_edge(v)); }
295
296 Halfedge_around_face_const_circulator
face_cycle(Face_const_handle f)297 face_cycle(Face_const_handle f) const
298 /*{\Mop returns a circulator for the outer face cycle of |f|.}*/
299 { return Halfedge_around_face_const_circulator(f->halfedge()); }
300
holes_begin(Face_const_handle f)301 Hole_const_iterator holes_begin(Face_const_handle f) const
302 /*{\Mop returns an iterator for all holes in the interior of |f|.
303 A |Hole_iterator| can be assigned to a
304 |Halfedge_around_face_const_circulator|.}*/
305 { return f->fc_begin(); }
306
holes_end(Face_const_handle f)307 Hole_const_iterator holes_end(Face_const_handle f) const
308 /*{\Mop returns the past-the-end iterator of |f|.}*/
309 { return f->fc_end(); }
310
311 Isolated_vertex_const_iterator
isolated_vertices_begin(Face_const_handle f)312 isolated_vertices_begin(Face_const_handle f) const
313 /*{\Mop returns an iterator for all isolated vertices in the interior
314 of |f|.}*/
315 { return f->iv_begin(); }
316
317 Isolated_vertex_const_iterator
isolated_vertices_end(Face_const_handle f)318 isolated_vertices_end(Face_const_handle f) const
319 /*{\Mop returns the past the end iterator of |f|.}*/
320 { return f->iv_end(); }
321
322
323 /*{\Mtext \headerline{Associated Information}\setopdims{2.5cm}{4cm}
324 The type |Mark| is the general attribute of an object. The type
325 |GenPtr| is equal to type |void*|.}*/
326
point(Vertex_const_handle v)327 const Point& point(Vertex_const_handle v) const
328 /*{\Mop returns the embedding of |v|.}*/
329 { return v->point(); }
330
mark(Vertex_const_handle v)331 const Mark& mark(Vertex_const_handle v) const
332 /*{\Mop returns the mark of |v|.}*/
333 { return v->mark(); }
334
mark(Halfedge_const_handle e)335 const Mark& mark(Halfedge_const_handle e) const
336 /*{\Mop returns the mark of |e|.}*/
337 { if (&*e < &*(e->opposite())) return e->mark();
338 else return e->opposite()->mark();
339 } // we store the mark in the container with smaller memory address !
340
mark(Face_const_handle f)341 const Mark& mark(Face_const_handle f) const
342 /*{\Mop returns the mark of |f|.}*/
343 { return f->mark(); }
344
info(Vertex_const_handle v)345 const GenPtr& info(Vertex_const_handle v) const
346 /*{\Mop returns a generic information slot.}*/
347 { return v->info(); }
348
info(Halfedge_const_handle e)349 const GenPtr& info(Halfedge_const_handle e) const
350 /*{\Mop returns a generic information slot.}*/
351 { return e->info(); }
352
info(Face_const_handle f)353 const GenPtr& info(Face_const_handle f) const
354 /*{\Mop returns a generic information slot.}*/
355 { return f->info(); }
356
357
358 /*{\Mtext \headerline{Statistics and Integrity}}*/
359
number_of_vertices()360 Size_type number_of_vertices() const
361 /*{\Mop returns the number of vertices.}*/
362 { return phds->size_of_vertices(); }
363
number_of_halfedges()364 Size_type number_of_halfedges() const
365 /*{\Mop returns the number of halfedges.}*/
366 { return phds->size_of_halfedges(); }
367
number_of_edges()368 Size_type number_of_edges() const
369 /*{\Mop returns the number of halfedge pairs.}*/
370 { return phds->size_of_halfedges()/2; }
371
number_of_faces()372 Size_type number_of_faces() const
373 /*{\Mop returns the number of faces.}*/
374 { return phds->size_of_faces(); }
375
376 Size_type number_of_face_cycles() const;
377 /*{\Mop returns the number of face cycles.}*/
378
379 Size_type number_of_connected_components() const;
380 /*{\Mop calculates the number of connected components of |P|.}*/
381
382 void print_statistics(std::ostream& os = std::cout) const
383 /*{\Mop print the statistics of |P|: the number of vertices, edges, and
384 faces.}*/
385 {
386 os << "Plane Map - Statistics\n";
387 os << "|V| = " << number_of_vertices() << std::endl;
388 os << "|E| = " << number_of_edges()
389 << " (" << 2*number_of_edges() << ")" << std::endl;
390 os << "|F| = " << number_of_faces() << std::endl;
391 os << "|Fcs| = " << number_of_face_cycles() << std::endl << std::endl;
392 }
393
394 void check_integrity_and_topological_planarity(bool faces=true) const;
395 /*{\Mop checks the link structure and the genus of |P|.}*/
396
397 }; // PM_const_decorator
398
399 template <class VH>
PV(VH v)400 std::string PV(VH v)
401 { std::ostringstream os; CGAL::IO::set_pretty_mode(os);
402 if (v != VH()) os << v->point();
403 else os << "nil";
404 return os.str();
405 }
406
407 template <class HH>
PE(HH e)408 std::string PE(HH e)
409 { std::ostringstream os;
410 if (e==HH()) return "nil";
411 os << "[" << PV(e->opposite()->vertex()) << ","
412 << PV(e->vertex()) << " "
413 #ifdef CGAL_I_DO_WANT_TO_USE_GENINFO
414 << e->info()
415 #endif
416 << "]";
417 return os.str();
418 }
419
420 template <typename HDS>
421 void PM_const_decorator<HDS>::
check_integrity_and_topological_planarity(bool faces)422 check_integrity_and_topological_planarity(bool faces) const
423 {
424 CGAL_NEF_TRACEN("check_integrity_and_topological_planarity:");
425 using CGAL::Object_index;
426 Object_index<Vertex_const_iterator>
427 VI(vertices_begin(),vertices_end(),'v');
428 Object_index<Halfedge_const_iterator>
429 EI(halfedges_begin(),halfedges_end(),'e');
430 Object_index<Face_const_iterator>
431 FI(faces_begin(),faces_end(),'f');
432 Vertex_const_handle vit, vend = phds->vertices_end();
433 int iso_vert_num=0;
434 /* check the source links of out edges and count isolated vertices */
435 for (vit = vertices_begin() ; vit != vend; ++vit) {
436 if ( is_isolated(vit) ) {
437 if ( faces )
438 CGAL_assertion_msg( vit->face() != Face_const_handle(),
439 VI(vit).c_str());
440 ++iso_vert_num;
441 } else {
442 CGAL_assertion_msg( vit->halfedge() != Halfedge_const_handle(),
443 VI(vit).c_str());
444 CGAL_assertion_msg( vit->halfedge()->vertex() == vit ,VI(vit).c_str());
445 }
446 }
447
448 /* check the bidirected links and the face pointer init */
449 Halfedge_const_iterator eit, eend = phds->halfedges_end();
450 for (eit = phds->halfedges_begin() ; eit != eend; ++eit) {
451 CGAL_assertion( twin(twin(eit)) == eit );
452 CGAL_assertion( eit->vertex() != Vertex_const_handle() );
453 CGAL_assertion( next(eit) != Halfedge_const_handle() );
454 CGAL_assertion( previous(next(eit)) == eit );
455 CGAL_assertion( target(eit) == source(next(eit)) );
456 CGAL_assertion( previous(eit) != Halfedge_const_handle() );
457 CGAL_assertion( next(previous(eit)) == eit );
458 CGAL_assertion( target(previous(eit)) == source(eit) );
459 if ( !faces ) continue;
460 CGAL_assertion( face(eit) != Face_const_handle() );
461 CGAL_assertion( face(next(eit)) == face(eit) );
462 CGAL_assertion( face(previous(eit)) == face(eit) );
463 }
464
465 bool first=true;
466 int fc_num(0),iv_num(0);
467 Face_const_iterator fit;
468 for (fit = faces_begin(); fit != faces_end(); ++fit) {
469 if (!first && halfedge(fit)!=Halfedge_const_handle()) {
470 CGAL_assertion( face(halfedge(fit))==fit ); ++fc_num;
471 }
472 Hole_const_iterator fcit;
473 for( fcit = holes_begin(fit); fcit != holes_end(fit); ++fcit) {
474 CGAL_assertion( face(fcit)==fit ); ++fc_num;
475 }
476 Isolated_vertex_const_iterator ivit;
477 for(ivit = isolated_vertices_begin(fit);
478 ivit != isolated_vertices_end(fit); ++ivit) {
479 CGAL_assertion( face(ivit)==fit ); ++iv_num;
480 }
481 first=false;
482 }
483
484 std::size_t v_num = number_of_vertices() - iso_vert_num;
485 std::size_t e_num = number_of_edges();
486 std::size_t c_num = number_of_connected_components() - iso_vert_num;
487 std::size_t f_num = number_of_face_cycles() - c_num + 1;
488 CGAL_USE(v_num);
489 CGAL_USE(e_num);
490 CGAL_USE(f_num);
491 CGAL_NEF_TRACEV(fc_num);CGAL_NEF_TRACEV(iv_num);CGAL_NEF_TRACEV(iso_vert_num);
492 CGAL_NEF_TRACEV(v_num);CGAL_NEF_TRACEV(e_num);CGAL_NEF_TRACEV(c_num);CGAL_NEF_TRACEV(f_num);
493 // CGAL_assertion(fc_num == f_num && iv_num == iso_vert_num);
494 /* this means all face cycles and all isolated vertices are
495 indeed referenced from a face */
496 /* every isolated vertex increases the component count
497 one face cycle per component is redundent except one
498 finally check the Euler formula: */
499 CGAL_assertion( v_num - e_num + f_num == 1 + c_num );
500 }
501
502 template <typename HDS>
503 typename PM_const_decorator<HDS>::Size_type
504 PM_const_decorator<HDS>::
number_of_face_cycles()505 number_of_face_cycles() const
506 {
507 Size_type fc_num=0;
508 CGAL::Unique_hash_map<Halfedge_const_handle,bool> visited;
509 // init with bool() == false
510 Halfedge_const_iterator eit = phds->halfedges_begin();
511 Halfedge_const_iterator eend = phds->halfedges_end();
512 for ( ; eit != eend; ++eit) {
513 if (visited[eit]) continue;
514 Halfedge_around_face_const_circulator hfc(eit), hend(hfc);
515 CGAL_For_all(hfc,hend) visited[hfc]=true;
516 ++fc_num;
517 }
518 return fc_num;
519 }
520
521 template <typename HDS>
522 size_t PM_const_decorator<HDS>::
number_of_connected_components()523 number_of_connected_components() const
524 {
525 typedef Vertex_const_iterator vc_handle;
526 typedef Halfedge_around_vertex_const_circulator hvc_circulator;
527 int comp_num=0;
528 CGAL::Unique_hash_map< vc_handle, bool> handled(false);
529 vc_handle vit = vertices_begin(), vend = vertices_end();
530 for ( ; vit != vend; ++vit) {
531 if (handled[vit]) continue;
532 std::list<vc_handle> L;
533 L.push_back(vit); handled[vit]=true;
534 /* we keep the invariant that all nodes which have been stacked
535 are marked handled */
536 while (!L.empty()) {
537 vc_handle v=L.front(); L.pop_front();
538 if ( is_isolated(v) ) continue;
539 hvc_circulator havc(first_out_edge(v)), hend(havc);
540 CGAL_For_all(havc,hend) {
541 if (!handled[target(havc)]) {
542 L.push_back(target(havc)); handled[target(havc)]=true;
543 }
544 }
545 }
546 ++comp_num;
547 }
548 return comp_num;
549 }
550
551 struct KERNELPNT {
552 template <typename PNT>
operatorKERNELPNT553 std::string operator() (const PNT& p) const
554 { std::ostringstream os;
555 os << "(" << CGAL::to_double(p.x()) << ","
556 << CGAL::to_double(p.y()) << ")";
557 return os.str();
558 }
559 };
560
561 template <typename PMCDEC, typename POINTDA>
print_as_leda_graph(std::ostream & os,const PMCDEC & D,const POINTDA & P)562 void print_as_leda_graph(std::ostream& os, const PMCDEC& D,
563 const POINTDA& P)
564 {
565 typedef typename PMCDEC::Vertex_const_iterator
566 Vertex_const_iterator;
567 typedef typename PMCDEC::Halfedge_const_iterator
568 Halfedge_const_iterator;
569 int vn(1), en(1);
570 CGAL::Unique_hash_map<Vertex_const_iterator,int> v_num;
571 CGAL::Unique_hash_map<Halfedge_const_iterator,int> e_num;
572 os << "LEDA.GRAPH\n" << "point\n" << "int\n";
573 os << D.number_of_vertices() << std::endl;
574 Vertex_const_iterator vit;
575 for (vit = D.vertices_begin(); vit != D.vertices_end(); ++vit) {
576 v_num[vit] = vn++;
577 os << "|{(" << P(D.point(vit)) << ")}|\n";
578 typename PMCDEC::Halfedge_around_vertex_const_circulator
579 ecirc(D.first_out_edge(vit)),ecend(ecirc);
580 int l=0;
581 CGAL_For_all(ecirc,ecend) e_num[ecirc]=l++;
582 }
583 os << 2* D.number_of_edges() << std::endl;
584 Halfedge_const_iterator eit;
585 for (eit = D.halfedges_begin(); eit != D.halfedges_end(); ++eit) {
586 e_num[eit] = en++;
587 }
588 for (eit = D.halfedges_begin(); eit != D.halfedges_end(); ++eit) {
589 os << v_num[D.source(eit)] << " "
590 << v_num[D.target(eit)] << " "
591 << e_num[D.twin(eit)] << " ";
592 os << "|{" << e_num[eit] << "}|\n";
593 }
594 os << std::flush;
595 }
596
597
598
599 } //namespace CGAL
600 #endif // CGAL_PM_CONST_DECORATOR_H
601