mirror of https://github.com/CGAL/cgal
863 lines
34 KiB
Plaintext
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
|