cgal/Nef_2/noweb/PM_decorator.lw

863 lines
34 KiB
Plaintext

%------------------------------------------------------------------------------
%KILLSTART DISS REP
%LDEL TRACE.*?\)\;
\documentclass[a4paper]{article}
\usepackage{MyLweb}
\input{defs}
\includeversion{ignoreindiss}
\excludeversion{ignore}
\begin{document}
\title{Extending the CGAL HDS}
\author{Michael Seel}
\maketitle
\tableofcontents
\newpage
\section{Realization of plane map data type}
%KILLEND DISS REP
We present some implementation details of our plane map decorator that
provides an abstract interface to a plane map. The abstract interface
of our plane map data type is sufficiently specified in the manual
page. We sketch how we implement this interface by the CGAL halfedge
data structure. We use the new HDS design as described in the design
paper \cite{kettner-polyhedra}. The paper contains also a survey of
classical plane map implementations and a motivation for the HDS
design. The generic HDS collection allows one to choose different
flavors of HDS structures. A user can specify if she uses explicit
vertex or face objects and how the iteration facilities are
implemented. For the topological Nef layer we choose the default
implementation including vertex and face objects. However the offered
design is limited to one single face cycle bounding a face. Our
definition of plane maps requires one to have multiple face cycles and
also trivial face cycles in the form of isolated vertices. We do not
want to bore the reader with the technical details of the
implementation but we describe the extension process from the
functionality of the default HDS design to our plane map data
type. Fortunately, the CGAL HDS allows a user to extend the
functionality by extending the objects (vertices, halfedges,
faces). The types are transported into the container type HDS in a
so-called items class; in our case it is called |HDS_items|. The
possibility of this extension is one advantage of the generic design.
\displayeps{HDS_default}{The default HDS design}{\textwidth}
Figure \figref{HDS_default} presents the default layout of the three
objects. The interface methods map to member variables. A vertex $v$
stores an incident edge $e$ such that |v.halfedge() = e| and
|e.vertex() = v|. A face $f$ stores an edge $e$ in its bounding face
cycle: |f.halfedge() = e| and |e.face() = f|. The additional links of
an edge $e$ create the topological structure of the
graph. |e.opposite()| is used to make the graph bidirected and
|e.next()| and |e.prev()| are used for the circular ordering of edges
in the face cycle of a face.
\displayeps{HDS_extended}{The extended HDS design}{\textwidth}
The extended structure in Figure \figref{HDS_extended} adds the
possibility to assign multiple face cycles as a boundary to a face $f$
to the above structure. We give generic container access by means of
two iterator ranges. The range |[ f.holes_begin()|, |f.holes_end() )|
stores halfedges that can be used as entry points into disjoint face
cycles. Accordingly, the range |[ f.isolated_vertices_begin()|,
|f.isolated_vertices_end() )| maintains a set of vertices in the
interior of $f$. Such vertices $v$ also store their containing face by
|v.face() = f|. Note that our implementation requires that insertion
or deletion operations in the two sets are constant-time
operations. We do not show the details. Note that all three objects
are attributed twice in addition to the topological linkage. All
objects store a mark and a generic slot of type |GenPtr = void*| for
further data association. These two extensions are mandatory for the
Nef structure. The |mark()| slots map to set inclusion flags. The
|info()| slots allow us to associate temporary information required
for the binary overlay of two structures. Finally, vertices carry a
point representing their embedding into the plane. \repdiss{The full
interfaces of the extended objects are presented in the manual pages
on page \pageref{The HDS vertex base class}, \pageref{The HDS halfedge
base class}, and \pageref{The HDS face base class}.}{}
\subsection*{Decorator classes}
\displayeps{HDS_decorators}{The decorator family defining the
interface to the HDS data structure}{7cm}
We interface the HDS via decorator classes that encapsulate a certain
functionality. The classes are depicted in Figure
\figref{HDS_decorators}. We implemented the two main concepts
|PMConstDecorator| and |PMDecorator| on top of the CGAL HDS. The first
gives read-only access to the HDS the second provides manipulation
operations. The concepts carry their interface into the additional
modules |PM_checker|, |PM_io_parser|, |PM_visualizor|. Whenever
geometric kernel operations are needed in the module as, for example,
in the checker, we add a template parameter carrying geometric kernel
methods. The |COLORDA| template parameter in the visualizor module
|PM_visualizor| allows the adaptation of the drawing of plane maps.
We elaborate on some details of the modules but do not show the whole
implementation.
\subsection*{PM\_const\_decorator - the read-only interface}
|PM_const_decorator<>| realizes non-mutable access to plane maps. It
provides interface operations on the objects as presented in our
concepts section on page \pageref{PMConstDecorator}. The sole link to
geometry is the embedding via a point type. All circular structures
are realized via circulators (the variation of iterators as introduced
in CGAL). The only method that carries more involved coding is the
integrity check operation. That operation checks the sanity of the
link structure coding the incidence relations of vertices, edges, and
faces and additionally checks the topological planarity of the
structure by checking that the genus of the plane map is zero. The
integrity check of the topological decorator does the following:
\begin{itemize}\itemsep0ex\topsep-0.5ex\parsep0ex plus 0.0ex minus 1.0ex%
\item all vertices are partitioned into two sets by the
|is_isolated()| predicate. All isolated vertices |v| have face links
where |v| is in the isolated vertices list of |v->face()|. All
non-isolated vertices are bound to adjacency lists by their halfedge
links.
\item for all vertices |v| we check that |source(A(v)) == v|
\item for all edges |e| we check that |twin(twin(e)) == e|
\item we check that the Euler formula is correctly fulfilled. Let
$n_v$ be the number of vertices, $n_e$ be number of edges (= number of
halfedges divided by 2), $n_f$ be the number of faces, $n_{fc}$ be the
number of face cycles, and $n_{cc}$ be the number of connected
components of the map. Then at first we have $n_f = n_{fc} - n_{cc} +
1$ and we check that $n_v - n_e + n_f = 1 + n_{cc}$. Note that we have
to cope with isolated vertices. They are counted in our connected
component number $n_{cc}$ and in $n_v$.
\end{itemize}
See Chapter 8 of the LEDA book for an elaborate treatment of this
check.
\subsection*{PM\_checker - checking geometric properties}
Our checker mainly realizes the integrity checks of the basic
properties of the plane map like that of an order-preserving embedding
or the forward-prefix property of the adjacency lists. We also added a
checker method that examines if a plane map represents a triangulation
of its vertices. The implemented methods are
@c
void check_order_preserving_embedding(Vertex_const_handle v) const;
void check_forward_prefix_condition(Vertex_const_handle v) const;
void check_order_preserving_embedding() const;
void check_is_triangulation() const;
@ The methods check the basic properties that we require from a plane
map. The task to check if our plane map actually is a triangulation of
its vertices follows the ideas as presented in \cite{checking-cgta99}
and the LEDA book.
\subsection*{PM\_decorator - manipulating the plane map}
|PM_decorator<>| gives mutable access to a plane map. Apart from
standard operations the interface also provides operations that are
very specially designed for the updates needed in our sweep framework
or in the simplification phase of our binary operations. Some
operations allow changing the incidence of plane map objects only
partially e.g. create an edge that is only linked to a vertex at its
source. With these operations one has to be careful not to spoil the
plane map structure. The advantage is that we do not need superflous
allocations of objects that are only needed temporarily.
The implementation of most of the operations is straight forward. The
only operation that should be mentioned is the clone operation for
plane maps. As the generic HDS container does not know the layout of
the objects that it maintains, a copy construction is hard to realize
for the general case. In the rare case where we actually need to copy
a plane map, we use the methods:
@c
void clone(const HDS& H);
template <typename LINKDA>
void clone_skeleton(const HDS& H, const LINKDA& L)
@ Both methods basically work in two stages. Let $H'$ be the target
copy of $H$. First each object $o$ in $H$ is cloned into an object
$o'$ in $H'$ whose links still point to objects in $H$. We store the
correspondance of $o$ to $o'$ in a map $M(o) = o'$. Then in the second
stage we iterate over all objects $o'$ in $H'$ and replace the links
to the objects in $H$ by the corresponding objects in $H'$ via the
map. The result is an isomorphic structure. Note that due to the fact
that the |prev|-|next| links of the halfedges also code the embedding,
this isomorphy is also topological and not only combinatorial
\cite{diestel97}. Of course the geometric embedding of the vertices
and the attributed marks are just transferred. The second cloning
operation just extracts a topologically isomorphic 1-skeleton from a
full-fledged plane map. In that operation we also provide access to
the newly created objects by an additional data accessor $L$. The
|LINKDA| concept requires the methods:
@c
struct LINKDA {
void operator()(Vertex_handle vn, Vertex_const_handle vo) const;
void operator()(Halfedge_handle hn, Halfedge_const_handle ho) const;
}
@ where |vn|, |hn| are the cloned objects in $H'$ and |vo|, |ho| are
the original objects of $H$. $L$ can now be used to get a hand on the
cloning process at the object level. The method is used to obtain an
isomorphic graph structure that can be used for further subdivision
(e.g. point location in constrained triangulations). We leave out the
details, as its design is mainly determined by the design of the CGAL
HDS.
\subsection*{PM\_io\_parser - stream input and output}
Input and output are mainly triggered by a decorator that has the
control over the I/O format and does some basic parsing when reading
input. The class template |PM_io_parser<PMDEC>| has two constructors
and two corresponding actions on the streams obtained on construction:
@c
PM_io_parser(std::istream& is, Plane_map& H);
void read();
PM_io_parser(std::ostream& os, const Plane_map& H);
void print() const;
@ The template parameter refers to the concept |PMDecorator|. A
decorator object decorating |H| is used to construct the plane map |H|
when reading from the input stream, or to explore the structure when
printing to the output stream. We omit the implementation details.
We only present the I/O format that is similar to that used in LEDA
for general graphs. There is a header and then three sections storing
the objects vertices, halfedges, faces:
@c
Plane_map_2
vertices n1
halfedges n2
faces n3
0 { isolated incident_object, mark, point }
...
n1-1 { isolated incident_object, mark, point }
0 { opposite, prev, next, vertex, face, mark }
...
n2-1 { opposite, prev, next, vertex, face, mark }
0 { halfedge, fclist, ivlist, mark }
...
n3-1 { halfedge, fclist, ivlist, mark }
@ there are $n_1$ lines for vertices, $n_2$ lines for halfedges, and
$n_3$ lines for faces. All objects are indexed by non-negative
integers. Vertex lines contain a boolean marker |isolated| followed
by the index of an incident object (a face if |isolated| is true,
otherwise the first halfedge of the adjacency list), the attribute and
the embedding. Halfedge lines store the link structure (again by
indices representing the objects): the |opposite| (also called twin or
reversal) halfedge, the |prev|ious and |next| halfedge of its face
cycle, the incident |vertex| and the incident |face|, and the
attributed |mark|. The face lines have no fixed length as the number
of face cycles and isolated vertices is not bounded. Both lists
|fclist| (for face cycles) and |ivlist| (for isolated vertices) are
white-space-separated lists of numbers. Their elements are the indices
of halfedges from the corresponding face cycle or the indices of the
isolated vertices in the interior of the faces respectively. The
|halfedge| is the index of a halfedge of the outer face cycle of the
face and the |mark| is again the attribute of the face. Note that as
our index range starts at $0$, we code undefined references by $-1$.
I/O and cloning processes bear a strong similarity. In both processes
one creates isomorphic representations of pointer structures. In case
of output, the representation of typed pointers (handles) is a unique
numbering of all objects that can be translated back during an input
process.
\subsection*{PM\_visualizor - drawing plane maps in a window}
We offer a decorator drawing a plane map into a CGAL window stream,
which is basically a LEDA window offering stream operations for all
affine kernel objects of the CGAL geometry kernels. The class template
|PM_visualizor<PMCDEC,GEOM,COLORDA>| requires models of the three
template parameters for instantiation. The first two can be
instantiated by |PM_const_decorator<>| and any geometry kernel that is
a model of the concept |AffineGeometryTraits_2|. The third parameter
assigns colors and sizes to the objects of the plane map depending on
their attributes by the following class concept:
@c
struct COLORDA {
CGAL::Color color(Vertex_const_handle, const Mark& m) const;
CGAL::Color color(Halfedge_const_handle, const Mark& m) const;
CGAL::Color color(Face_const_handle, const Mark& m) const;
int width(Vertex_const_handle, const Mark& m) const;
int width(Halfedge_const_handle, const Mark& m) const;
};
@ On construction the visualizor obtains a window stream |W|, a
decorator |D|, a geometry kernel |K|, and a color data accessor
|C|. The plane map referenced by |D| is drawn in the window |W| with
the properties as specified by |C|.
@c
PM_visualizor(CGAL::Window_stream& W, const PMCDEC& D,
const GEOM& K, const COLORDA& C);
@ The class offers drawing by object or drawing of the
full structure by the methods:
@c
void draw(Vertex_const_handle v) const
void draw(Halfedge_const_handle e) const
void draw(Face_const_handle f) const
void draw_map() const
@ We do not show their implementation here. For the drawing of the
faces we use the techniques that are used by LEDA windows to draw
polygons.
\begin{ignoreindiss}
\section{Extending the HDS}
We extend the basic HDS design by multiple face cycles and isolated
vertices.
\subsection{Extended vertices}
To summarize the vertex design compared to the default HDS:
\begin{description}
\item[topology and combinatorics] a vertex has extended incidence
operations. Depending on the predicate |is_isolated()| a vertex has
either a link to an incident face via |[set_]face()| or it has a link to
an incident halfedge via |[set_]halfedge()|.
\item[geometry] an object of type |Point| for its embedding.
\item[attribute] a mark of type |Mark| and an information slot
stored in a |GenPtr|. The latter can be used by the |geninfo| class.
\end{description}
Internal implementation invariants:
\begin{itemize}
\item |is_isolated()| $\Leftrightarrow$ |ivit()!=nil_|
an isolated vertex is stored in some faces isolated vertices list
\item |is_isolated()| $\Leftrightarrow$ |halfedge()==Halfedge_handle()|
an isolated vertex has no incident halfedge.
\end{itemize}
<<epm vertices>>=
/*{\Moptions outfile=epm_vertex.man }*/
/*{\Moptions constref=yes}*/
/*{\Moptions print_title=yes }*/
/*{\Moptions section=subsection}*/
/*{\Manpage{Vertex}{}{The HDS vertex base class}{v}}*/
template <typename Refs, typename Traits>
class Vertex_wrapper { public:
typedef typename Traits::Point Point;
class Vertex {
public:
typedef Refs HalfedgeDS;
typedef Vertex Base;
typedef CGAL::Tag_true Supports_vertex_halfedge;
typedef CGAL::Tag_true Supports_vertex_point;
typedef typename Refs::Vertex_handle Vertex_handle;
typedef typename Refs::Vertex_const_handle Vertex_const_handle;
typedef typename Refs::Halfedge_handle Halfedge_handle;
typedef typename Refs::Halfedge_const_handle Halfedge_const_handle;
typedef typename Refs::Face_handle Face_handle;
typedef typename Refs::Face_const_handle Face_const_handle;
typedef typename Refs::Halfedge Halfedge;
typedef typename Refs::Face Face;
typedef void* GenPtr;
/*{\Mtypes 3}*/
typedef typename Traits::Point Point;
/*{\Mtypemember geometric embedding}*/
typedef typename Traits::Mark Mark;
/*{\Mtypemember information}*/
typedef typename std::list<Vertex_handle>::iterator iv_iterator;
private:
Halfedge_handle _h;
Face_handle _f;
Point _p;
iv_iterator _ivit;
Mark _m;
GenPtr _i;
public:
/*{\Mcreation 3}*/
Vertex() :
_h(),_f(),_ivit(nil_),_m(),_i((GenPtr)0xABCD) {}
/*{\Mcreate constructs an uninitialized vertex concerning embedding
and mark. All links are initialized by their default value.}*/
Vertex(const Point& p) :
_h(),_f(),_p(p),_ivit(nil_),_m(),_i((GenPtr)0xABCD) {}
/*{\Mcreate constructs a vertex with embedding |p| and mark |m|.
All links are initialized by their default value.}*/
/*{\Moperations 3 4}*/
bool is_isolated() const
/*{\Mop returns true iff |\Mvar| is isolated, else false.}*/
{ return _h == Halfedge_handle(); }
Halfedge_handle halfedge() { return _h; }
/*{\Mop returns an incident halfedge. \precond |!is_isolated()|.}*/
Halfedge_const_handle halfedge() const { return _h; }
void set_halfedge(Halfedge_handle h) { _h=h; }
/*{\Mop makes |h| the entry point into the adjacency cycle of
|\Mvar|.}*/
Face_handle face() { return _f; }
/*{\Mop returns the incident face if |is_isolated()|.}*/
Face_const_handle face() const { return _f; }
void set_face(Face_handle f) { _f=f; }
/*{\Mop makes |f| the incident face of |\Mvar|.}*/
Point& point() { return _p; }
/*{\Mop returns the embedding point of |\Mvar|.}*/
const Point& point() const { return _p; }
Mark& mark() { return _m; }
/*{\Mop returns the mark of |\Mvar|.}*/
const Mark& mark() const { return _m; }
GenPtr& info() { return _i; }
/*{\Mop returns a generic information slot of |\Mvar|.}*/
const GenPtr& info() const { return _i; }
iv_iterator ivit() const { return _ivit; }
void set_ivit(iv_iterator it) { _ivit = it; }
static iv_iterator nil_;
/* stl iterators have default construction but are only equal
comparable when copy constructed, what a mess in the specification */
LEDA_MEMORY(Vertex)
};
};
@ \subsection{Extended faces}
To summarize the vertex design compared to the default concept:
\begin{description}
\item[topology and combinatorics] a face has extended incidence operations.
A face stores multiple bounding face cycles in a list |FC| of halfedges
serving as entry points into the face cycles. Additionally a face can
store isolated vertices contained in its interior in a list |IV|.
\item[geometry] no explicit geometric information. The embedding of its
bounding structure is obtained via the multiple non-trivial face
cycles stored in the |FC| list and the multiple contained isolated
vertices stored in the |IV| list.
\item[attribute] a mark of type |Mark| and a flexible usable information
slot stored via a |GenPtr|. The latter can be used by the |geninfo| class.
\end{description}
Internal implementation invariants:
\begin{itemize}
\item the halfedge |FC.front()| refers to the outer face cycle of the
face, all others are hole cycles. (this does not hold for our outer
face which has no outer face cycle)
\item all halfedges |e| in |FC| keep iterator links to their item in |FC|
via |e->[set_]fcit()|.
\item all vertices |v| in |IV| keep iterator links to their item in |IV|
via |v->[set_]ivit()|.
\end{itemize}
<<epm faces>>=
/*{\Moptions outfile=epm_face.man}*/
/*{\Moptions constref=yes}*/
/*{\Moptions print_title=yes }*/
/*{\Moptions section=subsection}*/
/*{\Manpage{Face}{}{The HDS face base class}{f}}*/
template <typename Refs, typename Traits>
class Face_wrapper { public:
class Face {
public:
typedef CGAL::Tag_true Supports_face_halfedge;
typedef Refs HalfedgeDS;
typedef Face Base;
typedef typename Refs::Vertex_handle Vertex_handle;
typedef typename Refs::Vertex_const_handle Vertex_const_handle;
typedef typename Refs::Halfedge_handle Halfedge_handle;
typedef typename Refs::Halfedge_const_handle Halfedge_const_handle;
typedef typename Refs::Face_handle Face_handle;
typedef typename Refs::Face_const_handle Face_const_handle;
typedef typename Refs::Vertex Vertex;
typedef typename Refs::Halfedge Halfedge;
typedef void* GenPtr;
/*{\Mtypes 3}*/
typedef typename Traits::Mark Mark;
/*{\Mtypemember mark information}*/
class Hole_iterator
/*{\Mtypemember iterator for face cycles. Fits the concept
|Halfedge_handle|.}*/
: public std::list<Halfedge_handle>::iterator
{ typedef typename std::list<Halfedge_handle>::iterator Ibase;
public:
Hole_iterator() : Ibase() {}
Hole_iterator(const Ibase& b) : Ibase(b) {}
Hole_iterator(const Hole_iterator& i) : Ibase(i) {}
operator Halfedge_handle() const { return Ibase::operator*(); }
Halfedge& operator*() { return *(Ibase::operator*()); }
Halfedge_handle operator->() { return Ibase::operator*(); }
};
class Hole_const_iterator :
public std::list<Halfedge_handle>::const_iterator
{ typedef typename std::list<Halfedge_handle>::const_iterator Ibase;
public:
Hole_const_iterator() : Ibase() {}
Hole_const_iterator(const Ibase& b) : Ibase(b) {}
Hole_const_iterator(const Hole_const_iterator& i) : Ibase(i) {}
operator Halfedge_const_handle() const { return Ibase::operator*(); }
const Halfedge& operator*() { return *(Ibase::operator*()); }
Halfedge_const_handle operator->() { return Ibase::operator*(); }
};
class Isolated_vertex_iterator
/*{\Mtypemember iterator for isolated vertices. Fits the concept
|Vertex_handle|.}*/
: public std::list<Vertex_handle>::iterator
{ typedef typename std::list<Vertex_handle>::iterator Ibase;
public:
Isolated_vertex_iterator() : Ibase() {}
Isolated_vertex_iterator(const Ibase& b) : Ibase(b) {}
Isolated_vertex_iterator(const Isolated_vertex_iterator& i)
: Ibase(i) {}
operator Vertex_handle() const { return Ibase::operator*(); }
Vertex& operator*() { return *(Ibase::operator*()); }
Vertex_handle operator->() { return Ibase::operator*(); }
};
class Isolated_vertex_const_iterator
: public std::list<Vertex_handle>::const_iterator
{ typedef typename std::list<Vertex_handle>::const_iterator Ibase;
public:
Isolated_vertex_const_iterator() : Ibase() {}
Isolated_vertex_const_iterator(const Ibase& b) : Ibase(b) {}
Isolated_vertex_const_iterator(
const Isolated_vertex_const_iterator& i) : Ibase(i) {}
operator Vertex_const_handle() const { return Ibase::operator*(); }
const Vertex& operator*() { return *(Ibase::operator*()); }
Vertex_const_handle operator->() { return Ibase::operator*(); }
};
/*{\Mtext |Hole_const_iterator| and |Isolated_vertex_const_iterator|
are the non mutable versions.}*/
private:
Halfedge_handle _e;
std::list<Halfedge_handle> FC;
std::list<Vertex_handle> IV;
Mark _m;
GenPtr _i;
public:
/*{\Mcreation 4}*/
Face() : _e(),_m(),_i((GenPtr)0xABCD) {}
/*{\Mcreate constructs an uninitialized face with undefined mark,
empty face cycle list, and empty isolated vertices list.}*/
~Face() { FC.clear(); IV.clear(); }
/*{\Moperations 2.5 3}*/
void store_fc(Halfedge_handle h)
/*{\Mop stores halfedge |h| as an entry into a face cycle of |\Mvar|.
Postcondition: |h->is_hole_entry()|.}*/
{ FC.push_back(h); h->set_fcit(--FC.end());
CGAL_assertion(h->is_hole_entry()); }
void remove_fc(Halfedge_handle h)
/*{\Mop removes halfedge |h| as an entry into a face cycle of |\Mvar|.
\precond |h->is_hole_entry()| and |h| is stored in the
face cycle list of |\Mvar|.
Postcondition: |!h->is_hole_entry()|.}*/
{ CGAL_assertion(h->is_hole_entry());
FC.erase(h->fcit()); h->set_fcit(Halfedge::nil_); }
void store_iv(Vertex_handle v)
/*{\Mop stores vertex |v| as an isolated vertex of |\Mvar|.}*/
{ IV.push_back(v); v->set_ivit(--IV.end()); }
void remove_iv(Vertex_handle v)
/*{\Mop removes vertex |v| as an isolated vertex of |\Mvar|.
\precond |v->is_isolated()| and |v| is stored in the
isolated vertices list of |\Mvar|.
Postcondition: |!v->is_isolated()|.}*/
{ CGAL_assertion(v->is_isolated());
IV.erase(v->ivit()); v->set_ivit(Vertex::nil_); }
/*{\Mtext\setopdims{4cm}{0cm}}*/
Hole_iterator fc_begin() { return FC.begin(); }
/*{\Mop}*/
Hole_iterator fc_end() { return FC.end(); }
/*{\Mop the iterator range |[fc_begin(),fc_end())| spans the set of
interior face cycles.}*/
Isolated_vertex_iterator iv_begin() { return IV.begin(); }
/*{\Mop}*/
Isolated_vertex_iterator iv_end() { return IV.end(); }
/*{\Mop the iterator range |[iv_begin(),iv_end())| spans the set of
isolated vertices.}*/
void clear_all_entries()
{ Hole_iterator hit;
for (hit = fc_begin(); hit!=fc_end(); ++hit)
hit->set_fcit(Halfedge::nil_);
Isolated_vertex_iterator vit;
for (vit = iv_begin(); vit!=iv_end(); ++vit)
vit->set_ivit(Vertex::nil_);
FC.clear(); IV.clear(); }
/*{\Mtext There are the same iterator ranges defined for the const
iterators |Hole_const_iterator|, |Isolated_vertex_const_iterator|.
\restoreopdims}*/
Hole_const_iterator fc_begin() const { return FC.begin(); }
Hole_const_iterator fc_end() const { return FC.end(); }
Isolated_vertex_const_iterator iv_begin() const { return IV.begin(); }
Isolated_vertex_const_iterator iv_end() const { return IV.end(); }
void set_halfedge(Halfedge_handle h) { _e = h; }
/*{\Mop makes |h| the entry edge into the outer face cycle.}*/
Halfedge_handle halfedge() { return _e; }
/*{\Mop returns a halfedge in the outer face cycle.}*/
Halfedge_const_handle halfedge() const { return _e; }
Mark& mark() { return _m; }
/*{\Mop returns the mark of |\Mvar|.}*/
const Mark& mark() const { return _m; }
GenPtr& info() { return _i; }
/*{\Mop returns a generic information slot of |\Mvar|.}*/
const GenPtr& info() const { return _i; }
LEDA_MEMORY(Face)
};
};
@ \subsection{Extended Halfedges}
Halfedge objects extend the default concepts:
\begin{description}
\item[topology and combinatorics] as in the default concept
|[set_]next|, |[set_]prev|, |[set_]vertex|,|[set_]face|
\item[geometry] indirect via embedding of vertices.
\item[attribute] a mark of type |Mark| and a flexible usable information
slot stored via a |GenPtr|. The latter can be used by the |geninfo| class.
\end{description}
Internal implementation invariants:
\begin{itemize}
\item |is_hole_entry()| $\Leftrightarrow$ |fcit()!=nil_|
the iterator link marks its role as an entry point into the face cycle of
the incident face |face()|.
\end{itemize}
<<halfedge base>>=
template <typename Refs >
struct Halfedge__base {
typedef typename Refs::Halfedge_handle Halfedge_handle;
typedef typename Refs::Halfedge_const_handle Halfedge_const_handle;
protected:
Halfedge_handle opp;
public:
Halfedge_handle opposite() { return opp; }
Halfedge_const_handle opposite() const { return opp; }
void set_opposite(Halfedge_handle h) { opp = h; }
};
<<epm halfedges>>=
/*{\Moptions outfile=epm_halfedge.man}*/
/*{\Moptions constref=yes}*/
/*{\Moptions print_title=yes }*/
/*{\Moptions section=subsection}*/
/*{\Manpage{Halfedge}{}{The HDS halfedge base class}{e}}*/
template <typename Refs, typename Traits>
class Halfedge_wrapper { public:
struct Halfedge {
public:
typedef Refs HalfedgeDS;
typedef Halfedge Base;
typedef Halfedge Base_base;
typedef CGAL::Tag_true Supports_halfedge_prev;
typedef CGAL::Tag_true Supports_halfedge_vertex;
typedef CGAL::Tag_true Supports_halfedge_face;
typedef typename Refs::Vertex_handle Vertex_handle;
typedef typename Refs::Vertex_const_handle Vertex_const_handle;
typedef typename Refs::Halfedge_handle Halfedge_handle;
typedef typename Refs::Halfedge_const_handle Halfedge_const_handle;
typedef typename Refs::Face_handle Face_handle;
typedef typename Refs::Face_const_handle Face_const_handle;
typedef typename Refs::Vertex Vertex;
typedef typename Refs::Face Face;
typedef void* GenPtr;
typedef typename std::list<Halfedge_handle>::iterator fc_iterator;
/*{\Mtypes 3}*/
typedef typename Traits::Mark Mark;
/*{\Mtypemember information}*/
protected:
Halfedge_handle opp, prv, nxt;
Vertex_handle _v;
Face_handle _f;
fc_iterator _fcit;
Mark _m;
GenPtr _i;
public:
/*{\Mcreation 3}*/
Halfedge() :
opp(),prv(),nxt(),_v(),_f(),_fcit(nil_),_m(),_i((GenPtr)0xABCD) {}
/*{\Mcreate constructs an uninitialized halfedge concerning embedding
and mark. All links are initialized by their default value.}*/
/*{\Moperations 3 4}*/
Halfedge_handle opposite() { return opp; }
/*{\Mop returns the twin of |\Mvar|.}*/
Halfedge_const_handle opposite() const { return opp; }
void set_opposite(Halfedge_handle h) { opp = h; }
/*{\Mop makes |h| the twin of |\Mvar|.}*/
Halfedge_handle prev() { return prv; }
/*{\Mop returns the previous edge of the face cycle of |\Mvar|.}*/
Halfedge_const_handle prev() const { return prv; }
void set_prev(Halfedge_handle h) { prv = h; }
/*{\Mop makes |h| the previous edge in the face cycle of |\Mvar|.}*/
Halfedge_handle next() { return nxt; }
/*{\Mop returns the next edge of the face cycle of |\Mvar|.}*/
Halfedge_const_handle next() const { return nxt; }
void set_next(Halfedge_handle h) { nxt = h; }
/*{\Mop makes |h| the next edge in the face cycle of |\Mvar|.}*/
Vertex_handle vertex() { return _v; }
/*{\Mop returns the vertex incident to the halfedge |\Mvar|.}*/
Vertex_const_handle vertex() const { return _v; }
void set_vertex(Vertex_handle v) { _v = v; }
/*{\Mop makes |v| the vertex incident to |\Mvar|.}*/
Face_handle face() { return _f; }
/*{\Mop returns the face incident to the halfedge |\Mvar|.}*/
Face_const_handle face() const { return _f; }
void set_face(Face_handle f) { _f = f; }
/*{\Mop makes |f| the face incident to |\Mvar|.}*/
bool is_border() const { return _f == Face_handle(); }
Mark& mark() { return _m; }
/*{\Mop returns the mark of |\Mvar|.}*/
const Mark& mark() const { return _m; }
GenPtr& info() { return _i; }
/*{\Mop returns a generic information slot of |\Mvar|.}*/
const GenPtr& info() const { return _i; }
fc_iterator fcit() const { return _fcit; }
void set_fcit(fc_iterator it) { _fcit=it; }
bool is_hole_entry() const
/*{\Mop returns true iff |\Mvar| is entry point into a hole face
cycle of |\Mvar.face()|.}*/
{ return _fcit != nil_; }
static fc_iterator nil_;
/* stl iterators have default construction but are only equal comparable
when copy constructed, what a mess in the specification */
LEDA_MEMORY(Halfedge)
};
};
@ The file wrapper:
<<HDS_items.h>>=
<<CGAL Header>>
#ifndef CGAL_HDS_ITEMS_H
#define CGAL_HDS_ITEMS_H
#include <CGAL/basic.h>
#include <CGAL/tags.h>
#include <list>
<<halfedge base>>
#ifndef CGAL_USE_LEDA
#define LEDA_MEMORY(t)
#endif
struct HDS_items {
<<epm vertices>>
<<epm halfedges>>
<<epm faces>>
}; // HDS_items
template <typename R,class T>
typename HDS_items::Vertex_wrapper<R,T>::Vertex::iv_iterator
HDS_items::Vertex_wrapper<R,T>::Vertex::nil_;
template <typename R,class T>
typename HDS_items::Halfedge_wrapper<R,T>::Halfedge::fc_iterator
HDS_items::Halfedge_wrapper<R,T>::Halfedge::nil_;
#endif // CGAL_HDS_ITEMS_H
@ \begin{ignore}
<<CGAL Header>>=
// ============================================================================
//
// Copyright (c) 1997-2000 The CGAL Consortium
//
// This software and related documentation is part of an INTERNAL release
// of the Computational Geometry Algorithms Library (CGAL). It is not
// intended for general use.
//
// ----------------------------------------------------------------------------
//
// release : $CGAL_Revision$
// release_date : $CGAL_Date$
//
// file : include/CGAL/Nef_2/HDS_items.h
// package : Nef_2
// chapter : Nef Polyhedra
//
// source : nef_2d/PM_decorator.lw
// revision : $Id$
// revision_date : $Date$
//
// author(s) : Michael Seel <seel@mpi-sb.mpg.de>
// maintainer : Michael Seel <seel@mpi-sb.mpg.de>
// coordinator : Michael Seel <seel@mpi-sb.mpg.de>
//
// implementation: Extended item classes
// ============================================================================
@ \end{ignore}
\end{ignoreindiss}
%KILLSTART DISS
\newpage
\section{Object Concepts}
\input manpages/epm_vertex.man
\input manpages/epm_halfedge.man
\input manpages/epm_face.man
%KILLSTART REP
\section{Appendix}
\input manpages/PMConstDecorator.man
\input manpages/PMDecorator.man
\input manpages/PM_checker.man
\input manpages/PM_io_parser.man
\input manpages/PM_visualizor.man
\bibliographystyle{alpha}
\bibliography{general,geo_mod,comp_geo}
\end{document}
%KILLEND DISS REP