The Planar_map_2<Dcel,Traits> class (Chapter ) is derived from the Topological_map<Dcel> class and it describes an embedding of a topological map in the Euclidean plane. This chapter and Chapter describe the Topological_map class and the Planar_map class respectively. These classes supply the ability to maintain subdivisions of the plane induced by collections of curves. In this chapter we introduce the topological map. In this section we briefly review the concepts underlying the data structures described in the following sections as well as the functionality of Topological_map in a nutshell.
Figure: A face, an edge, and a vertex
Topological Map, Vertex, Edge, Face: A topological map is a graph that consists of vertices V, edges E, faces F and an incidence relation on them. Each edge is represented by two halfedges with opposite orientations. A face of the topological map is defined by the ordered circular sequences (inner and outer) of halfedges along its boundary.
Incidence: If a vertex is an endpoint of an edge , then we say that and are incident to each other. Similarly, a face and an edge on its boundary are incident, and a face and a vertex on its boundary are incident (including edges and vertices that are not connected to the outer boundary - see below).
Halfedge, Twin, Source, Target: We consider each edge to be two-sided, representing it by two directed halfedges and (In other packages the twin halfedge is called ). A halfedge is an ordered pair of its endpoints, and it is directed from , the source, to , the target (there is no need to store both in each halfedge since ). We consider each halfedge to lie on the boundary of a single face.
Connected Component of the Boundary (CCB): Each connected component of the boundary of a face is defined by a circular list of halfedges. For a face of a topological map, we call each connected component of the boundary of a CCB. A bounded face has a unique CCB that is defined to be its outer CCB. An unbounded face does not have an outer boundary. In the topological map we have one unbounded face. Except for the outer CCB, any other connected component of the boundary of is called a hole (or inner CCB), every face can have none or several holes. We say that the holes are contained inside the face.
Edges around a Vertex : Every maximal set of halfedges that share the same target can be viewed as a circular list of halfedges ordered around their target vertex. It should be noted that the orientation of the edges around a vertex is opposite to that of the halfedges around a face, i.e., if edge succeeds edge in the order given around vertex , then succeeds in the order given around the incident face . Unlike the convention we adopt for Planar_map in Chapter where the halfedges are oriented counterclockwise around a face and clockwise around a vertex, in the topological map the users are free to choose any other convention.
Figure: Source and target vertices, and twin halfedges
Doubly Connected Edge List (DCEL): For a topological map, its DCEL representation consists of a connected list of halfedges for every CCB of every face in the subdivision, with additional incidence information that enables us to traverse the subdivision. For each halfedge the DCEL stores a pointer to its twin halfedge and to the next halfedge around its incident face (see Figure ). In addition, for each halfedge the DCEL stores a pointer to the incident face and the target vertex. For each face the DCEL stores a pointer to a halfedge representing its outer-CCB and an iterator over pointers to halfedges representing its inner-CCBs (traversing over a CCB is thus done with repetitive calls to the next halfedge pointer). For each vertex the DCEL stores a pointer to an incident halfedge. For more information about the DCEL representation see [dBvKOS97] and Chapter on Halfedge_data_structure. The DCEL is a low-level container class that stores the objects. The topological map layer adds high-level functions and protection of combinatorial validity. Iterators, handles and circulators are also introduced in this layer (pointers are no longer visible in this layer).
In the following specifications, we implement the subdivision by a DCEL.
The class Topological_map<Dcel> supplies the ability to maintain a topological map. The user can insert edges in various ways and then split, merge or remove them as well as move holes from one face to another. The vertices, edges and faces can be traversed in a linear way or any other fashion mentioned above. For a full reference of the class (i.e its associated types, its operations, etc.) read the Topological_map Reference Pages.
The function is_valid() checks the validity of the topological map.
// file: examples/Topological_map/example1.C #include <CGAL/basic.h> #include <iostream> #include <CGAL/Topological_map_bases.h> #include <CGAL/Pm_default_dcel.h> #include <CGAL/Topological_map.h> typedef CGAL::Pm_dcel<CGAL::Tpm_vertex_base, CGAL::Tpm_halfedge_base, CGAL::Tpm_face_base> Dcel; typedef CGAL::Topological_map<Dcel> Tpm; typedef Tpm::Halfedge_handle Halfedge_handle; typedef Tpm::Vertex_handle Vertex_handle; typedef Tpm::Face_handle Face_handle; int main() { Tpm t; Face_handle uf = t.unbounded_face(); std::cout << "Inserting edge e1 in unbounded face interior ... " ; Halfedge_handle e1 = t.insert_in_face_interior(uf); CGAL_assertion(t.is_valid()); std::cout << "map is valid!" << std::endl; std::cout << "Inserting edge e2 from target vertex of e1 ... " ; Halfedge_handle e2 = t.insert_from_vertex(e1); CGAL_assertion(t.is_valid()); std::cout << "map is valid!" << std::endl; std::cout << "Inserting edge e3 between target vertices of e2 and twin of " << "e1 ... "; t.insert_at_vertices(e2,e1->twin()); CGAL_assertion(t.is_valid()); std::cout << "map is valid!" << std::endl; return 0; }
The output of the program is:
inserting edge e1 in face interior ...map is valid. inserting edge e2 from target vertex of e1 ...map is valid. inserting edge e3 between target vertices of e2 and e1->twin() ...map is valid.
// file: examples/Topological_map/example2.C #include <CGAL/basic.h> #include <iostream> #include <CGAL/Topological_map_bases.h> #include <CGAL/Pm_default_dcel.h> #include <CGAL/Topological_map.h> class Face_with_info : public CGAL::Tpm_face_base { int inf; public: Face_with_info() : CGAL::Tpm_face_base(), inf(0) {} int info() { return inf; } void set_info(int i) { inf = i; } }; typedef CGAL::Pm_dcel<CGAL::Tpm_vertex_base, CGAL::Tpm_halfedge_base, Face_with_info > Dcel; typedef CGAL::Topological_map<Dcel> Tpm; typedef Tpm::Halfedge_handle Halfedge_handle; typedef Tpm::Vertex_handle Vertex_handle; typedef Tpm::Face_handle Face_handle; int main() { Tpm t; Face_handle uf = t.unbounded_face(); Halfedge_handle e1 = t.insert_in_face_interior(uf); CGAL_assertion(t.is_valid()); std::cout << "Edge e1 inserted in unbounded face interior" << std::endl; Halfedge_handle e2 = t.insert_from_vertex(e1); CGAL_assertion(t.is_valid()); std::cout << "Edge e2 inserted from target vertex of e1" << std::endl; Halfedge_handle e3 = t.insert_at_vertices(e2, e1->twin()); CGAL_assertion(t.is_valid()); std::cout << "Edge e3 inserted between target vertices of e2 and " << "twin of e1" << std::endl; std::cout << std::endl <<"Setting info of the new face to 10" << std::endl; Face_handle nf = e3->face(); nf->set_info(10); std::cout << "Unbounded face info = " << uf->info() << std::endl; std::cout << "New face info = " << nf->info() << std::endl; return 0; }
The output of the program is:
inserting e1 in face interior... inserting e2 from vertex... inserting e3 between vertices of e2 and e1->twin()... setting info of the new face to 10... unbounded face info = 0 new face info = 10