%------------------------------------------------------------------------------ %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 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| 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| 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} <>= /*{\Moptions outfile=epm_vertex.man }*/ /*{\Moptions constref=yes}*/ /*{\Moptions print_title=yes }*/ /*{\Moptions section=subsection}*/ /*{\Manpage{Vertex}{}{The HDS vertex base class}{v}}*/ template 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::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} <>= /*{\Moptions outfile=epm_face.man}*/ /*{\Moptions constref=yes}*/ /*{\Moptions print_title=yes }*/ /*{\Moptions section=subsection}*/ /*{\Manpage{Face}{}{The HDS face base class}{f}}*/ template 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::iterator { typedef typename std::list::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::const_iterator { typedef typename std::list::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::iterator { typedef typename std::list::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::const_iterator { typedef typename std::list::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 FC; std::list 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} <>= template 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; } }; <>= /*{\Moptions outfile=epm_halfedge.man}*/ /*{\Moptions constref=yes}*/ /*{\Moptions print_title=yes }*/ /*{\Moptions section=subsection}*/ /*{\Manpage{Halfedge}{}{The HDS halfedge base class}{e}}*/ template 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::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: <>= <> #ifndef CGAL_HDS_ITEMS_H #define CGAL_HDS_ITEMS_H #include #include #include <> #ifndef CGAL_USE_LEDA #define LEDA_MEMORY(t) #endif struct HDS_items { <> <> <> }; // HDS_items template typename HDS_items::Vertex_wrapper::Vertex::iv_iterator HDS_items::Vertex_wrapper::Vertex::nil_; template typename HDS_items::Halfedge_wrapper::Halfedge::fc_iterator HDS_items::Halfedge_wrapper::Halfedge::nil_; #endif // CGAL_HDS_ITEMS_H @ \begin{ignore} <>= // ============================================================================ // // 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 // maintainer : Michael Seel // coordinator : Michael Seel // // 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