Ok for CMap doc

This commit is contained in:
Guillaume Damiand 2016-09-30 13:37:34 -04:00
parent 4921361cbe
commit da7ca2e22a
9 changed files with 140 additions and 103 deletions

View File

@ -9,7 +9,7 @@ The class `Cell_attribute` represents an attribute containing (or not) an inform
\cgalModels `CellAttribute`
\tparam Map must be a model of the `CombinatorialMap` or of the `GeneralizedMap`.
\tparam Map must be a model of the `BasicMap` concept.
\tparam Info_ is the type of the information contained in the attribute.

View File

@ -4,18 +4,13 @@ namespace CGAL {
/*!
\ingroup PkgCombinatorialMapsClasses
The class `Combinatorial_map_min_items` is a model of the `CombinatorialMapItems`
concept. It defines the type of darts which is a
`Dart<d,CMap>`. The `Combinatorial_map_min_items` has a
template argument for the dimension of the combinatorial map.
In this class, no attribute is enabled.
The class `Combinatorial_map_min_items` is a model of the `BasicMapItems` concept. It defines the type of darts which is a `Dart<d,CMap>`. The `Combinatorial_map_min_items` has a template argument for the dimension of the combinatorial map. In this class, no attribute is enabled.
\cgalModels `CombinatorialMapItems`
\cgalModels `BasicMapItems`
\cgalHeading{Example}
The following example shows the implementation of the
`Combinatorial_map_min_items` class.
The following example shows the implementation of the `Combinatorial_map_min_items` class.
\code{.cpp}
template <unsigned int d>

View File

@ -11,7 +11,7 @@ The class `Dart` represents a <I>d</I>D dart in a combinatorial map.
associated to each dart by \link Attribute_handle `Attribute_handle<i>`\endlink, one for each
non void <I>i</I>-attribute.
\cgalModels `::Dart`
\cgalModels `::BasicDart`
\tparam d an integer for the dimension of the dart.

View File

@ -159,7 +159,7 @@ We say that a combinatorial map is <I>valid</I> if it satisfies all the conditio
\subsection ssec-comparison-cmaps-with-gmaps Comparison with generalized maps
Combinatorial maps and \ref ChapterGeneralizedMap "generalized maps" are very similar: they are both based on darts and applications and allow to represent quasi-manifold <I>n</I>D objects.
Combinatorial maps and \ref ChapterGeneralizedMap "generalized maps" are very similar: they are both based on darts and applications and allow to represent quasi-manifold <I>n</I>D objects which explains that they share their main concepts.
However they have two main differences. Firstly, generalized maps allow to represent non-orientable and orientable objects while combinatorial maps allow only to represent orientable objects. Secondly, generalized maps are homogeneous in each dimension since all applications are involutions, while combinatorial maps are not homogeneous since one application is a permutation while other ones are involutions. This homogeneity simplifies algorithms for generalized maps since it allows to avoid a specific case for the first dimension as for combinatorial maps. Thirdly, a generalized map requires twice the number of darts of a combinatorial map in order to represent an orientable object.
@ -169,7 +169,7 @@ Considering these different advantages and drawbacks, you can choose to use gene
\section secsoftwaredesign Software Design
The diagram in \cgalFigureRef{fig_cmap_diagramme_class} shows the different classes of the package. `Combinatorial_map` is the main class (see Section \ref sseccombinatorialmap "Combinatorial Maps"). It allows to manage darts (see Section \ref ssecdarts "Darts") and attributes (see Section \ref ssecattributes "Cell Attributes"). Users can customize a combinatorial map thanks to an items class (see Section \ref ssecitem "Combinatorial Map Items"), which defines the dart type and the attribute types. These types may be different for different dimensions, and they may also be void.
The diagram in \cgalFigureRef{fig_cmap_diagramme_class} shows the different classes of the package. `Combinatorial_map` is the main class (see Section \ref sseccombinatorialmap "Combinatorial Maps"). It allows to manage darts (see Section \ref ssecdarts "Darts") and attributes (see Section \ref ssecattributes "Cell Attributes"). Users can customize a combinatorial map thanks to an items class (see Section \ref ssecitem "Combinatorial Map Items"), which defines the dart type and the attribute types. These types may be different for different dimensions, and they may also be void \tred{(note that the main concepts are shared between combinatorial maps and generalized maps; their name are prefixed by `Basic` except for the `CellAttribute` concept)}.
The darts and attributes are accessed through <I>handles</I>. A handle is a model of the `Handle` concept, thus supporting the two dereference operators `operator*` and `operator->`. All handles are model of `LessThanComparable` and `Hashable`, that is they can be used as keys in containers such as `std::map` and `boost::unordered_map`.
@ -179,46 +179,46 @@ UML diagram of the main classes of the package. k is the number of non void attr
\subsection sseccombinatorialmap Combinatorial Maps
The class `Combinatorial_map<d,Items,Alloc>` is a model of the `CombinatorialMap` concept. It has three template parameters standing for the dimension of the combinatorial map (an `unsigned int`), an items class (a model of the `CombinatorialMapItems` concept), and an allocator which must be a model of the allocator concept of the \stl. %Default classes are provided for the items and the allocator classes.
The class `Combinatorial_map<d,Items,Alloc>` is a model of the `CombinatorialMap` concept \tred{which refines the generic concept of `BasicMap`}. It has three template parameters standing for the dimension of the combinatorial map (an `unsigned int`), an items class (a model of the `BasicMapItems` concept), and an allocator which must be a model of the allocator concept of the \stl. %Default classes are provided for the items and the allocator classes.
The main role of the class `Combinatorial_map` is the storage and the management of darts. It allows to create or remove an isolated dart from the combinatorial map. The \link CombinatorialMap::Dart_handle `Dart_handle`\endlink type defines a handle to the type of used darts (given in the items class). `Combinatorial_map` provides several <I>ranges</I> which allow to iterate over specific subsets of darts of the combinatorial map (see Section \ref ssecrange "Iterating over Orbits, Cells, and Attributes"). It also defines several methods to link and to unlink darts by \f$ \beta_i\f$s (see Section \ref sseclinkdarts "Sewing Orbits and Linking Darts"). We said that a dart <I>d0</I> is <I>i</I>-free if \f$ \beta_i\f$(<I>d0</I>)=\f$ \varnothing\f$. The \f$ \varnothing\f$ constant is represented in the class `Combinatorial_map` through a `Dart_handle` called \link CombinatorialMap::null_dart_handle `null_dart_handle`\endlink. Finally, some high level operations are defined as global functions taking a `Combinatorial_map` as argument (see Section \ref ssecoperations "Removal and Insertion Operations")
The main role of the class `Combinatorial_map` is the storage and the management of darts. It allows to create or remove an isolated dart from the combinatorial map. The \link BasicMap::Dart_handle `Dart_handle`\endlink type defines a handle to the type of used darts (given in the items class). `Combinatorial_map` provides several <I>ranges</I> which allow to iterate over specific subsets of darts of the combinatorial map (see Section \ref ssecrange "Iterating over Orbits, Cells, and Attributes"). It also defines several methods to link and to unlink darts by \f$ \beta_i\f$s (see Section \ref sseclinkdarts "Sewing Orbits and Linking Darts"). We said that a dart <I>d0</I> is <I>i</I>-free if \f$ \beta_i\f$(<I>d0</I>)=\f$ \varnothing\f$. The \f$ \varnothing\f$ constant is represented in the class `Combinatorial_map` through a `Dart_handle` called \link CombinatorialMap::null_dart_handle `null_dart_handle`\endlink. Finally, some high level operations are defined as global functions taking a `Combinatorial_map` as argument (see Section \ref ssecoperations "Removal and Insertion Operations")
The second role of the class `Combinatorial_map` is the storage and the management of attributes. It allows to create or remove an attribute, and provides methods to associate attributes and cells. A range is defined for each <I>i</I>-attribute allowing to iterate over all the <I>i</I>-attributes of the combinatorial map. Finally, `Combinatorial_map` defines several types allowing to manage the attributes. We can use \link CombinatorialMap::Attribute_handle `Combinatorial_map::Attribute_handle<i>::type`\endlink for a handle to the <I>i</I>-attributes (and the const version \link CombinatorialMap::Attribute_const_handle `Combinatorial_map::Attribute_const_handle<i>::type` \endlink) and \link CombinatorialMap::Attribute_type `Combinatorial_map::Attribute_type<i>::type` \endlink for the type of the <I>i</I>-attributes.
The second role of the class `Combinatorial_map` is the storage and the management of attributes. It allows to create or remove an attribute, and provides methods to associate attributes and cells. A range is defined for each <I>i</I>-attribute allowing to iterate over all the <I>i</I>-attributes of the combinatorial map. Finally, `Combinatorial_map` defines several types allowing to manage the attributes. We can use \link BasicMap::Attribute_handle `Combinatorial_map::Attribute_handle<i>::type`\endlink for a handle to the <I>i</I>-attributes (and the const version \link BasicMap::Attribute_const_handle `Combinatorial_map::Attribute_const_handle<i>::type` \endlink) and \link BasicMap::Attribute_type `Combinatorial_map::Attribute_type<i>::type` \endlink for the type of the <I>i</I>-attributes.
All information associated to darts (\f$ \beta\f$ links and attributes) can be accessed through member functions in `CombinatorialMap`.
\subsection ssecitem Combinatorial Map Items
The `CombinatorialMapItems` concept defines dart and attribute types of a combinatorial map. It contains one inner class named \link CombinatorialMapItems::Dart_wrapper `Dart_wrapper`\endlink, having one template parameter, `CMap`, a model of `CombinatorialMap` concept. The \link CombinatorialMapItems::Dart_wrapper `Dart_wrapper<CMap>`\endlink class provides two local types: `%Dart` which must be a model of the `::Dart` concept, and `%Attributes` which defines the attributes and their types.
\tred{The `BasicMapItems` concept defines dart and attribute types of a basic map and thus of a combinatorial map. It contains one inner class named \link BasicMapItems::Dart_wrapper `Dart_wrapper`\endlink, having one template parameter, `BMap`, a model of `BasicMap` concept. The \link BasicMapItems::Dart_wrapper `Dart_wrapper<CMap>`\endlink class provides two local types: `%Dart` which must be a model of the `::BasicDart` concept, and `%Attributes` which defines the attributes and their types.}
The `%Attributes` tuple must contain at most <I>d</I>+1 types (one for each possible cell dimension of the combinatorial map). Each type of the tuple must be either a model of the `CellAttribute` concept or `void`. The first type corresponds to 0-attributes, the second to 1-attributes and so on. If the <i>i <sup>th</sup></i> type in the tuple is `void`, <I>(i-1)</I>-attributes are disabled: we say that <I>(i-1)</I>-attributes are <I>void</I>. Otherwise, <I>(i-1)</I>-attributes are enabled and have the given type: we say <I>(i-1)</I>-attributes are <I>non void</I>. If the size of the tuple is <I>k</I>, with <I>k</I>\f$ <\f$<I>dimension+1</I>, \f$ \forall\f$<I>i</I>: <I>k</I>\f$ \leq\f$<I>i</I>\f$ \leq\f$dimension, <I>i</I>-attributes are void.
The class `Combinatorial_map_min_items<d>` is a model of the `CombinatorialMapItems` concept which can be used for default behaviors. It defines `Dart<d,CMap>` as type of dart, and `Attributes` as empty tuple.
The class `Combinatorial_map_min_items<d>` is a model of the `BasicMapItems` concept which can be used for default behaviors. It defines `Dart<d,CMap>` as type of dart, and `Attributes` as empty tuple.
\subsection ssecdarts Darts
The class `Dart<d,CMap>`, a model of the `::Dart` concept, defines a <I>d</I>D dart. It has two template parameters standing for the dimension of the combinatorial map, and a model of the `CombinatorialMap` concept, which provides the two types \link CombinatorialMap::Dart_handle `Dart_handle`\endlink and \link CombinatorialMap::Dart_const_handle `Dart_const_handle`\endlink.
The class `Dart<d,CMap>`, a model of the `BasicDart` concept, defines a <I>d</I>D dart. It has two template parameters standing for the dimension of the combinatorial map, and a model of the `CombinatorialMap` concept, which provides the two types \link BasicMap::Dart_handle `Dart_handle`\endlink and \link BasicMap::Dart_const_handle `Dart_const_handle`\endlink.
Each instance `d0` of `Dart<d,CMap>` stores the \f$ \beta_i\f$ pointers in an array of <I>d</I>+1 `Dart_handle` (because we describe also the \f$ \beta_0\f$ pointer). It also stores the attributes associated to this dart in a tuple of \link CombinatorialMap::Attribute_handle `CMap::Attribute_handle<i>::type` \endlink, one for each non void <I>i</I>-attribute.
Each instance `d0` of `Dart<d,CMap>` stores the \f$ \beta_i\f$ pointers in an array of <I>d</I>+1 `Dart_handle` (because we describe also the \f$ \beta_0\f$ pointer). It also stores the attributes associated to this dart in a tuple of \link BasicMap::Attribute_handle `CMap::Attribute_handle<i>::type` \endlink, one for each non void <I>i</I>-attribute.
Note that the use of the `Dart` class is not hard wired in the combinatorial map class. Users can provide their own model of the `::Dart` concept, and pass it to the combinatorial map with the help of a custom item class.
Note that the use of the `Dart` class is not hard wired in the combinatorial map class. Users can provide their own model of the `BasicDart` concept, and pass it to the combinatorial map with the help of a custom item class.
\subsection ssecattributes Cell Attributes
The class `Cell_attribute<Map,Info_,Tag,OnMerge,OnSplit>`, a model of the `CellAttribute` concept, represents an attribute associated with a cell of a combinatorial map \tred{or a generalized map (this concept and this class are shared between the two packages)}. The template parameter `Map` must be a model of the `CombinatorialMap` or the `GeneralizedMap` concept. The attribute stores a handle to one dart of its associated cell when the template parameter `Tag` is \link CGAL::Tag_true `Tag_true`\endlink. `Info_` is the type of information stored in the attribute. It may be `void`. `OnMerge` and `OnSplit` must be either `Null_functor`, or models of the `Binary Function` concept having two references to a model of `CellAttribute` as type of both parameters and `void` as return type. There are two default parameters for `OnMerge` and `OnSplit`, which are `Null_functor`, a default parameter for `Tag` which is `Tag_true`, and a default parameter for `Info_` which is `void`.
The class `Cell_attribute<Map,Info_,Tag,OnMerge,OnSplit>`, a model of the `CellAttribute` concept, represents an attribute associated with a cell of a combinatorial map. The template parameter `Map` must be a model of the `BasicMap` concept. The attribute stores a handle to one dart of its associated cell when the template parameter `Tag` is \link CGAL::Tag_true `Tag_true`\endlink. `Info_` is the type of information stored in the attribute. It may be `void`. `OnMerge` and `OnSplit` must be either `Null_functor`, or models of the `Binary Function` concept having two references to a model of `CellAttribute` as type of both parameters and `void` as return type. There are two default parameters for `OnMerge` and `OnSplit`, which are `Null_functor`, a default parameter for `Tag` which is `Tag_true`, and a default parameter for `Info_` which is `void`.
If `Info_` is different from `void`, the class `Cell_attribute` contains two methods `info()` returning the information contained in the attribute (const and non const version). The information is returned by reference, thus the non const version allows the modification of the information.
If `Info_` is different from `void`, the class `Cell_attribute` contains two methods `info()` returning the information contained in the attribute (const and non const version). The information is returned by reference, thus the non const version allows the modification of the information.
Two attributes are merged when their corresponding cells are merged into one cell during some operation. In this case, the functor `OnMerge` is called, unless it is equal to `Null_functor`. This functor allows the user to define its own custom behavior when two attributes are merged (for example if the information is a color, we can compute the average color of the two initial attributes, and affect this value to the first attribute, see example in Section \ref sseccombimapwithcolor "Combinatorial Map With Attributes"). Similarly, the functor `OnSplit` is called when one attribute is split in two, because its corresponding cell is split in two during some operation, unless it is equal to `Null_functor`. In any high level operation, `OnMerge` is called before to start the operation (i.e.\ before modifying the combinatorial map), and `OnSplit` is called when the operation is finished (i.e.\ after all the modifications were made).
In addition, there are dynamic onmerge and onsplit functions that can be associated to i-attributes, and modified, thanks to the \link CombinatorialMap::onmerge_function() `onmerge_function()`\endlink and \link CombinatorialMap::onsplit_function() `onsplit_function()`\endlink. When these functions are set, they are also called in addition to the previous mechanism when two attributes are merged or one attribute is split into two (see example in Section \ref sseccombimapdynamicattibute "Use of Dynamic Onmerge and Onsplit Functors").
In addition, there are dynamic onmerge and onsplit functions that can be associated to i-attributes, and modified, thanks to the \link BasicMap::onmerge_function() `onmerge_function()`\endlink and \link BasicMap::onsplit_function() `onsplit_function()`\endlink. When these functions are set, they are also called in addition to the previous mechanism when two attributes are merged or one attribute is split into two (see example in Section \ref sseccombimapdynamicattibute "Use of Dynamic Onmerge and Onsplit Functors").
What we said for the dart also holds for the cell attribute. The combinatorial map can be used with any user defined model of the `CellAttribute` concept.
\subsection ssecexampledef Example of Combinatorial Map Definition
Here comes an example of two combinatorial map definitions. The first case `Example_cmap4` defines a 4D combinatorial map which uses all the default values (`Dart` and `Combinatorial_map_min_items`). The second example `Example_custom_cmap3` uses its own model of the `CombinatorialMapItems` concept. In this model, the type of dart is `Dart<3,CMap>`, thus a dart is in 3D, and an attribute containing an integer is associated to edges.
Here comes an example of two combinatorial map definitions. The first case `Example_cmap4` defines a 4D combinatorial map which uses all the default values (`Dart` and `Combinatorial_map_min_items`). The second example `Example_custom_cmap3` uses its own model of the `BasicMapItems` concept. In this model, the type of dart is `Dart<3,CMap>`, thus a dart is in 3D, and an attribute containing an integer is associated to edges.
\code{.cpp}
@ -251,48 +251,48 @@ Instead of the `begin()/end()` member function pair as we know it from \stl cont
There are three different categories of dart range classes:
<UL>
<LI>\link CombinatorialMap::Dart_range `Dart_range`\endlink: range of all the darts of a combinatorial map;
<LI>\link BasicMap::Dart_range `Dart_range`\endlink: range of all the darts of a combinatorial map;
<LI>\link CombinatorialMap::Dart_of_orbit_range `Dart_of_orbit_range<Beta...>`\endlink: range of all the darts of the orbit \f$ \langle{}\f$`Beta...`\f$ \rangle{}\f$(<I>d0</I>) for a given <I>d0</I>. `Beta...` is a sequence of integers \f$ i_1\f$,..., \f$ i_k\f$, each \f$ i_j\f$\f$ \in\f${0, ..., <I>d</I>}. These integers must satisfy: \f$ i_1\f$\f$ <\f$\f$ i_2\f$\f$ <\f$...\f$ <\f$\f$ i_k\f$, and (\f$ i_1\f$\f$ \neq\f$ 0 or \f$ i_2\f$\f$ \neq\f$ 1) (for example \link CombinatorialMap::Dart_of_orbit_range `Dart_of_orbit_range<1,2>`\endlink for the orbit \f$ \langle{}\f$\f$ \beta_1\f$,\f$ \beta_2\f$\f$ \rangle{}\f$(<I>d0</I>));
<LI>\link BasicMap::Dart_of_orbit_range `Dart_of_orbit_range<Beta...>`\endlink: range of all the darts of the orbit \f$ \langle{}\f$`Beta...`\f$ \rangle{}\f$(<I>d0</I>) for a given <I>d0</I>. `Beta...` is a sequence of integers \f$ i_1\f$,..., \f$ i_k\f$, each \f$ i_j\f$\f$ \in\f${0, ..., <I>d</I>}. These integers must satisfy: \f$ i_1\f$\f$ <\f$\f$ i_2\f$\f$ <\f$...\f$ <\f$\f$ i_k\f$, and (\f$ i_1\f$\f$ \neq\f$ 0 or \f$ i_2\f$\f$ \neq\f$ 1) (for example \link BasicMap::Dart_of_orbit_range `Dart_of_orbit_range<1,2>`\endlink for the orbit \f$ \langle{}\f$\f$ \beta_1\f$,\f$ \beta_2\f$\f$ \rangle{}\f$(<I>d0</I>));
<LI>\link CombinatorialMap::Dart_of_cell_range `Dart_of_cell_range<i,dim>`\endlink: range of all the darts of the <I>i</I>-cell containing a given dart. The <I>i</I>-cell is considered in dimension `dim` (with 0\f$ \leq\f$<I>dim</I>\f$ \leq\f$<I>d</I>, <I>dim</I>=<I>d</I> by default), with 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>dim+1</I>. If <I>i</I>=<I>dim+1</I>, \link CombinatorialMap::Dart_of_cell_range `Dart_of_cell_range<i,dim>`\endlink is the range of all the darts of the connected component containing a given dart.
<LI>\link BasicMap::Dart_of_cell_range `Dart_of_cell_range<i,dim>`\endlink: range of all the darts of the <I>i</I>-cell containing a given dart. The <I>i</I>-cell is considered in dimension `dim` (with 0\f$ \leq\f$<I>dim</I>\f$ \leq\f$<I>d</I>, <I>dim</I>=<I>d</I> by default), with 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>dim+1</I>. If <I>i</I>=<I>dim+1</I>, \link BasicMap::Dart_of_cell_range `Dart_of_cell_range<i,dim>`\endlink is the range of all the darts of the connected component containing a given dart.
</UL>
There are also two different classes of ranges containing one dart per <I>i</I>-cell. Note that in these classes, the dart of each <I>i</I>-cell can be any dart of the cell. Moreover, each <I>i</I>-cell (and <I>j</I>-cell in the second case) is considered in dimension `dim` (with 0\f$ \leq\f$<I>dim</I>\f$ \leq\f$<I>d</I>, <I>dim=d</I> by default).
<UL>
<LI>\link CombinatorialMap::One_dart_per_cell_range `One_dart_per_cell_range<i,dim>`\endlink: range containing one dart of each <I>i</I>-cell of the combinatorial map, 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>dim+1</I> (for example \link CombinatorialMap::One_dart_per_cell_range `One_dart_per_cell_range<2>`\endlink for the range of one dart per 2-cell of the combinatorial map);
<LI>\link BasicMap::One_dart_per_cell_range `One_dart_per_cell_range<i,dim>`\endlink: range containing one dart of each <I>i</I>-cell of the combinatorial map, 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>dim+1</I> (for example \link BasicMap::One_dart_per_cell_range `One_dart_per_cell_range<2>`\endlink for the range of one dart per 2-cell of the combinatorial map);
<LI>\link CombinatorialMap::One_dart_per_incident_cell_range `One_dart_per_incident_cell_range<i,j,dim>`\endlink: range containing one dart of each <I>i</I>-cell incident to the <I>j</I>-cell containing a given dart, with 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>dim+1</I> and 0\f$ \leq\f$<I>j</I>\f$ \leq\f$<I>dim+1</I> (for example \link CombinatorialMap::One_dart_per_incident_cell_range `One_dart_per_incident_cell_range<0,3>`\endlink for the range of one dart per vertex of the volume incident to the starting dart). If <I>i</I>=<I>j</I>, the range contains only the given dart.
<LI>\link BasicMap::One_dart_per_incident_cell_range `One_dart_per_incident_cell_range<i,j,dim>`\endlink: range containing one dart of each <I>i</I>-cell incident to the <I>j</I>-cell containing a given dart, with 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>dim+1</I> and 0\f$ \leq\f$<I>j</I>\f$ \leq\f$<I>dim+1</I> (for example \link BasicMap::One_dart_per_incident_cell_range `One_dart_per_incident_cell_range<0,3>`\endlink for the range of one dart per vertex of the volume incident to the starting dart). If <I>i</I>=<I>j</I>, the range contains only the given dart.
</UL>
The iterators of the \link CombinatorialMap::Dart_range `Dart_range`\endlink are bidirectional iterators, while the iterators of the other four ranges are forward iterators. The value type of all these iterators is `Dart` thus all these iterators can be directly used as \link CombinatorialMap::Dart_handle `Dart_handle`\endlink.
The iterators of the \link BasicMap::Dart_range `Dart_range`\endlink are bidirectional iterators, while the iterators of the other four ranges are forward iterators. The value type of all these iterators is `Dart` thus all these iterators can be directly used as \link BasicMap::Dart_handle `Dart_handle`\endlink.
Additionally, there is a range over non void <I>i</I>-attributes: \link CombinatorialMap::Attribute_range `Attribute_range<i>::type`\endlink, having a bidirectional iterator with value type \link CombinatorialMap::Attribute_type Attribute_type<i>::type`\endlink.
Additionally, there is a range over non void <I>i</I>-attributes: \link BasicMap::Attribute_range `Attribute_range<i>::type`\endlink, having a bidirectional iterator with value type \link BasicMap::Attribute_type Attribute_type<i>::type`\endlink.
For each range, there is an associated const range, a model of the `ConstRange` concept. You can find some examples of ranges in Section \ref ssecexample3DCM "A 3D Combinatorial Map".
\subsection ssecconstruction Construction Operations
Several functions allow to create specific configurations of darts into a combinatorial map. Existing darts in the combinatorial map are not modified. Note that the dimension of the combinatorial map must be large enough: darts must contain all the \f$ \beta\f$ pointers used by the operation. All these functions return a \link CombinatorialMap::Dart_handle `Dart_handle`\endlink to a new dart created during the operation.
Several functions allow to create specific configurations of darts into a combinatorial map. Existing darts in the combinatorial map are not modified. Note that the dimension of the combinatorial map must be large enough: darts must contain all the \f$ \beta\f$ pointers used by the operation. All these functions return a \link BasicMap::Dart_handle `Dart_handle`\endlink to a new dart created during the operation.
<UL>
<LI>`cm.`\link CombinatorialMap::make_edge `make_edge()`\endlink: creates an isolated edge (two darts linked by \f$ \beta_2\f$); dimension must be greater or equal than two;
<LI>`cm.`\link CombinatorialMap::make_combinatorial_polygon `make_combinatorial_polygon(lg)`\endlink: creates an isolated combinatorial polygon of length `lg` (`lg` darts linked by \f$ \beta_1\f$), for `lg>0`; dimension must be greater or equal than one;
<LI>`cm.`\link CombinatorialMap::make_combinatorial_tetrahedron `make_combinatorial_tetrahedron()`\endlink: creates an isolated combinatorial tetrahedron (four combinatorial triangles linked together by \f$ \beta_2\f$); dimension must be greater or equal than two;
<LI>`cm.`\link CombinatorialMap::make_combinatorial_hexahedron `make_combinatorial_hexahedron()`\endlink: creates an isolated combinatorial hexahedron (six combinatorial quadrangles linked together by \f$ \beta_2\f$); dimension must be greater or equal than two.
<LI>`cm.`\link BasicMap::make_edge `make_edge()`\endlink: creates an isolated edge (two darts linked by \f$ \beta_2\f$); dimension must be greater or equal than two;
<LI>`cm.`\link BasicMap::make_combinatorial_polygon `make_combinatorial_polygon(lg)`\endlink: creates an isolated combinatorial polygon of length `lg` (`lg` darts linked by \f$ \beta_1\f$), for `lg>0`; dimension must be greater or equal than one;
<LI>`cm.`\link BasicMap::make_combinatorial_tetrahedron `make_combinatorial_tetrahedron()`\endlink: creates an isolated combinatorial tetrahedron (four combinatorial triangles linked together by \f$ \beta_2\f$); dimension must be greater or equal than two;
<LI>`cm.`\link BasicMap::make_combinatorial_hexahedron `make_combinatorial_hexahedron()`\endlink: creates an isolated combinatorial hexahedron (six combinatorial quadrangles linked together by \f$ \beta_2\f$); dimension must be greater or equal than two.
</UL>
\subsection ssecadvmarks Boolean Marks
It is often necessary to mark darts, for example to retrieve in <I>O(1)</I> if a given dart was already processed during a specific algorithm, for example, iteration over a given range. Users can also mark specific parts of a combinatorial map (for example mark all the darts belonging to objects having specific semantics). To answer these needs, a `CombinatorialMap` has a certain number of Boolean marks (fixed by the constant \link CombinatorialMap::NB_MARKS `NB_MARKS`\endlink). When one wants to use a Boolean mark, the following methods are available (with `cm` an instance of a combinatorial map):
It is often necessary to mark darts, for example to retrieve in <I>O(1)</I> if a given dart was already processed during a specific algorithm, for example, iteration over a given range. Users can also mark specific parts of a combinatorial map (for example mark all the darts belonging to objects having specific semantics). To answer these needs, a `BasicMap` has a certain number of Boolean marks (fixed by the constant \link BasicMap::NB_MARKS `NB_MARKS`\endlink). When one wants to use a Boolean mark, the following methods are available (with `cm` an instance of a combinatorial map):
<ul>
<li> get a new free mark: `size_type m = cm.`\link CombinatorialMap::get_new_mark `get_new_mark()`\endlink (throws the exception Exception_no_more_available_mark if no mark is available);
<li> set mark `m` for a given dart `d0`: `cm.`\link CombinatorialMap::mark `mark(dh0,m)`\endlink;
<li> unset mark `m` for a given dart `d0`: `cm.`\link CombinatorialMap::unmark `unmark(dh0,m)`\endlink;
<li> test if a given dart `d0` is marked for `m`: `cm.`\link CombinatorialMap::is_marked `is_marked(dh0,m)`\endlink;
<li> unmark all the darts of `cm` for `m`: `cm.`\link CombinatorialMap::unmark_all `unmark_all(m)`\endlink;
<li> negate mark `m` of all the darts of `cm`: `cm.`\link CombinatorialMap::negate_mark `negate_mark(m)`\endlink. All the marked darts become unmarked and all the unmarked darts become marked;
<li> free mark `m`: `cm.`\link CombinatorialMap::free_mark `free_mark(m)`\endlink. This method unmarks all the darts of `cm` for `m` before freeing it.
<li> get a new free mark: `size_type m = cm.`\link BasicMap::get_new_mark `get_new_mark()`\endlink (throws the exception Exception_no_more_available_mark if no mark is available);
<li> set mark `m` for a given dart `d0`: `cm.`\link BasicMap::mark `mark(dh0,m)`\endlink;
<li> unset mark `m` for a given dart `d0`: `cm.`\link BasicMap::unmark `unmark(dh0,m)`\endlink;
<li> test if a given dart `d0` is marked for `m`: `cm.`\link BasicMap::is_marked `is_marked(dh0,m)`\endlink;
<li> unmark all the darts of `cm` for `m`: `cm.`\link BasicMap::unmark_all `unmark_all(m)`\endlink;
<li> negate mark `m` of all the darts of `cm`: `cm.`\link BasicMap::negate_mark `negate_mark(m)`\endlink. All the marked darts become unmarked and all the unmarked darts become marked;
<li> free mark `m`: `cm.`\link BasicMap::free_mark `free_mark(m)`\endlink. This method unmarks all the darts of `cm` for `m` before freeing it.
</ul>
It is important to free a mark when it is no longer needed, otherwise you may at some point run out of marks.
@ -305,15 +305,15 @@ The following example illustrates how to use marks. Two combinatorial tetrahedra
Several operations allow to modify a given combinatorial map. There are two main categories of modification operations:
<UL>
<LI>\ref CombinatorialMap::sew "Sew", \ref CombinatorialMap::link_beta "link_beta", \ref CombinatorialMap::unsew "unsew" and \ref CombinatorialMap::unlink_beta "unlink_beta" which modify some existing \f$ \beta\f$ pointers, without creating or removing darts (see Section \ref sseclinkdarts "Sewing Orbits and Linking Darts");
<LI>\ref BasicMap::sew "Sew", \ref CombinatorialMap::link_beta "link_beta", \ref BasicMap::unsew "unsew" and \ref CombinatorialMap::unlink_beta "unlink_beta" which modify some existing \f$ \beta\f$ pointers, without creating or removing darts (see Section \ref sseclinkdarts "Sewing Orbits and Linking Darts");
<LI>Removal and insertion of cells which modify both darts and \f$ \beta\f$ pointers (see Section \ref ssecoperations "Removal and Insertion Operations").
</UL>
\subsection sseclinkdarts Sewing Orbits and Linking Darts
The `CombinatorialMap` defines two groups of methods to modify the \f$ \beta\f$ pointers of existing darts.
The `BasicMap` defines two groups of methods to modify the \f$ \beta\f$ pointers of existing darts.
The sew and unsew methods iterate over two orbits in order to link or unlink specific darts two by two. Intuitively, a \link CombinatorialMap::sew `sew<i>`\endlink operation glues two <I>i</I>-cells by identifying two of their <I>(i-1)</I>-cells (see example in \cgalFigureRef{fig_cmap_example_3d_sew} where \link CombinatorialMap::sew `sew<3>`\endlink is used to glue two 3-cells along one 2-cell). Reciprocally, a \link CombinatorialMap::unsew `unsew<i>`\endlink operation un-glues two <I>i</I>-cells which were glued along one of their <I>(i-1)</I>-cells. These methods guarantee that given a valid combinatorial map and a possible operation we obtain a valid combinatorial map as result of the operation.
The sew and unsew methods iterate over two orbits in order to link or unlink specific darts two by two. Intuitively, a \link BasicMap::sew `sew<i>`\endlink operation glues two <I>i</I>-cells by identifying two of their <I>(i-1)</I>-cells (see example in \cgalFigureRef{fig_cmap_example_3d_sew} where \link BasicMap::sew `sew<3>`\endlink is used to glue two 3-cells along one 2-cell). Reciprocally, a \link BasicMap::unsew `unsew<i>`\endlink operation un-glues two <I>i</I>-cells which were glued along one of their <I>(i-1)</I>-cells. These methods guarantee that given a valid combinatorial map and a possible operation we obtain a valid combinatorial map as result of the operation.
\cgalAdvancedBegin
The \link CombinatorialMap::link_beta `link_beta`\endlink and \link CombinatorialMap::unlink_beta `unlink_beta`\endlink methods only modify the pointer of two darts: the obtained combinatorial maps may be not valid. These operations can be useful to use low level operations in a specific algorithm, for example to modify locally a combinatorial map in a really fast way. In such a case, additional operations may be needed to restore the validity conditions.
@ -325,29 +325,29 @@ Linking two darts <I>d1</I> and <I>d2</I> by \f$ \beta_i\f$, with 2\f$ \leq\f$<I
Reciprocally, unlinking a given dart <I>d0</I> by \f$ \beta_i\f$, with 2\f$ \leq\f$ <I>i</I>\f$ \leq\f$<I>d</I>, consists in modifying two \f$ \beta_i\f$ pointers such that \f$ \beta_i\f$(\f$ \beta_i\f$(<I>d0</I>))=\f$ \varnothing\f$ and \f$ \beta_i\f$(<I>d0</I>)=\f$ \varnothing\f$. For <I>i=1</I>, the modification is \f$ \beta_1\f$(<I>d0</I>)=\f$ \varnothing\f$ (and thus \f$ \beta_0\f$(\f$ \beta_1\f$(<I>d0</I>))=\f$ \varnothing\f$ by definition of \f$ \beta_0\f$). Note that is it possible to unlink a given dart for \f$ \beta_i\f$ only if it is not <I>i</I>-free.
\cgalFigureBegin{fig_cmap_example_3d_sew,cmap_example_3d_sew.svg}
Example of 3-sew operation. Left: A 3D combinatorial map containing two volumes that are not connected, with 2-attributes. Each attribute contains a color in RGB format, and there are four 2-cells associated with attributes. Associations between darts and attributes are drawn with red segments. Right: The 3D combinatorial map obtained as result of \link CombinatorialMap::sew `sew<3>(1,5)`\endlink (or \link CombinatorialMap::sew `sew<3>(2,8)`\endlink, or \link CombinatorialMap::sew `sew<3>(3,7)`\endlink, or \link CombinatorialMap::sew `sew<3>(4,6)`\endlink). Darts (1,5), (2,8), (3,7) and (4,6) are linked together by \f$ \beta_3\f$. The two 2-cells <I>c1</I>={1,2,3,4} and <I>c2</I>={5,6,7,8} are merged after the sew into the 2-cell {1,2,3,4,5,6,7,8}. We are in the case where the two attributes are non NULL, thus the first one is kept, and all the darts of <I>c2</I> are associated with the first attribute.
Example of 3-sew operation. Left: A 3D combinatorial map containing two volumes that are not connected, with 2-attributes. Each attribute contains a color in RGB format, and there are four 2-cells associated with attributes. Associations between darts and attributes are drawn with red segments. Right: The 3D combinatorial map obtained as result of \link BasicMap::sew `sew<3>(1,5)`\endlink (or \link BasicMap::sew `sew<3>(2,8)`\endlink, or \link BasicMap::sew `sew<3>(3,7)`\endlink, or \link BasicMap::sew `sew<3>(4,6)`\endlink). Darts (1,5), (2,8), (3,7) and (4,6) are linked together by \f$ \beta_3\f$. The two 2-cells <I>c1</I>={1,2,3,4} and <I>c2</I>={5,6,7,8} are merged after the sew into the 2-cell {1,2,3,4,5,6,7,8}. We are in the case where the two attributes are non NULL, thus the first one is kept, and all the darts of <I>c2</I> are associated with the first attribute.
\cgalFigureEnd
The \link CombinatorialMap::sew `sew<i>(dh1,dh2)`\endlink method consists mainly to link two by two several darts by \f$ \beta_i\f$. This operation is possible only if there is a bijection <I>f</I> between all the darts of the orbit <I>D1</I>=\f$ \langle{}\f$\f$ \beta_1\f$,...,\f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,...,\f$ \beta_d\f$\f$ \rangle{}\f$(<I>d1</I>) and <I>D2</I>=\f$ \langle{}\f$\f$ \beta_1\f$,...,\f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,..., \f$ \beta_d\f$\f$ \rangle{}\f$(<I>d2</I>) satisfying: <I>f</I>(<I>d1</I>)=<I>d2</I>, and for all <I>e</I>\f$ \in\f$<I>D1</I>, for all <I>j</I>\f$ \in\f${1,..., i-2,i+2,...,<I>d</I>}, <I>f</I>(\f$ \beta_j\f$(<I>e</I>))=\f$ \beta_j^{-1}\f$(<I>f</I>(<I>e</I>)). Intuitively, this condition ensures the validity of the combinatorial map by verifying that condition discussed in Section \ref sseccombimapvalidity "Combinatorial Map Properties" will be satisfied after the operation. This condition can be tested by using the method \link CombinatorialMap::is_sewable `is_sewable<i>(dh1,dh2)`\endlink. For example, the function \link CombinatorialMap::is_sewable `is_sewable<3>`\endlink would return `false` if we tried to 3-sew a triangular facet with a quad facet. Note that given two darts <I>d1</I> and <I>d2</I>, if there is such a bijection, it is uniquely defined. So giving the two darts as arguments of the \link CombinatorialMap::sew `sew<i>`\endlink is enough to retrieve all the pairs of darts to link. If such a bijection exists, the \link CombinatorialMap::sew `sew<i>(dh1,dh2)`\endlink operation consists only in linking by \f$ \beta_i\f$ each couple of darts <I>d3</I> and <I>d4</I> such that <I>d3</I>=<I>f</I>(<I>d4</I>).
The \link BasicMap::sew `sew<i>(dh1,dh2)`\endlink method consists mainly to link two by two several darts by \f$ \beta_i\f$. This operation is possible only if there is a bijection <I>f</I> between all the darts of the orbit <I>D1</I>=\f$ \langle{}\f$\f$ \beta_1\f$,...,\f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,...,\f$ \beta_d\f$\f$ \rangle{}\f$(<I>d1</I>) and <I>D2</I>=\f$ \langle{}\f$\f$ \beta_1\f$,...,\f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,..., \f$ \beta_d\f$\f$ \rangle{}\f$(<I>d2</I>) satisfying: <I>f</I>(<I>d1</I>)=<I>d2</I>, and for all <I>e</I>\f$ \in\f$<I>D1</I>, for all <I>j</I>\f$ \in\f${1,..., i-2,i+2,...,<I>d</I>}, <I>f</I>(\f$ \beta_j\f$(<I>e</I>))=\f$ \beta_j^{-1}\f$(<I>f</I>(<I>e</I>)). Intuitively, this condition ensures the validity of the combinatorial map by verifying that condition discussed in Section \ref sseccombimapvalidity "Combinatorial Map Properties" will be satisfied after the operation. This condition can be tested by using the method \link BasicMap::is_sewable `is_sewable<i>(dh1,dh2)`\endlink. For example, the function \link BasicMap::is_sewable `is_sewable<3>`\endlink would return `false` if we tried to 3-sew a triangular facet with a quad facet. Note that given two darts <I>d1</I> and <I>d2</I>, if there is such a bijection, it is uniquely defined. So giving the two darts as arguments of the \link BasicMap::sew `sew<i>`\endlink is enough to retrieve all the pairs of darts to link. If such a bijection exists, the \link BasicMap::sew `sew<i>(dh1,dh2)`\endlink operation consists only in linking by \f$ \beta_i\f$ each couple of darts <I>d3</I> and <I>d4</I> such that <I>d3</I>=<I>f</I>(<I>d4</I>).
In addition, the sew operation updates the associations between darts and non void attributes in order to guarantee that all the darts belonging to a given cell are associated with the same attribute (which is a condition of combinatorial map validity). For each couple of <I>j</I>-cells <I>c1</I> and <I>c2</I> that are merged into one <I>j</I>-cell during the sew, we have to update the two associated attributes <I>attr1</I> and <I>attr2</I>. If both are NULL, there is nothing to do. If one is NULL and the other not, we only associate the non NULL attribute to all the darts of the resulting cell. When the two attributes are non NULL, we first apply functor \link CellAttribute::On_merge `On_merge`\endlink on the two attributes <I>attr1</I> and <I>attr2</I> (see Section \ref ssecattributes "Cell Attributes"). Then, we associate the attribute <I>attr1</I> to all darts of the resulting <I>j</I>-cell. Finally, attribute <I>attr2</I> is removed from the combinatorial map.
Note that when the two attributes are non NULL, the first one is kept. But user can customize this behavior in order to update the information contained in the attributes according to its needs. For that, we can define a specific functor, and use it as template argument for \link CellAttribute::On_merge `On_merge`\endlink parameter of the `Cell_attribute` definition. This functor can for example copy the information of the second attribute in the information of the first one to make as if the second attribute is kept.
For example, in \cgalFigureRef{fig_cmap_example_3d_sew}, we want to 3-sew the two initial volumes. \link CombinatorialMap::sew `sew<3>(1,5)`\endlink links by \f$ \beta_3\f$ the pairs of darts (1,5), (2,8), (3,7) and (4,6), thus the combinatorial map obtained is valid. 2-attributes are updated so that all the darts belonging to the 2-cell containing dart 1 become associated to the same 2-attribute after the operation.
For example, in \cgalFigureRef{fig_cmap_example_3d_sew}, we want to 3-sew the two initial volumes. \link BasicMap::sew `sew<3>(1,5)`\endlink links by \f$ \beta_3\f$ the pairs of darts (1,5), (2,8), (3,7) and (4,6), thus the combinatorial map obtained is valid. 2-attributes are updated so that all the darts belonging to the 2-cell containing dart 1 become associated to the same 2-attribute after the operation.
Similarly, \link CombinatorialMap::unsew `unsew<i>(dh0)`\endlink operation unlinks \f$ \beta_i\f$ for all the darts in the orbit \f$ \langle{}\f$\f$ \beta_1\f$,..., \f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,...,\f$ \beta_d\f$\f$ \rangle{}\f$(<I>d0</I>), and thus guarantees to obtain a valid combinatorial map. This operation is possible for any non <I>i</I>-free dart.
Similarly, \link BasicMap::unsew `unsew<i>(dh0)`\endlink operation unlinks \f$ \beta_i\f$ for all the darts in the orbit \f$ \langle{}\f$\f$ \beta_1\f$,..., \f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,...,\f$ \beta_d\f$\f$ \rangle{}\f$(<I>d0</I>), and thus guarantees to obtain a valid combinatorial map. This operation is possible for any non <I>i</I>-free dart.
As for the sew operations, attributes are updated to guarantee that two darts belonging to two different <I>j</I>-cells are associated to two different <I>j</I>-attributes. If the unsew operation splits a <I>j</I>-cell <I>c</I> in two <I>j</I>-cells <I>c1</I> and <I>c2</I>, and if <I>c</I> is associated to a <I>j</I>-attribute <I>attr1</I>, then this attribute is duplicated into <I>attr2</I>, and all the darts belonging to <I>c2</I> are associated with this new attribute. Finally, we call the functor \link CellAttribute::On_split `On_split`\endlink on the two attributes <I>attr1</I> and <I>attr2</I> (see Section \ref ssecattributes "Cell Attributes").
Let us consider the combinatorial map given in \cgalFigureRef{fig_cmap_example_3d_sew} (Right). If we call \link CombinatorialMap::unsew `unsew<3>(2)`\endlink, we obtain the combinatorial map in \cgalFigureRef{fig_cmap_example_3d_sew} (Left) (except for the color of the attribute associated to the 2-cell {5,6,7,8} which would be <TT>#00ff00</TT>). The \link CombinatorialMap::unsew `unsew<3>`\endlink operation has duplicated the 2-attribute associated to the 2-cell {1,2,3,4,5,6,7,8} since this 2-cell is split in two after the unsew operation.
Let us consider the combinatorial map given in \cgalFigureRef{fig_cmap_example_3d_sew} (Right). If we call \link BasicMap::unsew `unsew<3>(2)`\endlink, we obtain the combinatorial map in \cgalFigureRef{fig_cmap_example_3d_sew} (Left) (except for the color of the attribute associated to the 2-cell {5,6,7,8} which would be <TT>#00ff00</TT>). The \link BasicMap::unsew `unsew<3>`\endlink operation has duplicated the 2-attribute associated to the 2-cell {1,2,3,4,5,6,7,8} since this 2-cell is split in two after the unsew operation.
\cgalAdvancedBegin
If one wants to modify a combinatorial map <I>manually</I>, it is possible to switch off the updating between darts and attributes by calling \link CombinatorialMap::set_automatic_attributes_management `set_automatic_attributes_management(false)`\endlink before to call \link CombinatorialMap::sew `sew<i>(dh1,dh2)`\endlink and \link CombinatorialMap::unsew `unsew<i>(dh0)`\endlink. In these cases, the combinatorial map obtained may be no longer valid due to incorrect associations between darts and attributes. A call latter to \link CombinatorialMap::set_automatic_attributes_management `set_automatic_attributes_management(true)`\endlink will correct the invalid non void attributes.
If one wants to modify a combinatorial map <I>manually</I>, it is possible to switch off the updating between darts and attributes by calling \link BasicMap::set_automatic_attributes_management `set_automatic_attributes_management(false)`\endlink before to call \link BasicMap::sew `sew<i>(dh1,dh2)`\endlink and \link BasicMap::unsew `unsew<i>(dh0)`\endlink. In these cases, the combinatorial map obtained may be no longer valid due to incorrect associations between darts and attributes. A call latter to \link BasicMap::set_automatic_attributes_management `set_automatic_attributes_management(true)`\endlink will correct the invalid non void attributes.
In \cgalFigureRef{fig_cmap_example_3d_sew} (Left), if we call \link CombinatorialMap::sew `sew<3>(1,5)`\endlink, the resulting combinatorial map is similar to the combinatorial map of \cgalFigureRef{fig_cmap_example_3d_sew} (Right) (we have linked by \f$ \beta_3\f$ the pairs of darts (1,5), (2,8), (3,7) and (4,6)), but associations between darts and attributes are not valid. Indeed, we have kept the four initial attributes and all the associations between darts and attributes, thus two darts belonging to the same 2-cell (for example darts 1 and 5) are associated with two different attributes.
In \cgalFigureRef{fig_cmap_example_3d_sew} (Left), if we call \link BasicMap::sew `sew<3>(1,5)`\endlink, the resulting combinatorial map is similar to the combinatorial map of \cgalFigureRef{fig_cmap_example_3d_sew} (Right) (we have linked by \f$ \beta_3\f$ the pairs of darts (1,5), (2,8), (3,7) and (4,6)), but associations between darts and attributes are not valid. Indeed, we have kept the four initial attributes and all the associations between darts and attributes, thus two darts belonging to the same 2-cell (for example darts 1 and 5) are associated with two different attributes.
We can also use the \link CombinatorialMap::link_beta `link_beta<i>(dh1,dh2)`\endlink which links `d1` and `d2` by \f$ \beta_i\f$ without modifying the other links. Association between darts and attributes are only modified for darts `d1` and `d2`, and similarly as for \link CombinatorialMap::sew `sew<i>`\endlink, this updating can be avoided by calling \link CombinatorialMap::set_automatic_attributes_management `set_automatic_attributes_management(false)`\endlink before to call \link CombinatorialMap::link_beta `link_beta<i>(dh1,dh2)`\endlink. Lastly, we can use \link CombinatorialMap::unlink_beta `unlink_beta<i>(dh0)`\endlink to unlink `d0` for \f$ \beta_i\f$. In this last case, there is no modification of association between darts and attributes.
We can also use the \link CombinatorialMap::link_beta `link_beta<i>(dh1,dh2)`\endlink which links `d1` and `d2` by \f$ \beta_i\f$ without modifying the other links. Association between darts and attributes are only modified for darts `d1` and `d2`, and similarly as for \link BasicMap::sew `sew<i>`\endlink, this updating can be avoided by calling \link BasicMap::set_automatic_attributes_management `set_automatic_attributes_management(false)`\endlink before to call \link CombinatorialMap::link_beta `link_beta<i>(dh1,dh2)`\endlink. Lastly, we can use \link CombinatorialMap::unlink_beta `unlink_beta<i>(dh0)`\endlink to unlink `d0` for \f$ \beta_i\f$. In this last case, there is no modification of association between darts and attributes.
In \cgalFigureRef{fig_cmap_example_3d_sew} (Left), if we call \link CombinatorialMap::link_beta `link_beta<3>(1,5)`\endlink, in the resulting combinatorial map we have now \f$ \beta_3\f$(1)=5 and \f$ \beta_3\f$(5)=1. This combinatorial map is no longer valid (for example dart 2 is 3-free and we should have \f$ \beta_3\f$(2)=8).
\cgalAdvancedEnd
@ -356,46 +356,46 @@ In \cgalFigureRef{fig_cmap_example_3d_sew} (Left), if we call \link Combinatoria
The following high level operations are defined. All these methods ensure that given a valid combinatorial map and a possible operation, the modified combinatorial map is also valid.
The first one is `cm.`\link CombinatorialMap::remove_cell `remove_cell<i>(dh0)`\endlink which modifies the combinatorial map to remove the <I>i</I>-cell containing dart `d0`, with 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>d</I>. This operation is possible if <I>i</I>=<I>d</I> or if the given <I>i</I>-cell is incident to at most two <I>(i+1)</I>-cells which can be tested thanks to `cm.`\link CombinatorialMap::is_removable `is_removable<i>(dh0)`\endlink. If the removed <I>i</I>-cell was incident to two different <I>(i+1)</I>-cells, these two cells are merged into one <I>(i+1)</I>-cell. In this case, the \link CellAttribute::On_merge `On_merge`\endlink functor is called if two <I>(i+1)</I>-attributes are associated to the two <I>(i+1)</I>-cells. If the <I>i</I>-cell is associated with a non void attribute, it is removed from the combinatorial map (see three examples on \cgalFigureRef{fig_cmap_insert_vertex}, \cgalFigureRef{fig_cmap_insert_edge} and \cgalFigureRef{fig_cmap_insert_facet}).
The first one is `cm.`\link BasicMap::remove_cell `remove_cell<i>(dh0)`\endlink which modifies the combinatorial map to remove the <I>i</I>-cell containing dart `d0`, with 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>d</I>. This operation is possible if <I>i</I>=<I>d</I> or if the given <I>i</I>-cell is incident to at most two <I>(i+1)</I>-cells which can be tested thanks to `cm.`\link BasicMap::is_removable `is_removable<i>(dh0)`\endlink. If the removed <I>i</I>-cell was incident to two different <I>(i+1)</I>-cells, these two cells are merged into one <I>(i+1)</I>-cell. In this case, the \link CellAttribute::On_merge `On_merge`\endlink functor is called if two <I>(i+1)</I>-attributes are associated to the two <I>(i+1)</I>-cells. If the <I>i</I>-cell is associated with a non void attribute, it is removed from the combinatorial map (see three examples on \cgalFigureRef{fig_cmap_insert_vertex}, \cgalFigureRef{fig_cmap_insert_edge} and \cgalFigureRef{fig_cmap_insert_facet}).
\cgalFigureBegin{fig_cmap_insert_vertex,cmap_insert_vertex.svg}
Example of \link CombinatorialMap::insert_cell_0_in_cell_1 `insert_cell_0_in_cell_1`\endlink and \link CombinatorialMap::remove_cell `remove_cell<0>`\endlink operations. Left: Initial combinatorial map. Right: After the insertion of a 0-cell in the 1-cell containing dart `d1`. Now if we remove the 0-cell containing dart `d2`, we obtain the initial combinatorial map.
Example of \link BasicMap::insert_cell_0_in_cell_1 `insert_cell_0_in_cell_1`\endlink and \link BasicMap::remove_cell `remove_cell<0>`\endlink operations. Left: Initial combinatorial map. Right: After the insertion of a 0-cell in the 1-cell containing dart `d1`. Now if we remove the 0-cell containing dart `d2`, we obtain the initial combinatorial map.
\cgalFigureEnd
The inverse operation of the removal is the insertion operation. Several versions exist, sharing a common principle. They consist in adding a new <I>i</I>-cell "inside" an existing <I>j</I>-cell, <I>i</I>\f$ <\f$<I>j</I>, by splitting the <I>j</I>-cell into several <I>j</I>-cells. Contrary to `remove_cell<i>`, is it not possible to define a unique `insert_cell_i_in_cell_j<i,j>` function because parameters are different depending on `i` and `j`.
`cm.`\link CombinatorialMap::insert_cell_0_in_cell_1 `insert_cell_0_in_cell_1(dh0)`\endlink adds a 0-cell in the 1-cell containing dart `d0`. The 1-cell is split in two. This operation is possible if `d0`\f$ \in\f$\link CombinatorialMap::darts `cm.darts()`\endlink (see example on \cgalFigureRef{fig_cmap_insert_vertex}).
`cm.`\link BasicMap::insert_cell_0_in_cell_1 `insert_cell_0_in_cell_1(dh0)`\endlink adds a 0-cell in the 1-cell containing dart `d0`. The 1-cell is split in two. This operation is possible if `d0`\f$ \in\f$\link BasicMap::darts `cm.darts()`\endlink (see example on \cgalFigureRef{fig_cmap_insert_vertex}).
`cm.`\link CombinatorialMap::insert_cell_0_in_cell_2 `insert_cell_0_in_cell_2(dh0)`\endlink adds a 0-cell in the 2-cell containing dart `d0`. The 2-cell is split in triangles, one for each initial edge of the facet. This operation is possible if `d0`\f$ \in\f$\link CombinatorialMap::darts `cm.darts()`\endlink (see example on \cgalFigureRef{fig_cmap_triangulation}).
`cm.`\link BasicMap::insert_cell_0_in_cell_2 `insert_cell_0_in_cell_2(dh0)`\endlink adds a 0-cell in the 2-cell containing dart `d0`. The 2-cell is split in triangles, one for each initial edge of the facet. This operation is possible if `d0`\f$ \in\f$\link BasicMap::darts `cm.darts()`\endlink (see example on \cgalFigureRef{fig_cmap_triangulation}).
\cgalFigureBegin{fig_cmap_triangulation,cmap_triangulation.svg}
Example of \link CombinatorialMap::insert_cell_0_in_cell_2 `insert_cell_0_in_cell_2`\endlink operation.
Example of \link BasicMap::insert_cell_0_in_cell_2 `insert_cell_0_in_cell_2`\endlink operation.
\cgalFigureEnd
`cm.`\link CombinatorialMap::insert_cell_1_in_cell_2 `insert_cell_1_in_cell_2(dh1,dh2)`\endlink adds a 1-cell in the 2-cell containing darts `d1` and `d2`, between the two 0-cells containing darts `d1` and `d2`. The 2-cell is split in two. This operation is possible if <I>d1</I>\f$ \in\f$\f$ \langle{}\f$\f$ \beta_1\f$\f$ \rangle{}\f$(<I>d2</I>) which can be tested thanks to `cm.`\link CombinatorialMap::is_insertable_cell_1_in_cell_2 `is_insertable_cell_1_in_cell_2(dh1,dh2)`\endlink. In the example on \cgalFigureRef{fig_cmap_insert_edge}, it is possible to insert an edge between darts <I>d2</I> and <I>d3</I>, but it is not possible to insert an edge between <I>d1</I> and <I>d3</I>.
`cm.`\link BasicMap::insert_cell_1_in_cell_2 `insert_cell_1_in_cell_2(dh1,dh2)`\endlink adds a 1-cell in the 2-cell containing darts `d1` and `d2`, between the two 0-cells containing darts `d1` and `d2`. The 2-cell is split in two. This operation is possible if <I>d1</I>\f$ \in\f$\f$ \langle{}\f$\f$ \beta_1\f$\f$ \rangle{}\f$(<I>d2</I>) which can be tested thanks to `cm.`\link BasicMap::is_insertable_cell_1_in_cell_2 `is_insertable_cell_1_in_cell_2(dh1,dh2)`\endlink. In the example on \cgalFigureRef{fig_cmap_insert_edge}, it is possible to insert an edge between darts <I>d2</I> and <I>d3</I>, but it is not possible to insert an edge between <I>d1</I> and <I>d3</I>.
\cgalFigureBegin{fig_cmap_insert_edge,cmap_insert_edge.svg}
Example of \link CombinatorialMap::insert_cell_1_in_cell_2 `insert_cell_1_in_cell_2`\endlink and \link CombinatorialMap::remove_cell `remove_cell<1>`\endlink operations. Left: Initial combinatorial map. Right: After the insertion of two 1-cells: a first one between the two 0-cells containing darts `d2` and `d3`, and a second one incident to the 0-cell containing dart `d1`. Now if we remove the two 1-cells containing darts `d4` and `d5`, we obtain the initial combinatorial map.
Example of \link BasicMap::insert_cell_1_in_cell_2 `insert_cell_1_in_cell_2`\endlink and \link BasicMap::remove_cell `remove_cell<1>`\endlink operations. Left: Initial combinatorial map. Right: After the insertion of two 1-cells: a first one between the two 0-cells containing darts `d2` and `d3`, and a second one incident to the 0-cell containing dart `d1`. Now if we remove the two 1-cells containing darts `d4` and `d5`, we obtain the initial combinatorial map.
\cgalFigureEnd
`cm.`\link CombinatorialMap::insert_dangling_cell_1_in_cell_2 `insert_dangling_cell_1_in_cell_2(dh0)`\endlink adds a 1-cell in the 2-cell containing dart `d0`, the 1-cell being attached by only one of its vertex to the 0-cell containing dart `d0`. This operation is possible if `d0`\f$ \in\f$\link CombinatorialMap::darts `cm.darts()`\endlink.
`cm.`\link BasicMap::insert_dangling_cell_1_in_cell_2 `insert_dangling_cell_1_in_cell_2(dh0)`\endlink adds a 1-cell in the 2-cell containing dart `d0`, the 1-cell being attached by only one of its vertex to the 0-cell containing dart `d0`. This operation is possible if `d0`\f$ \in\f$\link BasicMap::darts `cm.darts()`\endlink.
`cm.`\link CombinatorialMap::insert_cell_2_in_cell_3 `insert_cell_2_in_cell_3(itbegin,itend)`\endlink adds a 2-cell in the 3-cell containing all the darts between `itbegin` and `itend`, along the path of 1-cells containing darts in [`itbegin`,`itend`). The 3-cell is split in two. This operation is possible if all the darts in [`itbegin`,`itend`) form a closed path inside a same 3-cell which can be tested thanks to `cm.`\link CombinatorialMap::is_insertable_cell_2_in_cell_3 `is_insertable_cell_2_in_cell_3(itbegin,itend)`\endlink (see example on \cgalFigureRef{fig_cmap_insert_facet}).
`cm.`\link BasicMap::insert_cell_2_in_cell_3 `insert_cell_2_in_cell_3(itbegin,itend)`\endlink adds a 2-cell in the 3-cell containing all the darts between `itbegin` and `itend`, along the path of 1-cells containing darts in [`itbegin`,`itend`). The 3-cell is split in two. This operation is possible if all the darts in [`itbegin`,`itend`) form a closed path inside a same 3-cell which can be tested thanks to `cm.`\link BasicMap::is_insertable_cell_2_in_cell_3 `is_insertable_cell_2_in_cell_3(itbegin,itend)`\endlink (see example on \cgalFigureRef{fig_cmap_insert_facet}).
\cgalFigureBegin{fig_cmap_insert_facet,cmap_insert_facet.svg}
Example of \link CombinatorialMap::insert_cell_2_in_cell_3 `insert_cell_2_in_cell_3`\endlink and \link CombinatorialMap::remove_cell `remove_cell<2>`\endlink operations. Left: Initial combinatorial map. Right: After the insertion of a 2-cell along the path of 1-cells containing respectively `d1,d2,d3,d4`. Now if we remove the 2-cell containing dart `d5`, we obtain the initial combinatorial map. \cgalFigureEnd
Example of \link BasicMap::insert_cell_2_in_cell_3 `insert_cell_2_in_cell_3`\endlink and \link BasicMap::remove_cell `remove_cell<2>`\endlink operations. Left: Initial combinatorial map. Right: After the insertion of a 2-cell along the path of 1-cells containing respectively `d1,d2,d3,d4`. Now if we remove the 2-cell containing dart `d5`, we obtain the initial combinatorial map. \cgalFigureEnd
Some examples of use of these operations are given in Section \ref ssecexempleoperations "High Level Operations".
\cgalAdvancedBegin
If \link CombinatorialMap::set_automatic_attributes_management `set_automatic_attributes_management(false)`\endlink is called, all the future insertion or removal operations will not update non void attributes. These attributes will be updated latter by the call to \link CombinatorialMap::set_automatic_attributes_management `set_automatic_attributes_management(true)`\endlink. This can be useful to speed up an algorithm which uses several successive insertion and removal operations. See example \ref ssecAttributesManagement "Automatic attributes management".
If \link BasicMap::set_automatic_attributes_management `set_automatic_attributes_management(false)`\endlink is called, all the future insertion or removal operations will not update non void attributes. These attributes will be updated latter by the call to \link BasicMap::set_automatic_attributes_management `set_automatic_attributes_management(true)`\endlink. This can be useful to speed up an algorithm which uses several successive insertion and removal operations. See example \ref ssecAttributesManagement "Automatic attributes management".
\cgalAdvancedEnd
\section Combinatorial_mapExamples Examples
\subsection ssecexample3DCM A 3D Combinatorial Map
In this example, a 3-dimensional combinatorial map is constructed. Two combinatorial tetrahedra are created, then the numbers of cells of the combinatorial map are displayed, and the validity of the combinatorial map is checked. Then, we illustrate the use of ranges to iterate over specific darts. The first loop enumerates all the darts of the first tetrahedron by using the range \link CombinatorialMap::Dart_of_orbit_range `Dart_of_orbit_range<1,2>`\endlink, and the second loop enumerates all the darts of the facet containing dart `dh2` by using the range \link CombinatorialMap::Dart_of_orbit_range `Dart_of_orbit_range<1>`\endlink.
In this example, a 3-dimensional combinatorial map is constructed. Two combinatorial tetrahedra are created, then the numbers of cells of the combinatorial map are displayed, and the validity of the combinatorial map is checked. Then, we illustrate the use of ranges to iterate over specific darts. The first loop enumerates all the darts of the first tetrahedron by using the range \link BasicMap::Dart_of_orbit_range `Dart_of_orbit_range<1,2>`\endlink, and the second loop enumerates all the darts of the facet containing dart `dh2` by using the range \link BasicMap::Dart_of_orbit_range `Dart_of_orbit_range<1>`\endlink.
\cgalExample{Combinatorial_map/map_3_simple_example.cpp}
@ -408,7 +408,7 @@ Number of darts of the facet containing dh2: 3
which gives the number of darts of the combinatorial map, the numbers of different cells, the number of connected components, and finally a Boolean showing the validity of the combinatorial map (a tetrahedron is made up of 12 darts because there are 3 darts per facet and there are 4 facets).
Note the creation in the for loops of the two instances of \link CombinatorialMap::Dart_of_orbit_range `Dart_of_orbit_range`\endlink::`const_iterator`: `it` is the current iterator, and `itend` an iterator to the end of the range. Having `itend` avoids calling \link CombinatorialMap::darts_of_orbit `cm.darts_of_orbit<1,2>(dh1)`\endlink`.end()` again and again as in the following example (which is a bad solution):
Note the creation in the for loops of the two instances of \link BasicMap::Dart_of_orbit_range `Dart_of_orbit_range`\endlink::`const_iterator`: `it` is the current iterator, and `itend` an iterator to the end of the range. Having `itend` avoids calling \link BasicMap::darts_of_orbit `cm.darts_of_orbit<1,2>(dh1)`\endlink`.end()` again and again as in the following example (which is a bad solution):
\code{.cpp}
@ -443,13 +443,13 @@ The second line is the result after the removal operations. We retrieve the orig
Example of high level operations. Left: Initial 3D combinatorial map after the creation of the combinatorial hexahedron. Middle: Combinatorial map obtained after the two 1-cell insertions. The two 2-cells were split in two. Right: Combinatorial map obtained after the 2-cell insertion. The 3-cell was split in two.
\cgalFigureEnd
\subsection Combinatorial_mapA4DCombinatorialMap A 4D Combinatorial Map
\subsection Combinatorial_mapA4DBasicMap A 4D Combinatorial Map
In this example, a 4-dimensional combinatorial map is used. Two tetrahedral cells are created and sewn by \f$ \beta_4\f$. Then the numbers of cells of the combinatorial map are displayed, and its validity is checked.
By looking at these numbers of cells, we can see that the 4D combinatorial map contains only one 3-cell. Indeed, the \link CombinatorialMap::sew `sew<4>`\endlink operation has identified by pairs all the darts of the two 3-cells by definition of the sew operation (see Section \ref sseclinkdarts "Sewing Orbits and Linking Darts") which, in 4D, links by \f$ \beta_3\f$ all the darts in \f$ \langle{}\f$\f$ \beta_1\f$,\f$ \beta_2\f$\f$ \rangle{}\f$(<I>d1</I>) and in \f$ \langle{}\f$\f$ \beta_1\f$,\f$ \beta_2\f$\f$ \rangle{}\f$(<I>d2</I>). The situation is similar (but in higher dimension) to the configuration where we have two triangles in a 3D combinatorial map, and you use \link CombinatorialMap::sew `sew<3>`\endlink between these two triangles. The two triangles are identified since all their darts are linked by \f$ \beta_3\f$, thus we obtain a 3D combinatorial map containing only one 3-cell. Note that this 3-cell is unbounded since the darts of the two triangles are all 2-free. In the 4D case, the 4-cell is unbounded since all its darts are 3-free.
By looking at these numbers of cells, we can see that the 4D combinatorial map contains only one 3-cell. Indeed, the \link BasicMap::sew `sew<4>`\endlink operation has identified by pairs all the darts of the two 3-cells by definition of the sew operation (see Section \ref sseclinkdarts "Sewing Orbits and Linking Darts") which, in 4D, links by \f$ \beta_3\f$ all the darts in \f$ \langle{}\f$\f$ \beta_1\f$,\f$ \beta_2\f$\f$ \rangle{}\f$(<I>d1</I>) and in \f$ \langle{}\f$\f$ \beta_1\f$,\f$ \beta_2\f$\f$ \rangle{}\f$(<I>d2</I>). The situation is similar (but in higher dimension) to the configuration where we have two triangles in a 3D combinatorial map, and you use \link BasicMap::sew `sew<3>`\endlink between these two triangles. The two triangles are identified since all their darts are linked by \f$ \beta_3\f$, thus we obtain a 3D combinatorial map containing only one 3-cell. Note that this 3-cell is unbounded since the darts of the two triangles are all 2-free. In the 4D case, the 4-cell is unbounded since all its darts are 3-free.
In this example, we also illustrate how to use the basic methods to build "by hand" some specific configuration in a combinatorial map. In fact, these functions are already present in the package: function `make_triangle(cm)` is equivalent to \link CombinatorialMap::make_combinatorial_polygon `cm.make_combinatorial_polygon(3)`\endlink and `make_tetrahedral(cm)` is equivalent to \link CombinatorialMap::make_combinatorial_tetrahedron `cm.make_combinatorial_tetrahedron()`\endlink. If we want to create a 4D simplex, we must create five 3D simplexes, and sew them correctly two by two by \f$ \beta_3\f$ (and so on if you want to create higher dimensional combinatorial map).
In this example, we also illustrate how to use the basic methods to build "by hand" some specific configuration in a combinatorial map. In fact, these functions are already present in the package: function `make_triangle(cm)` is equivalent to \link BasicMap::make_combinatorial_polygon `cm.make_combinatorial_polygon(3)`\endlink and `make_tetrahedral(cm)` is equivalent to \link BasicMap::make_combinatorial_tetrahedron `cm.make_combinatorial_tetrahedron()`\endlink. If we want to create a 4D simplex, we must create five 3D simplexes, and sew them correctly two by two by \f$ \beta_3\f$ (and so on if you want to create higher dimensional combinatorial map).
\cgalExample{Combinatorial_map/map_4_simple_example.cpp}
@ -473,9 +473,9 @@ The output is:
#Darts=64, #0-cells=13, #1-cells=24, #2-cells=14, #3-cells=2, #ccs=1, valid=1
\endverbatim
Before the `cm.`\link CombinatorialMap::sew `sew<3>`\endlink, each 2-cell of the first cube is associated with an attribute having 7 as value, and each 2-cell of the second cube with an attribute having 13 as value. During the `cm.`\link CombinatorialMap::sew `sew<3>`\endlink, two 2-cells are merged, thus the functor `Sum_functor` is called on the two associated 2-attributes, and the value of the new 2-cell is the sum of the two previous one: 20.
Before the `cm.`\link BasicMap::sew `sew<3>`\endlink, each 2-cell of the first cube is associated with an attribute having 7 as value, and each 2-cell of the second cube with an attribute having 13 as value. During the `cm.`\link BasicMap::sew `sew<3>`\endlink, two 2-cells are merged, thus the functor `Sum_functor` is called on the two associated 2-attributes, and the value of the new 2-cell is the sum of the two previous one: 20.
Then we call \link CombinatorialMap::insert_cell_0_in_cell_2 `insert_cell_0_in_cell_2`\endlink on a dart which belong to this 2-cell. This method splits the existing 2-cell in <I>k</I> 2-cells, <I>k</I> being the number of 1-cells of the initial 2-cell (4 in this example). These splits are made consecutively, thus for the first split, we create a new attribute as copy of the initial one and call functor `Divide_by_two_functor` on these two attributes: the value of each attribute is thus 20/2=10. For the second split, the value of each attribute is thus 10/2=5, and for the last split the value of each attribute is thus 5/2=2 (remember that information contained in 2-attributes in an `int`). At the end, we obtain five 2-attributes with 7 as value, five 2-attributes with 13 as value, and four 2-attributes having respectively 2, 2, 5 and 10 as values.
Then we call \link BasicMap::insert_cell_0_in_cell_2 `insert_cell_0_in_cell_2`\endlink on a dart which belong to this 2-cell. This method splits the existing 2-cell in <I>k</I> 2-cells, <I>k</I> being the number of 1-cells of the initial 2-cell (4 in this example). These splits are made consecutively, thus for the first split, we create a new attribute as copy of the initial one and call functor `Divide_by_two_functor` on these two attributes: the value of each attribute is thus 20/2=10. For the second split, the value of each attribute is thus 10/2=5, and for the last split the value of each attribute is thus 5/2=2 (remember that information contained in 2-attributes in an `int`). At the end, we obtain five 2-attributes with 7 as value, five 2-attributes with 13 as value, and four 2-attributes having respectively 2, 2, 5 and 10 as values.
\subsection sseccombimapdynamicattibute Use of Dynamic Onmerge and Onsplit Functors
@ -483,7 +483,7 @@ In the following example, we show an example of use of dynamic onmerge and onspl
Step 2 defines the onsplit and onmerge dynamic functors. We can see here that with this mechanism, functors can store data member. This is the case in the example for `Split_functor` which stores a reference to the combinatorial map.
The next operations will call these functors when 2-cells are split or merged. The \link CombinatorialMap::sew `sew<3>`\endlink operation calls 1 onmerge as two faces are identified; the \link CombinatorialMap::insert_cell_0_in_cell_2 `insert_cell_0_in_cell_2`\endlink operation calls 3 onsplit as one face is split in 4.
The next operations will call these functors when 2-cells are split or merged. The \link BasicMap::sew `sew<3>`\endlink operation calls 1 onmerge as two faces are identified; the \link BasicMap::insert_cell_0_in_cell_2 `insert_cell_0_in_cell_2`\endlink operation calls 3 onsplit as one face is split in 4.
Lastly we remove the dynamic onmerge functor (step 7). This is done by initializing the fonctor to a default boost::function. After this initialization, no dynamic merge functor is called when two faces are merged.

View File

@ -60,14 +60,14 @@ using Attribute_const_handle = unspecified_type;
/// @{
/*!
To simplify a future implementation, it is recommended to not use this function and to use \link BasicMap::attribute `cm.attribute(dh)`\endlink instead.
To simplify a future implementation, it is recommended to not use this function and to use \link BasicMap::attribute `bm.attribute(dh)`\endlink instead.
Returns a handle to the <I>i</I>-attribute associated to the dart.
\pre 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>dimension</I>, and <I>i</I>-attributes are non `void`.
*/
template <unsigned int i> Attribute_handle<i>::type attribute();
/*!
To simplify a future implementation, it is recommended to not use this function and to use \link BasicMap::attribute `cm.attribute(dh)`\endlink instead.
To simplify a future implementation, it is recommended to not use this function and to use \link BasicMap::attribute `bm.attribute(dh)`\endlink instead.
Returns a const handle to the <I>i</I>-attribute associated to the dart, when the dart is const.
\pre 0\f$ \leq\f$<I>i</I>\f$ \leq\f$<I>dimension</I>, and <I>i</I>-attributes are non `void`.
*/

View File

@ -2,13 +2,16 @@
\ingroup PkgCombinatorialMapsConcepts
\cgalConcept
The concept `BasicMap` defines a <I>d</I>-dimensional basic map. This concept is defined only to factorize the common notions between \link CGAL::Combinatorial_map `combinatorial maps`\endlink and \link CGAL::Generalized_map `generalized maps`\endlink classes.
The concept `BasicMap` defines a <I>d</I>-dimensional basic map. This concept is defined only to factorize the common notions between \link CombinatorialMap `CombinatorialMap`\endlink and \link GeneralizedMap `GeneralizedMap`\endlink concepts.
A basic map has a set of darts <I>D</I>, and applications defined on these darts \f$ f_0\f$,\f$ \ldots\f$,\f$ f_{d}\f$.
\cgalHasModel \link CGAL::Combinatorial_map `CGAL::Combinatorial_map<d,Items,Alloc>`\endlink
\cgalHasModel \link CGAL::Generalized_map `CGAL::Generalized_map<d,Items,Alloc>`\endlink
\sa `CombinatorialMap`
\sa `GeneralizedMap`
*/
class BasicMap {
@ -263,7 +266,7 @@ bool is_empty() const;
/*!
Returns true iff the basic map is valid.
See the following links for the definition of valid for \link CombinatorialMap `combinatorial maps` and for \link GeneralizedMap `generalized maps`.
See the following links for the definition of valid for \link CombinatorialMap `combinatorial maps`\endlink and for \link GeneralizedMap `generalized maps`\endlink.
*/
bool is_valid() const;
@ -325,6 +328,40 @@ Returns a const handle to a dart belonging to the other vertex of the edge conta
*/
Dart_const_handle other_extremity(Dart_const_handle dh) const;
/*!
Returns a handle to a dart belonging to the next edge after `*dh`, that does not belong to the same <I>0</I>-cell than `*dh` and that belongs to the same <I>i</I>-cell than `*dh`for each <I>i</I>, 2\f$ \leq\f$<I>i</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink.
*/
Dart_handle next(Dart_handle dh);
/*!
Returns a const handle to a dart belonging to the next edge after `*dh`, that does not belong to the same <I>0</I>-cell than `*dh` and that belongs to the same <I>i</I>-cell than `*dh`for each <I>i</I>, 2\f$ \leq\f$<I>i</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink.
*/
Dart_const_handle next(Dart_const_handle dh) const;
/*!
Returns a handle to a dart belonging to the previous edge begore `*dh`, that does not belong to the same <I>0</I>-cell than `*dh` and that belongs to the same <I>i</I>-cell than `*dh`for each <I>i</I>, 2\f$ \leq\f$<I>i</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink.
*/
Dart_handle previous(Dart_handle dh);
/*!
Returns a const handle to a dart belonging to the previous edge begore `*dh`, that does not belong to the same <I>0</I>-cell than `*dh` and that belongs to the same <I>i</I>-cell than `*dh`for each <I>i</I>, 2\f$ \leq\f$<I>i</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink.
*/
Dart_const_handle previous(Dart_const_handle dh) const;
/*!
Returns a handle to a dart belonging to the opposite <I>i</I>-cell than `*dh`. This dart does not belong to the same <I>0</I>-cell than `*dh`, nor to the same <I>i</I>-cell, but belongs to the same <I>i</I>-cell than `*dh`for each <I>j</I>, 2\f$ \leq\f$<I>j</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink, <I>j</I>\f$ \neq\f$<I>i</I>.
\pre 2\f$ \leq\f$<I>i</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink.
*/
template<unsigned int i>
Dart_handle opposite(Dart_handle dh);
/*!
Returns a const handle to a dart belonging to the opposite <I>i</I>-cell than `*dh`. This dart does not belong to the same <I>0</I>-cell than `*dh`, nor to the same <I>i</I>-cell, but belongs to the same <I>i</I>-cell than `*dh`for each <I>j</I>, 2\f$ \leq\f$<I>j</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink, <I>j</I>\f$ \neq\f$<I>i</I>.
\pre 2\f$ \leq\f$<I>i</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink.
*/
template<unsigned int i>
Dart_const_handle opposite(Dart_const_handle dh) const;
/*!
Displays on `os` the number of elements of the basic map.
Its number of darts,
@ -472,8 +509,7 @@ template<unsigned int i> Attribute_const_range<i>::type & attributes() const;
Returns a range of all the darts of the orbit `<I...>(*dh)`.
The first element in the range points onto `*dh`.
\pre `*dh`\f$ \in\f$`darts()` and `I...` is a sequence of integers \f$ i_1\f$,\f$ \ldots\f$,\f$ i_k\f$,
such that 0\f$ \leq\f$\f$ i_1\f$\f$ <\f$\f$ i_2\f$\f$ <\f$\f$ \ldots\f$\f$ <\f$\f$ i_k\f$\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink,
and (\f$ i_1\f$\f$ \neq\f$ 0 or \f$ i_2\f$\f$ \neq\f$ 1).
such that 0\f$ \leq\f$\f$ i_1\f$\f$ <\f$\f$ i_2\f$\f$ <\f$\f$ \ldots\f$\f$ <\f$\f$ i_k\f$\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink.
*/
template<unsigned int ... I> Dart_of_orbit_range darts_of_orbit(Dart_handle dh);
@ -646,15 +682,15 @@ void correct_invalid_attributes();
/*!
Returns true iff `*dh1` can be <I>i</I>-sewn with `*dh2` by keeping the basic map valid.
See the following links for the definition of is_sewable for \link CombinatorialMap `combinatorial maps` and for \link GeneralizedMap `generalized maps`.
\pre 0\f$ \leq\f$<I>i</I>\f$ \leq\f$\link CombinatorialMap::dimension `dimension`\endlink,
See the following links for the definition of is_sewable for \link CombinatorialMap `combinatorial maps`\endlink and for \link GeneralizedMap `generalized maps`\endlink.
\pre 0\f$ \leq\f$<I>i</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink,
`*dh1`\f$ \in\f$`darts()`, and `*dh2`\f$ \in\f$`darts()`.
*/
template <unsigned int i> bool is_sewable(Dart_const_handle dh1, Dart_const_handle dh2) const;
/*!
<I>i</I>-sew darts `*dh1` and `*dh2`, by keeping the basic map valid.
See the following links for the definition of the <I>i</I>-sew for \link CombinatorialMap `combinatorial maps` and for \link GeneralizedMap `generalized maps`.
See the following links for the definition of the <I>i</I>-sew for \link CombinatorialMap `combinatorial maps`\endlink and for \link GeneralizedMap `generalized maps`\endlink.
If \link BasicMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, when necessary, non void attributes are updated to ensure the validity of the basic map: for each <I>j</I>-cells <I>c1</I> and <I>c2</I> which are merged into one <I>j</I>-cell during the sew, the two associated attributes <I>attr1</I> and <I>attr2</I> are considered. If one attribute is NULL and the other not, the non NULL attribute is associated to all the darts of the resulting cell. When the two attributes are non NULL, functor \link CellAttribute::On_merge `Attribute_type<i>::type::On_merge`\endlink is called on the two attributes <I>attr1</I> and <I>attr2</I>. If set, the dynamic onmerge function of <i>i</i>-attributes is also called on <I>attr1</I> and <I>attr2</I>. Then, the attribute <I>attr1</I> is associated to all darts of the resulting <I>j</I>-cell. Finally, attribute <I>attr2</I> is removed from the basic map.
\pre \link BasicMap::is_sewable `is_sewable<i>(dh1,dh2)`\endlink.
@ -667,8 +703,8 @@ If \link BasicMap::are_attributes_automatically_managed `are_attributes_automati
template <unsigned int i> void sew(Dart_handle dh1,Dart_handle dh2);
/*!
<I>i</I>-unsew darts `*dh` and \f$ \beta_i\f$`(*dh)`, by keeping the basic map valid.
See the following links for the definition of is_sewable for \link CombinatorialMap `combinatorial maps` and for \link GeneralizedMap `generalized maps`.
<I>i</I>-unsew darts `*dh` and `*opposite<i>(*dh)`, by keeping the basic map valid.
See the following links for the definition of is_sewable for \link CombinatorialMap `combinatorial maps`\endlink and for \link GeneralizedMap `generalized maps`\endlink.
If \link BasicMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, when necessary, non void attributes are updated to ensure the validity of the basic map: for each <I>j</I>-cell <I>c</I> split in two <I>j</I>-cells <I>c1</I> and <I>c2</I> by the operation, if <I>c</I> is associated to a <I>j</I>-attribute <I>attr1</I>, then this attribute is duplicated into <I>attr2</I>, and all the darts belonging to <I>c2</I> are associated with this new attribute. Finally, the functor \link CellAttribute::On_split `Attribute_type<i>::type::On_split`\endlink is called on the two attributes <I>attr1</I> and <I>attr2</I>. If set, the dynamic onsplit function of <i>i</i>-attributes is also called on <I>attr1</I> and <I>attr2</I>.
\pre 0\f$ \leq\f$<I>i</I>\f$ \leq\f$\link BasicMap::dimension `dimension`\endlink, `*dh`\f$ \in\f$`darts()` and `*dh` is not <I>i</I>-free.
@ -841,7 +877,7 @@ Dart_handle make_edge();
/// @{
/*!
Inserts a 0-cell in the 1-cell containing `dh`. Returns \f$ \beta_1\f$(`dh`), a handle on one dart belonging to the new 0-cell.
Inserts a 0-cell in the 1-cell containing `dh`. Returns `next(dh)`, a handle on one dart belonging to the new 0-cell.
\pre \link BasicMap::dimension `dimension`\endlink \f$ \geq\f$ 1 and `*dh`\f$ \in\f$\link BasicMap::darts `darts()`\endlink.
See examples for combinatorial map in \cgalFigureRef{fig_cmap_insert_vertex} and for generalized map in \cgalFigureRef{fig_gmap_insert_vertex}.
@ -881,7 +917,7 @@ If \link BasicMap::are_attributes_automatically_managed `are_attributes_automati
Dart_handle insert_cell_0_in_cell_2(Dart_handle dh);
/*!
Inserts a 1-cell in the 2-cell containing `dh1` and `dh2`. Returns \f$ \beta_0\f$(`dh1`), a handle on one dart belonging to the new 1-cell.
Inserts a 1-cell in the 2-cell containing `dh1` and `dh2`. Returns `previous(dh1)`, a handle on one dart belonging to the new 1-cell.
\pre `is_insertable_cell_1_in_cell_2(dh1,dh2)`.
See examples for combinatorial map in \cgalFigureRef{fig_cmap_insert_edge} and for generalized map in \cgalFigureRef{fig_gmap_insert_edge}.
@ -902,7 +938,7 @@ If \link BasicMap::are_attributes_automatically_managed `are_attributes_automati
Dart_handle insert_cell_1_in_cell_2(Dart_handle dh1, Dart_handle dh2);
/*!
Inserts a 2-cell along the path of 1-cells containing darts given by the range `[afirst,alast)`. Returns \f$ \beta_2\f$(`*afirst`), a handle on one dart belonging to the new 2-cell.
Inserts a 2-cell along the path of 1-cells containing darts given by the range `[afirst,alast)`. Returns `opposite<2>(*afirst)`, a handle on one dart belonging to the new 2-cell.
\pre `is_insertable_cell_2_in_cell_3(afirst,alast)`.
See examples for combinatorial map in \cgalFigureRef{fig_cmap_insert_facet} and for generalized map in \cgalFigureRef{fig_gmap_insert_facet}.
@ -924,10 +960,10 @@ template <class InputIterator>
Dart_handle insert_cell_2_in_cell_3(InputIterator afirst, InputIterator alast);
/*!
Inserts a 1-cell in a the 2-cell containing `dh`, the 1-cell being attached only by one of its extremity to the 0-cell containing `dh`. Returns \f$ \beta_0\f$(`dh`), a handle on the dart belonging to the new 1-cell and to the new 0-cell.
Inserts a 1-cell in a the 2-cell containing `dh`, the 1-cell being attached only by one of its extremity to the 0-cell containing `dh`. Returns `previous(dh)`, a handle on the dart belonging to the new 1-cell and to the new 0-cell.
\pre \link BasicMap::dimension `dimension`\endlink \f$ \geq\f$ 2 and `*dh`\f$ \in\f$\link BasicMap::darts `darts()`\endlink.
See example in \cgalFigureRef{fig_cmap_insert_edge}.
See examples for combinatorial map in \cgalFigureRef{fig_cmap_insert_edge} and for generalized map in \cgalFigureRef{fig_gmap_insert_edge}.
\cgalAdvancedBegin
If \link BasicMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==false`, non void attributes are not updated; thus the basic map can be no more valid after this operation.
@ -945,7 +981,7 @@ Dart_handle insert_dangling_cell_1_in_cell_2(Dart_handle dh);
/*!
Returns true iff it is possible to insert a 1-cell in the basic map between `dh1` and `dh2`.
This is possible if `dh1`\f$ \neq\f$`dh2` and `dh1`\f$ \in\f$\f$ \langle{}\f$\f$ \beta_1\f$\f$ \rangle{}\f$(`dh2`).
This is possible if `dh1`\f$ \neq\f$`dh2` and `dh1` can be reached from `dh2` by using some `previous` and `next` calls.
\pre \link BasicMap::dimension `dimension`\endlink \f$ \geq\f$ 2, `*dh1`\f$ \in\f$\link BasicMap::darts `darts()`\endlink, and `*dh2`\f$ \in\f$\link BasicMap::darts `darts()`\endlink.
\sa `insert_cell_1_in_cell_2`
@ -955,7 +991,7 @@ This is possible if `dh1`\f$ \neq\f$`dh2` and `dh1`\f$ \in\f$\f$ \langle{}\f$\f$
bool is_insertable_cell_1_in_cell_2(Dart_const_handle dh1, Dart_const_handle dh2);
/*!
Returns true iff it is possible to insert a 2-cell in the basic map along the path of darts given by the range `[afirst,alast)`. The 2-cell can be inserted iff each couple of consecutive darts of the path <I>a1</I> and <I>a2</I> belong to the same vertex and the same volume, and if the path is closed.
Returns true iff it is possible to insert a 2-cell in the basic map along the path of darts given by the range `[afirst,alast)`. The 2-cell can be inserted iff the ordered list of darts form a closed path of edges inside a same volume.
\pre \link BasicMap::dimension `dimension`\endlink \f$ \geq\f$ 3.
\sa `insert_cell_2_in_cell_3<InputIterator>`

View File

@ -31,8 +31,8 @@ The concept `BasicMapItems` allows to customize a <I>d</I>D basic map by choosin
template < class GMap >
struct Dart_wrapper
{
typedef CGAL::GMap_dart<3, CMap> Dart;
typedef CGAL::Cell_attribute<CMap, int> Edge_attrib;
typedef CGAL::GMap_dart<3, GMap> Dart;
typedef CGAL::Cell_attribute<GMap, int> Edge_attrib;
typedef CGAL::cpp11::tuple<void,Edge_attrib> Attributes;
};
};

View File

@ -4,11 +4,17 @@
The concept `CombinatorialMap` defines a <I>d</I>-dimensional combinatorial map.
\cgalRefines `BasicMap`
\cgalHasModel \link CGAL::Combinatorial_map `CGAL::Combinatorial_map<d,Items,Alloc>`\endlink
\cgalHeading{Basic functions}
For a combinatorial map, the function \link BasicMap::next `next`\endlink is equal to \f$ \beta_1\f$, \link BasicMap::previous `previous`\endlink is equal to \f$ \beta_0\f$ and the function \link BasicMap::opposite `opposite<i>`\endlink is equal to \f$ \beta_i\f$.
\cgalHeading{Validity}
The function \link BasicMap::is_valid `is_valid` return true iff the combinatorial map is valid.
The function \link BasicMap::is_valid `is_valid`\endlink returns true iff the combinatorial map is valid.
A combinatorial map is valid (see Sections \ref sseccombimapanddarts and \ref sseccombimapvalidity) if for all its darts `d` \f$\in\f$`darts()`:
- `d` is 0-free, or \f$ \beta_1(\beta_0(d))=d\f$;
@ -20,18 +26,17 @@ A combinatorial map is valid (see Sections \ref sseccombimapanddarts and \ref ss
+ \f$ \forall\f$<I>d2</I> in the same <I>i</I>-cell than <I>d</I>: <I>d</I> and <I>d2</I> have the same <I>i</I>-attribute;
+ \f$ \forall\f$<I>d2</I> in a different <I>i</I>-cell than <I>d</I>: <I>d</I> and <I>d2</I> have different <I>i</I>-attributes.
\cgalHeading{Sew and unsew}
The function \link BasicMap::is_sewable `is_sewable` returns true iff `*dh1` can be <I>i</I>-sewn with `*dh2` by keeping the basic map valid.
The function \link BasicMap::is_sewable `is_sewable`\endlink returns true iff `*dh1` can be <I>i</I>-sewn with `*dh2` by keeping the combinatorial map valid.
This is true if there is a bijection <I>f</I> between all the darts of the orbit <I>D1</I>=\f$ \langle{}\f$\f$ \beta_1\f$,\f$ \ldots\f$,\f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,\f$ \ldots\f$,\f$ \beta_d\f$\f$ \rangle{}\f$(<I>*dh1</I>) and <I>D2</I>=\f$ \langle{}\f$\f$ \beta_1\f$,\f$ \ldots\f$,\f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,\f$ \ldots\f$,\f$ \beta_d\f$\f$ \rangle{}\f$(<I>*dh2</I>) satisfying: <I>f</I>(<I>*dh1</I>)=<I>*dh2</I>, and for all <I>e</I>\f$ \in\f$<I>D1</I>, for all <I>j</I>\f$ \in\f${1,\f$ \ldots\f$,<I>i</I>-2,<I>i</I>+2,\f$ \ldots\f$,<I>d</I>}, <I>f</I>(\f$ \beta_j\f$(<I>e</I>))=\f$ \beta_j^{-1}\f$(<I>f</I>(<I>e</I>)).
The function \link BasicMap::sew `sew` <I>i</I>-sew darts `*dh1` and `*dh2`, by keeping the combinatorial map valid.
The function \link BasicMap::sew `sew`\endlink <I>i</I>-sew darts `*dh1` and `*dh2`, by keeping the combinatorial map valid.
Links by \f$ \beta_i\f$ two by two all the darts of the orbit <I>D1</I>=\f$ \langle{}\f$\f$ \beta_1\f$,\f$ \ldots\f$,\f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,\f$ \ldots\f$,\f$ \beta_d\f$\f$ \rangle{}\f$(`*dh1`) and <I>D2</I>=\f$ \langle{}\f$\f$ \beta_0\f$,\f$ \beta_2\f$,\f$ \ldots\f$,\f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,\f$ \ldots\f$,\f$ \beta_d\f$\f$ \rangle{}\f$(`*dh2`) such that <I>d2</I>=<I>f</I>(<I>d1</I>).
<I>f</I> is the bijection between <I>D1</I> and <I>D2</I> satisfying: <I>f</I>(<I>*dh1</I>)=<I>*dh2</I>, and for all <I>e</I>\f$ \in\f$<I>D1</I>, for all <I>j</I>\f$ \in\f${1,\f$ \ldots\f$,<I>i</I>-2,<I>i</I>+2,\f$ \ldots\f$,<I>d</I>}, <I>f</I>(\f$ \beta_j\f$(<I>e</I>))=\f$ \beta_j^{-1}\f$(<I>f</I>(<I>e</I>)).
The function \link BasicMap::unsew `unsew` <I>i</I>-unsew darts `*dh` and \f$ \beta_i\f$`(*dh)`, by keeping the combinatorial map valid.
The function \link BasicMap::unsew `unsew`\endlink <I>i</I>-unsew darts `*dh` and \f$ \beta_i\f$`(*dh)`, by keeping the combinatorial map valid.
Unlinks by \f$ \beta_i\f$ all the darts in the orbit \f$ \langle{}\f$\f$ \beta_1\f$,\f$ \ldots\f$,\f$ \beta_{i-2}\f$,\f$ \beta_{i+2}\f$,\f$ \ldots\f$,\f$ \beta_d\f$\f$ \rangle{}\f$(`*dh`).
*/

View File

@ -42,10 +42,11 @@
\cgalClassifedRefPages
## Concepts ##
- `CombinatorialMap`
- `Dart`
- `BasicDart`
- `BasicMap`
- `BasicMapItems`
- `CellAttribute`
- `CombinatorialMapItems`
- `CombinatorialMap`
## Classes ##
- `CGAL::Combinatorial_map<d,Items,Alloc>`