diff --git a/Combinatorial_map/doc/Combinatorial_map/Combinatorial_map.txt b/Combinatorial_map/doc/Combinatorial_map/Combinatorial_map.txt
index ed3c60b63b5..2867dc1c2f7 100644
--- a/Combinatorial_map/doc/Combinatorial_map/Combinatorial_map.txt
+++ b/Combinatorial_map/doc/Combinatorial_map/Combinatorial_map.txt
@@ -168,7 +168,7 @@ Considering these different advantages and drawbacks, you can choose to use gene
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 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 information associated with darts and the attribute types. These types may be different for different dimensions, and they may also be void (note that the main concepts of `GenericMap`, `GenericMapItems` and `CellAttribute` are shared between combinatorial maps and generalized maps).
-The darts and attributes are accessed through descriptors (either Indices or Handles). 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 `std::unordered_map`. An index is a model of the `Index` concept, which is mainly an integer which is convertible from and to std::size_t. Indices can be used as index into vectors which store properties (cf. one example in Section \ref ssecexample3DCMWI "3D Combinatorial Map using Indices").
+The darts and attributes are accessed through descriptors (either Indices or Handles). 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 `std::unordered_map`. An index is a model of the `Index` concept, which is mainly an integer which is convertible from and to std::size_t. Indices can be used as index into vectors which store properties (cf. one example in Section \ref ssecexample3DCMWI "3D Combinatorial Map Using Indices").
\cgalFigureBegin{fig_cmap_diagramme_class,cmap_diagramme_class.svg}
UML diagram of the main classes of the package. k is the number of non void attributes.
@@ -393,6 +393,8 @@ Example of \link GenericMap::insert_cell_1_in_cell_2 `insert_cell_1_in_cell_2`\e
`cm.`\link GenericMap::insert_dangling_cell_1_in_cell_2 `insert_dangling_cell_1_in_cell_2(d0)`\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 GenericMap::darts `cm.darts()`\endlink.
+`cm.`\link GenericMap::insert_cell_1_between_two_cells_2 `insert_cell_1_between_two_cells_2(d1,d2)`\endlink adds a 1-cell between the two faces containing containing darts `d1` and `d2`, between the two 0-cells containing darts `d1` and `d2`. The 2-cells are merged in one. This operation is possible if d1\f$ \not \in \f$ \f$ \langle{}\f$\f$ \beta_1\f$\f$ \rangle{}\f$(d2) which can be tested thanks to `cm.`\link GenericMap::is_insertable_cell_1_between_two_cells_2 `is_insertable_cell_1_between_two_cells_2(d1,d2)`\endlink.
+
`cm.`\link GenericMap::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 GenericMap::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}
@@ -456,6 +458,24 @@ 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_mapInsertion Insert an Edge Between Two Different Faces
+
+\anchor ssecexempleinsertion
+
+This example shows the use of \link GenericMap::insert_cell_1_between_two_cells_2 `insert_cell_1_between_two_cells_2`\endlink operation. First we create a combinatorial hexahedron and a face with 4 edges. This face is inserted in the face of the hexahedron containing dart d1. We display the characteristics of the combinatorial map and check its validity. Then we count and display the number of 2-free darts.
+
+\cgalExample{Combinatorial_map/map_3_insert.cpp}
+
+The output is:
+\verbatim
+#Darts=30, #0-cells=12, #1-cells=17, #2-cells=6, #3-cells=1, #ccs=1, valid=1
+Number of 2-free darts: 4
+\endverbatim
+
+We can verify that there are 6 2-cells after the insertion since the squared face was inserted as a hole in one face of the hexahedron. We can also see that there are 4 2-free darts, which are the darts of the squared face. Since they bound an hole, there is no face filling the hole and thus 4 darts are 2-free.
+
+See also a similar example for Linear cell complex \ref Linear_cell_complexInsert "Insert an Edge Between Two Different Faces".
+
\subsection Combinatorial_mapA4DGenericMap 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.
@@ -502,7 +522,7 @@ Lastly we remove the dynamic onmerge functor (step 7). This is done by initializ
\cgalExample{Combinatorial_map/map_3_dynamic_onmerge.cpp}
-\subsection ssecexample3DCMWI 3D Combinatorial Map using Indices
+\subsection ssecexample3DCMWI 3D Combinatorial Map Using Indices
In this example, a 3-dimensional combinatorial map is used, but using indices instead of handles. Two vectors are created to store some external information associated with darts and 3-attributes. Since descriptors are indices, they can directly be used to access elements of the vector.
diff --git a/Combinatorial_map/doc/Combinatorial_map/Concepts/GenericMap.h b/Combinatorial_map/doc/Combinatorial_map/Concepts/GenericMap.h
index ae828e3cdf0..2439a614f03 100644
--- a/Combinatorial_map/doc/Combinatorial_map/Concepts/GenericMap.h
+++ b/Combinatorial_map/doc/Combinatorial_map/Concepts/GenericMap.h
@@ -267,12 +267,12 @@ using One_dart_per_cell_const_range = unspecified_type;
/// @{
/*!
-Returns true iff the generic map is empty, i.e.\ it contains no dart.
+Returns `true` iff the generic map is empty, i.e.\ it contains no dart.
*/
bool is_empty() const;
/*!
-Returns true iff the generic map is without i-boundary.
+Returns `true` iff the generic map is without i-boundary.
The map is without i-boundary if there is no `i`-free dart.
\pre 1\f$ \leq \f$ i \f$ \leq \f$ \link GenericMap::dimension `dimension`\endlink.
@@ -280,7 +280,7 @@ The map is without i-boundary if there is no `i`-free dart.
bool is_without_boundary(unsigned int i) const;
/*!
-Returns true iff the generic map is without boundary in all dimensions.
+Returns `true` iff the generic map is without boundary in all dimensions.
*/
bool is_without_boundary() const;
@@ -308,18 +308,18 @@ Returns an upper bound of the id of i-attributes descriptors if indices a
template
size_type upper_bound_on_attribute_ids() const;
-/*! Returns true if `d` is a descriptor of a used dart (i.e.\ valid).
+/*! Returns `true` if `d` is a descriptor of a used dart (i.e.\ valid).
*/
bool is_dart_used(Dart_const_descriptor d) const;
/*!
-Returns true iff dart `d` is i-free.
+Returns `true` iff dart `d` is i-free.
\pre 0 \f$ \leq \f$ i \f$ \leq \f$ \link GenericMap::dimension `dimension`\endlink.
*/
bool is_free(Dart_const_descriptor d, unsigned int i) const;
/*!
-Returns true iff dart `d` is i-free.
+Returns `true` iff dart `d` is i-free.
\pre 0 \f$ \leq \f$ i \f$ \leq \f$ \link GenericMap::dimension `dimension`\endlink.
*/
template
@@ -477,7 +477,7 @@ A shortcut for \link GenericMap::dart_of_attribute(typename Attribute_const_desc
template
Dart_const_descriptor dart(Dart_const_descriptor adart) const;
-/*! Returns true if ah points to a used i-attribute (i.e.\ valid).
+/*! Returns `true` if ah points to a used i-attribute (i.e.\ valid).
\pre 0 \f$ \leq \f$ i \f$ \leq \f$ \link GenericMap::dimension `dimension`\endlink, and i-attributes are non `void`.
*/
template
@@ -703,13 +703,13 @@ void correct_invalid_attributes();
/// \cond SKIP_IN_MANUAL boost::function \endcond
-/// \name Dynamic Onmerge/Onsplit functors
+/// \name Dynamic On-Merge/On-Split functors
/// @{
/*!
- Return the current dynamic onsplit function associated with i-attributes.
+ Return the current dynamic on-split function associated with i-attributes.
This is a boost::function returning void and having two references to \link GenericMap::Attribute_type `Attribute_type::type`\endlink as parameters.
- The onsplit function is returned by reference so that we can modify it.
+ The on-split function is returned by reference so that we can modify it.
*/
template
boost::function::type&,
@@ -717,7 +717,7 @@ void correct_invalid_attributes();
onsplit_function();
/*!
- Return the current dynamic onsplit function associated with i-attributes, when *this is const.
+ Return the current dynamic on-split function associated with i-attributes, when *this is const.
This is a boost::function returning void and having two references to \link GenericMap::Attribute_type `Attribute_type::type`\endlink as parameters.
*/
template
@@ -726,9 +726,9 @@ void correct_invalid_attributes();
onsplit_function() const;
/*!
- Return the current dynamic onmerge function associated with i-attributes.
+ Return the current dynamic on-merge function associated with i-attributes.
This is a boost::function returning void and having two references to \link GenericMap::Attribute_type `Attribute_type::type`\endlink as parameters.
- The onmerge function is returned by reference so that we can modify it.
+ The on-merge function is returned by reference so that we can modify it.
*/
template
boost::function::type&,
@@ -736,7 +736,7 @@ void correct_invalid_attributes();
onmerge_function();
/*!
- Return the current dynamic onmerge function associated with i-attributes, when *this is const.
+ Return the current dynamic on-merge function associated with i-attributes, when *this is const.
This is a boost::function returning void and having two references to \link GenericMap::Attribute_type `Attribute_type::type`\endlink as parameters.
*/
template
@@ -756,13 +756,13 @@ index. If there is no more available free mark, throw the exception Exception_no
size_type get_new_mark() const;
/*!
-Returns true iff `m` is a reserved mark of the generic map.
+Returns `true` iff `m` is a reserved mark of the generic map.
\pre 0\f$ \leq \f$ m \f$ < \f$ \link GenericMap::NB_MARKS `NB_MARKS`\endlink.
*/
bool is_reserved(size_type m) const;
/*!
-Returns true iff dart `d` is marked for `m`.
+Returns `true` iff dart `d` is marked for `m`.
\pre \link GenericMap::is_reserved `is_reserved(m)`\endlink and `d`\f$ \in \f$ `darts()`.
*/
bool is_marked(Dart_const_descriptor d, size_type m) const;
@@ -820,9 +820,9 @@ void free_mark(size_type m) const;
Creates a combinatorial hexahedron (six combinatorial quadrangles 2-sewn together), and adds it in the generic map. Returns a descriptor on one dart of this combinatorial hexahedron.
\pre `dimension` \f$\geq\f$ 2.
-\sa `make_edge`
-\sa `make_combinatorial_polygon`
-\sa `make_combinatorial_tetrahedron`
+\sa `make_edge()`
+\sa `make_combinatorial_polygon()`
+\sa `make_combinatorial_tetrahedron()`
*/
Dart_descriptor make_combinatorial_hexahedron();
@@ -831,9 +831,9 @@ Dart_descriptor make_combinatorial_hexahedron();
Creates a combinatorial polygon of length `lg` (a cycle of `lg` edges), and adds it in the generic map. Returns a descriptor on one dart of this combinatorial polygon.
\pre `dimension`\f$ \geq\f$ 1 and `lg`\f$ >\f$ 0.
-\sa `make_edge`
-\sa `make_combinatorial_tetrahedron`
-\sa `make_combinatorial_hexahedron`
+\sa `make_edge()`
+\sa `make_combinatorial_tetrahedron()`
+\sa `make_combinatorial_hexahedron()`
*/
Dart_descriptor make_combinatorial_polygon(unsigned int lg);
@@ -841,9 +841,9 @@ Dart_descriptor make_combinatorial_polygon(unsigned int lg);
Creates a combinatorial tetrahedron (four combinatorial triangles 2-sewn together), and adds it in the generic map. Returns a descriptor on one dart of this combinatorial tetrahedron.
\pre `dimension`\f$ \geq\f$ 2.
-\sa `make_edge`
-\sa `make_combinatorial_polygon`
-\sa `make_combinatorial_hexahedron`
+\sa `make_edge()`
+\sa `make_combinatorial_polygon()`
+\sa `make_combinatorial_hexahedron()`
*/
Dart_descriptor make_combinatorial_tetrahedron();
@@ -851,9 +851,9 @@ Dart_descriptor make_combinatorial_tetrahedron();
Creates an isolated edge (two darts sewn to represent one edge and two vertices) and adds it in the generic map. Returns a descriptor on one dart of this edge.
\pre `dimension`\f$ \geq\f$ 2.
-\sa `make_combinatorial_polygon`
-\sa `make_combinatorial_tetrahedron`
-\sa `make_combinatorial_hexahedron`
+\sa `make_combinatorial_polygon()`
+\sa `make_combinatorial_tetrahedron()`
+\sa `make_combinatorial_hexahedron()`
*/
Dart_descriptor make_edge();
@@ -868,17 +868,18 @@ Inserts a 0-cell in the 1-cell containing `d`. Returns `next(d)`, a descriptor o
See examples for combinatorial map in \cgalFigureRef{fig_cmap_insert_vertex} and for generalized map in \cgalFigureRef{fig_gmap_insert_vertex}.
-If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if 1-attributes are non `void`, \link CellAttribute::On_split `Attribute_type<1>::type::On_split`\endlink(a,a') is called, with a the original 1-attribute associated with d and a' the new 1-attribute created during the operation. If set, the dynamic onsplit function of 1-attributes is also called on a and a'.
+If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if 1-attributes are non `void`, \link CellAttribute::On_split `Attribute_type<1>::type::On_split`\endlink(a,a') is called, with a the original 1-attribute associated with d and a' the new 1-attribute created during the operation. If set, the dynamic on-split function of 1-attributes is also called on a and a'.
\cgalAdvancedBegin
If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==false`, non void attributes are not updated; thus the generic map can be no more valid after this operation.
\cgalAdvancedEnd
-\sa `insert_cell_0_in_cell_2`
-\sa `insert_cell_1_in_cell_2`
-\sa `insert_dangling_cell_1_in_cell_2`
-\sa `insert_cell_2_in_cell_3`
-\sa `remove_cell`
+\sa `insert_cell_0_in_cell_2()`
+\sa `insert_cell_1_in_cell_2()`
+\sa `insert_cell_1_between_two_cells_2()`
+\sa `insert_dangling_cell_1_in_cell_2()`
+\sa `insert_cell_2_in_cell_3()`
+\sa `remove_cell()`
*/
Dart_descriptor insert_cell_0_in_cell_1(Dart_descriptor d);
@@ -888,17 +889,18 @@ Inserts a 0-cell in the 2-cell containing `d`. The 2-cell is split in triangles,
See examples for combinatorial map in \cgalFigureRef{fig_cmap_triangulation} and for generalized map in \cgalFigureRef{fig_gmap_triangulation}.
-If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if 2-attributes are non `void`, \link CellAttribute::On_split `Attribute_type<2>::type::On_split`\endlink(a,a') is called, with a the original 2-attribute associated with `d` and a' each new 2-attribute created during the operation. If set, the dynamic onsplit function of 2-attributes is also called on a and a'.
+If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if 2-attributes are non `void`, \link CellAttribute::On_split `Attribute_type<2>::type::On_split`\endlink(a,a') is called, with a the original 2-attribute associated with `d` and a' each new 2-attribute created during the operation. If set, the dynamic on-split function of 2-attributes is also called on a and a'.
\cgalAdvancedBegin
If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==false`, non void attributes are not updated; thus the generic map can be no more valid after this operation.
\cgalAdvancedEnd
-\sa `insert_cell_0_in_cell_2`
-\sa `insert_cell_1_in_cell_2`
-\sa `insert_dangling_cell_1_in_cell_2`
-\sa `insert_cell_2_in_cell_3`
-\sa `remove_cell`
+\sa `insert_cell_0_in_cell_2()`
+\sa `insert_cell_1_in_cell_2()`
+\sa `insert_cell_1_between_two_cells_2()`
+\sa `insert_dangling_cell_1_in_cell_2()`
+\sa `insert_cell_2_in_cell_3()`
+\sa `remove_cell()`
*/
Dart_descriptor insert_cell_0_in_cell_2(Dart_descriptor d);
@@ -908,39 +910,68 @@ Inserts a 1-cell in the 2-cell containing `d1` and `d2`. Returns `previous(d1)`,
See examples for combinatorial map in \cgalFigureRef{fig_cmap_insert_edge} and for generalized map in \cgalFigureRef{fig_gmap_insert_edge}.
-If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if 2-attributes are non `void`, \link CellAttribute::On_split `Attribute_type<2>::type::On_split`\endlink(a,a') is called, with a the original 2-attribute associated with `d` and a' the new 2-attribute created during the operation. If set, the dynamic onsplit function of 2-attributes is also called on a and a'.
+If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if 2-attributes are non `void`, \link CellAttribute::On_split `Attribute_type<2>::type::On_split`\endlink(a,a') is called, with a the original 2-attribute associated with `d1` and a' the new 2-attribute created during the operation. If set, the dynamic on-split function of 2-attributes is also called on a and a'.
\cgalAdvancedBegin
If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==false`, non void attributes are not updated; thus the generic map can be no more valid after this operation.
\cgalAdvancedEnd
-\sa `is_insertable_cell_1_in_cell_2`
-\sa `insert_cell_0_in_cell_1`
-\sa `insert_cell_0_in_cell_2`
-\sa `insert_dangling_cell_1_in_cell_2`
-\sa `insert_cell_2_in_cell_3`
-\sa `remove_cell`
+\sa `is_insertable_cell_1_in_cell_2()`
+\sa `insert_cell_0_in_cell_1()`
+\sa `insert_cell_0_in_cell_2()`
+\sa `insert_cell_1_between_two_cells_2()`
+\sa `insert_dangling_cell_1_in_cell_2()`
+\sa `insert_cell_2_in_cell_3()`
+\sa `remove_cell()`
*/
Dart_descriptor insert_cell_1_in_cell_2(Dart_descriptor d1, Dart_descriptor d2);
+/*!
+Inserts a 1-cell between the 2-cell containing `d1` and the one containing `d2`. Returns `previous(d1)`, a descriptor on one dart belonging to the new 1-cell.
+\pre `is_insertable_cell_1_between_two_cells_2(d1,d2)`.
+
+If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, call \link CellAttribute::On_merge `Attribute_type::type::On_merge`\endlink(a,a') is called for all enabled i-attributes, for i>=2, with a the original 2-attribute associated with `d1` and a' the original 2-attribute associated with `d2`. If set, the dynamic on-merge function of i-attributes is also called on a and a'.
+
+\cgalAdvancedBegin
+If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==false`, non void attributes are not updated; thus the generic map can be no more valid after this operation.
+\cgalAdvancedEnd
+
+\sa `is_insertable_cell_1_between_two_cells_2()`
+\sa `insert_cell_0_in_cell_1()`
+\sa `insert_cell_0_in_cell_2()`
+\sa `insert_cell_1_in_cell_2()`
+\sa `insert_dangling_cell_1_in_cell_2()`
+\sa `insert_cell_2_in_cell_3()`
+\sa `remove_cell()`
+*/
+Dart_descriptor insert_cell_1_between_two_cells_2(Dart_descriptor d1, Dart_descriptor d2);
+
+/*! Call `insert_cell_1_in_cell_2()` if `is_insertable_cell_1_in_cell_2(d1, d2)`, otherwise call `insert_cell_1_between_two_cells_2()`.
+\sa `insert_cell_1_in_cell_2()`
+\sa `insert_cell_1_between_two_cells_2()`
+\sa `is_insertable_cell_1_in_cell_2()`
+*/
+Dart_descriptor insert_cell_1(Dart_descriptor d1, Dart_descriptor d2);
+
/*!
Inserts a 2-cell along the path of 1-cells containing darts given by the range `[afirst,alast)`. Returns `opposite<2>(*afirst)`, a descriptor 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}.
-If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if 3-attributes are non `void`, \link CellAttribute::On_split `Attribute_type<3>::type::On_split`\endlink(a,a') is called, with a the original 3-attribute associated with `d` and a' the new 3-attribute created during the operation. If set, the dynamic onsplit function of 3-attributes is also called on a and a'.
+If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if 3-attributes are non `void`, \link CellAttribute::On_split `Attribute_type<3>::type::On_split`\endlink(a,a') is called, with a the original 3-attribute associated with `d` and a' the new 3-attribute created during the operation. If set, the dynamic on-split function of 3-attributes is also called on a and a'.
\cgalAdvancedBegin
If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==false`, non void attributes are not updated; thus the generic map can be no more valid after this operation.
\cgalAdvancedEnd
-\sa `is_insertable_cell_2_in_cell_3`
-\sa `insert_cell_0_in_cell_1`
-\sa `insert_cell_0_in_cell_2`
-\sa `insert_cell_1_in_cell_2`
-\sa `insert_dangling_cell_1_in_cell_2`
-\sa `remove_cell`
+\sa `is_insertable_cell_2_in_cell_3()`
+\sa `insert_cell_0_in_cell_1()`
+\sa `insert_cell_0_in_cell_2()`
+\sa `insert_cell_1_in_cell_2()`
+\sa `insert_cell_1_between_two_cells_2()`
+\sa `insert_dangling_cell_1_in_cell_2()`
+\sa `remove_cell()`
*/
template
Dart_descriptor insert_cell_2_in_cell_3(InputIterator afirst, InputIterator alast);
@@ -955,45 +986,57 @@ See examples for combinatorial map in \cgalFigureRef{fig_cmap_insert_edge} and f
If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==false`, non void attributes are not updated; thus the generic map can be no more valid after this operation.
\cgalAdvancedEnd
-\sa `insert_cell_0_in_cell_1`
-\sa `insert_cell_0_in_cell_2`
-\sa `insert_cell_1_in_cell_2`
-\sa `insert_cell_2_in_cell_3`
-\sa `remove_cell`
+\sa `insert_cell_0_in_cell_1()`
+\sa `insert_cell_0_in_cell_2()`
+\sa `insert_cell_1_in_cell_2()`
+\sa `insert_cell_1_between_two_cells_2()`
+\sa `insert_cell_2_in_cell_3()`
+\sa `remove_cell()`
*/
Dart_descriptor insert_dangling_cell_1_in_cell_2(Dart_descriptor d);
/*!
-Returns true iff it is possible to insert a 1-cell in the generic map between `d1` and `d2`.
+Returns `true` iff it is possible to insert a 1-cell in the generic map between `d1` and `d2`.
This is possible if `d1`\f$ \neq \f$ `d2` and `d1` can be reached from `d2` by using some `previous` and `next` calls.
\pre \link GenericMap::dimension `dimension`\endlink \f$ \geq\f$ 2, `d1`\f$ \in \f$ \link GenericMap::darts `darts()`\endlink, and `d2`\f$ \in \f$ \link GenericMap::darts `darts()`\endlink.
-\sa `insert_cell_1_in_cell_2`
-\sa `is_insertable_cell_2_in_cell_3`
+\sa `insert_cell_1_in_cell_2()`
+\sa `is_insertable_cell_2_in_cell_3()`
*/
bool is_insertable_cell_1_in_cell_2(Dart_const_descriptor d1, Dart_const_descriptor d2);
/*!
-Returns true iff it is possible to insert a 2-cell in the generic 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.
+Returns `true` iff it is possible to insert a 1-cell in the generic map between `d1` and `d2`.
+
+This is possible if `d1`\f$ \neq \f$ `d2` and `d1` can not be reached from `d2` by using some `previous` and `next` calls.
+\pre \link GenericMap::dimension `dimension`\endlink \f$ \geq\f$ 2, `d1`\f$ \in \f$ \link GenericMap::darts `darts()`\endlink, and `d2`\f$ \in \f$ \link GenericMap::darts `darts()`\endlink.
+
+\sa `insert_cell_1_between_two_cells_2()`
+
+*/
+bool is_insertable_cell_1_between_two_cells_2(Dart_const_descriptor d1, Dart_const_descriptor d2);
+
+/*!
+Returns `true` iff it is possible to insert a 2-cell in the generic 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 GenericMap::dimension `dimension`\endlink \f$ \geq\f$ 3.
-\sa `insert_cell_2_in_cell_3`
-\sa `is_insertable_cell_1_in_cell_2`
+\sa `insert_cell_2_in_cell_3()`
+\sa `is_insertable_cell_1_in_cell_2()`
*/
template
bool is_insertable_cell_2_in_cell_3(InputIterator afirst, InputIterator alast);
/*!
-Returns true iff the i-cell containing `d` can be removed.
+Returns `true` iff the i-cell containing `d` can be removed.
An i-cell can be removed if `i`==\link GenericMap::dimension `dimension`\endlink or if `i`==\link GenericMap::dimension `dimension`\endlink-1 or if `i`\f$ < \f$ \link GenericMap::dimension `dimension`\endlink-1 and the i-cell containing `d` is incident to at most two (i+1)-cells.
\pre 0\f$ \leq \f$ `i`\f$ \leq \f$ \link GenericMap::dimension `dimension`\endlink and `d`\f$ \in \f$ \link GenericMap::darts `darts()`\endlink.
-\sa `remove_cell`
+\sa `remove_cell()`
*/
template
bool is_removable(Dart_const_descriptor d);
@@ -1004,20 +1047,21 @@ Removes the i-cell containing `d`. Returns the number of darts removed fr
See examples in \cgalFigureRef{fig_cmap_insert_vertex}, \cgalFigureRef{fig_cmap_insert_edge} and \cgalFigureRef{fig_cmap_insert_facet}.
-If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if `i`\f$ < \f$ \link GenericMap::dimension `dimension`\endlink, and i+1-attributes are non `void`, and if there are two distinct (i+1)-cells around dart `d`, \link CellAttribute::On_merge `Attribute_type::type::On_merge`\endlink(a1,a2) is called, with a1 the (i+1)-attribute associated to `d`, and a2 the (i+1)-attribute associated to \f$ \beta_{i+1}\f$(d). If set, the dynamic onmerge function of i+1-attributes is also called on a1 and a2.
+If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if `i`\f$ < \f$ \link GenericMap::dimension `dimension`\endlink, and i+1-attributes are non `void`, and if there are two distinct (i+1)-cells around dart `d`, \link CellAttribute::On_merge `Attribute_type::type::On_merge`\endlink(a1,a2) is called, with a1 the (i+1)-attribute associated to `d`, and a2 the (i+1)-attribute associated to \f$ \beta_{i+1}\f$(d). If set, the dynamic on-merge function of i+1-attributes is also called on a1 and a2.
-If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if a j-cell is disconnected in two j-cells during the operation, and if j-attributes are non void, \link CellAttribute::On_split `Attribute_type::type::On_split`\endlink(a,a') is called with a the original j-attribute and a' the new j-attribute created due to the disconnection. If set, the dynamic onsplit function of j-attributes is also called on a and a'.
+If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if a j-cell is disconnected in two j-cells during the operation, and if j-attributes are non void, \link CellAttribute::On_split `Attribute_type::type::On_split`\endlink(a,a') is called with a the original j-attribute and a' the new j-attribute created due to the disconnection. If set, the dynamic on-split function of j-attributes is also called on a and a'.
\cgalAdvancedBegin
If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==false`, non void attributes are not updated; thus the generic map can be no more valid after this operation.
\cgalAdvancedEnd
-\sa `is_removable`
-\sa `insert_cell_0_in_cell_1`
-\sa `insert_cell_0_in_cell_2`
-\sa `insert_cell_1_in_cell_2`
-\sa `insert_dangling_cell_1_in_cell_2`
-\sa `insert_cell_2_in_cell_3`
+\sa `is_removable()`
+\sa `insert_cell_0_in_cell_1()`
+\sa `insert_cell_0_in_cell_2()`
+\sa `insert_cell_1_in_cell_2()`
+\sa `insert_cell_1_between_two_cells_2()`
+\sa `insert_dangling_cell_1_in_cell_2()`
+\sa `insert_cell_2_in_cell_3()`
*/
template
size_type remove_cell(Dart_descriptor d);
diff --git a/Combinatorial_map/doc/Combinatorial_map/examples.txt b/Combinatorial_map/doc/Combinatorial_map/examples.txt
index ce72b6a64a2..c77e4e6c522 100644
--- a/Combinatorial_map/doc/Combinatorial_map/examples.txt
+++ b/Combinatorial_map/doc/Combinatorial_map/examples.txt
@@ -6,4 +6,5 @@
\example Combinatorial_map/map_3_with_colored_facets.cpp
\example Combinatorial_map/map_3_dynamic_onmerge.cpp
\example Combinatorial_map/map_3_index.cpp
+\example Combinatorial_map/map_3_insert.cpp
*/
diff --git a/Combinatorial_map/examples/Combinatorial_map/map_3_insert.cpp b/Combinatorial_map/examples/Combinatorial_map/map_3_insert.cpp
new file mode 100644
index 00000000000..4963fcb23a7
--- /dev/null
+++ b/Combinatorial_map/examples/Combinatorial_map/map_3_insert.cpp
@@ -0,0 +1,34 @@
+#include
+#include
+#include
+#include
+
+typedef CGAL::Combinatorial_map<3> CMap_3;
+typedef CMap_3::Dart_descriptor Dart_descriptor;
+
+int main()
+{
+ CMap_3 cm;
+
+ // Create one combinatorial hexahedron
+ Dart_descriptor d1 = cm.make_combinatorial_hexahedron();
+
+ // Create one square face
+ Dart_descriptor d2=cm.make_combinatorial_polygon(4);
+
+ assert(cm.is_insertable_cell_1_between_two_cells_2(d1,d2));
+
+ // Insert the square face as a hole of the face of the hexahedron containing d1
+ cm.insert_cell_1_between_two_cells_2(d1, d2);
+
+ // Display the combinatorial map characteristics.
+ cm.display_characteristics(std::cout)<<", valid="
+ <(dh)) ++nb; }
+ std::cout<<"Number of 2-free darts: "<::value>=0,
"set_attribute but i-attributes are disabled");
- for ( typename Dart_of_cell_range::iterator it(*this, dh);
- it.cont(); ++it)
+ for (typename Dart_of_cell_range::iterator it(*this, dh);
+ it.cont(); ++it)
{
this->template set_dart_attribute(it, ah);
}
+ if(ah!=null_descriptor)
+ // To ensure that the dart of this attribute is dh
+ { this->template set_dart_of_attribute(ah, dh); }
}
/// @return a Attributes_range (range through all the
@@ -4410,7 +4413,8 @@ namespace CGAL {
bool is_insertable_cell_1_in_cell_2(Dart_const_descriptor adart1,
Dart_const_descriptor adart2) const
{
- if ( adart1==adart2 ) return false;
+ if (adart1==adart2 || adart1==null_descriptor) return false;
+ if (adart2==null_descriptor) return true;
for ( CMap_dart_const_iterator_of_orbit it(*this,adart1);
it.cont(); ++it )
{
@@ -4427,15 +4431,81 @@ namespace CGAL {
* same vertex than adart1.
*/
Dart_descriptor insert_cell_1_in_cell_2(Dart_descriptor adart1,
- Dart_descriptor adart2,
- bool update_attributes=true)
+ Dart_descriptor adart2,
+ bool update_attributes=true)
{
+ CGAL_assertion(is_insertable_cell_1_in_cell_2(adart1, adart2));
if ( adart2==null_descriptor )
return insert_dangling_cell_1_in_cell_2(adart1, null_descriptor,
update_attributes);
+ return generic_insert_cell_1(adart1, adart2, false, update_attributes);
+ }
- CGAL_assertion(is_insertable_cell_1_in_cell_2(adart1, adart2));
+ /** Test if an edge can be inserted between two different 2-cells
+ * between two given darts.
+ * @param adart1 a first dart.
+ * @param adart2 a second dart.
+ * @return true iff an edge can be inserted between adart1 and adart2.
+ */
+ bool is_insertable_cell_1_between_two_cells_2(Dart_const_descriptor adart1,
+ Dart_const_descriptor adart2) const
+ {
+ if (adart1==adart2 || adart1==null_descriptor || adart2==null_descriptor)
+ { return false; }
+ for ( CMap_dart_const_iterator_of_orbit it(*this,adart1);
+ it.cont(); ++it )
+ {
+ if ( it==adart2 ) return false;
+ }
+ return true;
+ }
+ /** Insert an edge between two different 2-cells, between two given darts.
+ * @param adart1 a first dart of the first facet (!=null_descriptor && !=null_dart_descriptor).
+ * @param adart2 a second dart of the second facet (!=null_descriptor && !=null_dart_descriptor).
+ * @param update_attributes a boolean to update the enabled attributes
+ * @return a dart of the new edge, and not incident to the
+ * same vertex than adart1.
+ */
+ Dart_descriptor insert_cell_1_between_two_cells_2(Dart_descriptor adart1,
+ Dart_descriptor adart2,
+ bool update_attributes=true)
+ {
+ CGAL_assertion(is_insertable_cell_1_between_two_cells_2(adart1, adart2));
+ return generic_insert_cell_1(adart1, adart2, true, update_attributes);
+ }
+
+ /** Insert an edge between two given darts. If the two darts belong to the same facet, call
+ * insert_cell_1_in_cell_2, otherwise call insert_cell_1_between_two_cells_2.
+ * @param adart1 a first dart (!=null_descriptor && !=null_dart_descriptor).
+ * @param adart2 a second dart.
+ * @param update_attributes a boolean to update the enabled attributes
+ * @return a dart of the new edge, and not incident to the
+ * same vertex than adart1.
+ */
+ Dart_descriptor insert_cell_1(Dart_descriptor adart1,
+ Dart_descriptor adart2,
+ bool update_attributes=true)
+ {
+ if(is_insertable_cell_1_in_cell_2(adart1, adart2))
+ { return insert_cell_1_in_cell_2(adart1, adart2, update_attributes); }
+ return insert_cell_1_between_two_cells_2(adart1, adart2, update_attributes);
+ }
+
+ /** Generic method to insert a 1-cell, either in a 2-cell (cf. insert_cell_1_in_cell_2)
+ * or between two different 2-cells (cf. insert_cell_1_between_two_cells_2).
+ * Indeed the code is the same, except for the group/degroup attribute.
+ * merge is true if adart1 and adart2 belongs to two different facets; in this case
+ * the two facets should be merged (they are now linked by the new edge);
+ * merge is false it adart1 and adart2 belongs to the same facet; in this case
+ * the facet is split in two.
+ * Internal method not supposed to be called by users.
+ */
+ Dart_descriptor generic_insert_cell_1(Dart_descriptor adart1,
+ Dart_descriptor adart2,
+ bool merge,
+ bool update_attributes)
+ {
size_type m1=get_new_mark();
CMap_dart_iterator_basic_of_involution it1(*this, adart1, m1);
@@ -4492,7 +4562,7 @@ namespace CGAL {
}
this->template basic_link_beta_for_involution<2>(d2, d1);
- for ( unsigned int dim=3; dim<=dimension; ++dim)
+ for (unsigned int dim=3; dim<=dimension; ++dim)
{
if ( !is_free(it1, dim) &&
is_marked(beta(it1, dim), treated) )
@@ -4509,7 +4579,19 @@ namespace CGAL {
if (are_attributes_automatically_managed() && update_attributes)
{
- internal::Degroup_attribute_functor_run::run(*this, d1, d2);
+ if(merge)
+ { // Here we group all enabled attributes starting from 2 to dimension
+ Helper::template Foreach_enabled_attributes
+ , 2>::run(*this, adart1, adart2);
+ // And we need to group also beta_i(adart1) and beta_i(adart2) for all
+ // enabled attributes starting from 3 dimension. Indeed when two i-cells
+ // are grouped for adart1 and adart2, this group also all beta_j two by two
+ // except for beta_i.
+ Helper::template Foreach_enabled_attributes
+ , 3>::run(*this, adart1, adart2);
+ }
+ else // Here we degroup 2-attributes
+ { internal::Degroup_attribute_functor_run::run(*this, adart1, adart2); }
}
negate_mark(m1);
diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map/internal/Combinatorial_map_group_functors.h b/Combinatorial_map/include/CGAL/Combinatorial_map/internal/Combinatorial_map_group_functors.h
index 2b55a2c21c9..a8da5c4ddd5 100644
--- a/Combinatorial_map/include/CGAL/Combinatorial_map/internal/Combinatorial_map_group_functors.h
+++ b/Combinatorial_map/include/CGAL/Combinatorial_map/internal/Combinatorial_map_group_functors.h
@@ -36,12 +36,19 @@
* non nullptr, we override all the i-attribute of the second i-cell to the
* first i-attribute.
*
+ * Group_neighboor_attribute to group the -attributes of beta_i(d1) and
+ * beta_i(d2) if they exist.
+ *
* Degroup_attribute_functor_run to degroup one i-attributes in two
* (except for j-adim).
*
* Test_split_attribute_functor to test if there is some i-attributes
* that are split after an operation. Modified darts are given in a
* std::deque.
+ *
+ * Set_dart_of_attribute_if_marked to set the dart of the i-attribute
+ * associated with a dart if the old dart is marked. Used in remove_cell
+ * functions.
*/
namespace CGAL
{
@@ -238,7 +245,8 @@ struct Group_nonvoid_attribute_functor_run
{
static void run(CMap& amap,
typename CMap::Dart_descriptor adart1,
- typename CMap::Dart_descriptor adart2)
+ typename CMap::Dart_descriptor adart2,
+ bool dart1_deleted=true)
{
static_assert( 1<=i && i<=CMap::dimension );
static_assert( i!=j );
@@ -251,8 +259,13 @@ struct Group_nonvoid_attribute_functor_run
a2=amap.template attribute(adart2);
// If the two attributes are equal, nothing to do.
- if ( a1 == a2 ) return;
-
+ if (a1==a2)
+ {
+ if(a1!=CMap::null_descriptor && dart1_deleted &&
+ amap.template dart_of_attribute(a1)==adart1)
+ { amap.template set_dart_of_attribute(a1, adart2); }
+ return;
+ }
typename CMap::Dart_descriptor toSet = amap.null_descriptor;
// If the attribute associated to adart1 is nullptr, set it with
@@ -268,6 +281,8 @@ struct Group_nonvoid_attribute_functor_run
}
}
amap.template set_attribute(toSet, a1);
+ if(dart1_deleted && toSet==adart1)
+ { amap.template set_dart_of_attribute(a1, adart2); }
}
};
// Specialization for i=0 and 2<=j. We update 0-attributes for beta_j j>=2.
@@ -277,7 +292,8 @@ struct Group_nonvoid_attribute_functor_run
{
static void run( CMap& amap,
typename CMap::Dart_descriptor dh1,
- typename CMap::Dart_descriptor dh2 )
+ typename CMap::Dart_descriptor dh2,
+ bool dart1_deleted=true)
{
static_assert
( CMap::Helper::template Dimension_index<0>::value>=0,
@@ -306,6 +322,8 @@ struct Group_nonvoid_attribute_functor_run
}
}
amap.template set_attribute<0>(toSet, a1);
+ if(dart1_deleted && toSet==dh1)
+ { amap.template set_dart_of_attribute<0>(a1, od); }
}
}
// Second extremity
@@ -338,7 +356,8 @@ struct Group_nonvoid_attribute_functor_run
{
static void run( CMap& amap,
typename CMap::Dart_descriptor dh1,
- typename CMap::Dart_descriptor dh2 )
+ typename CMap::Dart_descriptor dh2,
+ bool dart1_deleted=true)
{
static_assert
( CMap::Helper::template Dimension_index<0>::value>=0,
@@ -364,6 +383,8 @@ struct Group_nonvoid_attribute_functor_run
}
}
amap.template set_attribute<0>(toSet, a1);
+ if(dart1_deleted && toSet==dh1)
+ { amap.template set_dart_of_attribute<0>(a1, od); }
}
}
}
@@ -375,7 +396,8 @@ struct Group_nonvoid_attribute_functor_run
{
static void run( CMap& amap,
typename CMap::Dart_descriptor dh1,
- typename CMap::Dart_descriptor dh2 )
+ typename CMap::Dart_descriptor dh2,
+ bool=true)
{
static_assert
( CMap::Helper::template Dimension_index<0>::value>=0,
@@ -411,7 +433,8 @@ struct Group_nonvoid_attribute_functor_run
{
static void run(CMap&,
typename CMap::Dart_descriptor,
- typename CMap::Dart_descriptor)
+ typename CMap::Dart_descriptor,
+ bool=true)
{}
};
// Specialization for i=1 and j=0. Do nothing as edges attributes are not
@@ -421,7 +444,8 @@ struct Group_nonvoid_attribute_functor_run
{
static void run(CMap&,
typename CMap::Dart_descriptor,
- typename CMap::Dart_descriptor)
+ typename CMap::Dart_descriptor,
+ bool=true)
{}
};
//------------------------------------------------------------------------------
@@ -432,8 +456,10 @@ struct Group_attribute_functor_run
{
static void run( CMap& amap,
typename CMap::Dart_descriptor d1,
- typename CMap::Dart_descriptor d2)
- { Group_nonvoid_attribute_functor_run::run(amap, d1, d2); }
+ typename CMap::Dart_descriptor d2,
+ bool dart1_deleted=true)
+ { Group_nonvoid_attribute_functor_run::
+ run(amap, d1, d2, dart1_deleted); }
};
// Specialization for void attributes.
template
@@ -441,7 +467,8 @@ struct Group_attribute_functor_run
{
static void run( CMap&,
typename CMap::Dart_descriptor,
- typename CMap::Dart_descriptor )
+ typename CMap::Dart_descriptor,
+ bool=true)
{}
};
// ************************************************************************
@@ -464,6 +491,22 @@ struct Group_attribute_functor
run(amap,adart1,adart2); }
};
// ************************************************************************
+/// Group i-attribute of beta_i(d1) and beta_i(d2) if they exist.
+template
+struct Group_neighboor_attribute
+{
+ template
+ static void run(CMap& amap, typename CMap::Dart_descriptor d1,
+ typename CMap::Dart_descriptor d2)
+ {
+ if(!amap.template is_free(d1) && !amap.template is_free(d2))
+ {
+ CGAL::internal::Group_attribute_functor_run::run
+ (amap, amap.template opposite(d1), amap.template opposite(d2), false);
+ }
+ }
+};
+// ************************************************************************
// Functor used to degroup one i-attribute of one i-cell in two, except the
// attribute of j.
template::type>
+struct Set_dart_of_attribute_if_marked
+{
+ static void run(CMap& amap, typename CMap::Dart_descriptor d1,
+ typename CMap::size_type amark)
+ {
+ if(amap.template attribute(d1)!=CMap::null_descriptor &&
+ amap.template dart(d1)!=CMap::null_descriptor &&
+ amap.is_marked(amap.template dart(d1), amark))
+ { amap.template dart(d1)=d1; }
+ }
+};
+// Specialization for void attributes.
+template
+struct Set_dart_of_attribute_if_marked
+{
+ static void run(CMap&, typename CMap::Dart_descriptor,
+ typename CMap::size_type)
+ {}
+};
+// ************************************************************************
} // namespace internal
} // namespace CGAL
diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map/internal/Combinatorial_map_utility.h b/Combinatorial_map/include/CGAL/Combinatorial_map/internal/Combinatorial_map_utility.h
index 2a8d24c0123..b7ca3d12b42 100644
--- a/Combinatorial_map/include/CGAL/Combinatorial_map/internal/Combinatorial_map_utility.h
+++ b/Combinatorial_map/include/CGAL/Combinatorial_map/internal/Combinatorial_map_utility.h
@@ -342,23 +342,24 @@ namespace CGAL
//is called for case k only if the k'th type in the tuple
//is different from Void. Note that to the converse of Foreach_static
//Functor are called from n =0 to k
- template
+ template
struct Foreach_static_restricted;
- template
+ template
struct Foreach_static_restricted,n>
+ std::tuple,n, startn>
{
template
static void run(T& ... t){
- Conditionnal_run::run(t...);
+ if(n>=startn)
+ { Conditionnal_run::run(t...); }
Foreach_static_restricted
- ,n+1>::run(t...);
+ , n+1, startn>::run(t...);
}
};
- template
- struct Foreach_static_restricted,n>{
+ template
+ struct Foreach_static_restricted,n, startn>{
template
static void run(T& ... ){}
};
@@ -609,13 +610,13 @@ namespace CGAL
struct Attribute_const_range
{ typedef CGAL::Void type; };
- // To iterate onto each enabled attributes
- template
+ // To iterate onto each enabled attributes, starting from startn-attributes (0 by default)
+ template
struct Foreach_enabled_attributes
{
template
static void run(Ts& ... t)
- { Foreach_static_restricted::run(t...); }
+ { Foreach_static_restricted::run(t...); }
};
// To iterate onto each enabled attributes, except j-attributes
template
diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h b/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h
index 6a7a1b6f271..72c89d40142 100644
--- a/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h
+++ b/Combinatorial_map/include/CGAL/Combinatorial_map_operations.h
@@ -107,8 +107,10 @@ namespace CGAL
{
// We group the two (i+1)-cells incident if they exist.
if ( dg1!=amap.null_descriptor )
+ {
CGAL::internal::Group_attribute_functor_run::
- run(amap, dg1, dg2);
+ run(amap, dg1, dg2, true); // true because dg1 will be removed
+ }
}
// During the operation, we store in modified_darts the darts modified
@@ -148,6 +150,9 @@ namespace CGAL
if ( d1!=amap.null_dart_descriptor )
{
+ internal::Set_dart_of_attribute_if_marked::
+ run(amap, d1, mark);
+
if ( d2!=amap.null_dart_descriptor && d1!=d2 )
{
amap.template basic_link_beta(d1, d2);
@@ -353,7 +358,7 @@ namespace CGAL
// We group the two edges incident if they exist.
if ( dg1!=amap.null_descriptor )
CGAL::internal::Group_attribute_functor_run::
- run(amap, dg1, dg2);
+ run(amap, dg1, dg2, true); // true because dg1 will be removed
}
// During the operation, we store in modified_darts the darts modified
@@ -369,6 +374,9 @@ namespace CGAL
{
if ( !amap.template is_free<0>(*it) )
{
+ internal::Set_dart_of_attribute_if_marked::
+ run(amap, amap.template beta<0>(*it), mark);
+
if ( !amap.template is_free<1>(*it) &&
amap.template beta<0>(*it)!=(*it) )
{
@@ -523,7 +531,7 @@ namespace CGAL
// We group the two (i-1)-cells incident if they exist.
if ( dg1!=amap.null_descriptor )
CGAL::internal::Group_attribute_functor_run::
- run(amap, dg1, dg2);
+ run(amap, dg1, dg2, true); // true because dg1 will be removed
}
// During the operation, we store in modified_darts the darts modified
@@ -677,7 +685,7 @@ namespace CGAL
// We group the two vertices incident if they exist.
if ( dg1!=amap.null_descriptor )
CGAL::internal::Group_attribute_functor_run::
- run(amap, dg1, dg2);
+ run(amap, dg1, dg2, true); // true because dg1 will be removed
}
// During the operation, we store in modified_darts the darts modified
diff --git a/Combinatorial_map/include/CGAL/Compact_container_with_index.h b/Combinatorial_map/include/CGAL/Compact_container_with_index.h
index 044db27dc87..d3d67c57a88 100644
--- a/Combinatorial_map/include/CGAL/Compact_container_with_index.h
+++ b/Combinatorial_map/include/CGAL/Compact_container_with_index.h
@@ -738,6 +738,9 @@ public:
size_type index(const_iterator cit) const
{ return static_cast(cit); }
+ size_type index(Index idx) const
+ { return static_cast(idx); }
+
// Returns whether the iterator "cit" is in the range [begin(), end()].
// This function is mostly useful for purposes of efficient debugging at
// higher levels.
diff --git a/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h b/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h
index 1abea6aef50..aecd73c271a 100644
--- a/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h
+++ b/Combinatorial_map/test/Combinatorial_map/Combinatorial_map_3_test.h
@@ -1012,6 +1012,17 @@ bool test3D()
map.insert_cell_1_in_cell_2(d1, map.beta(d1,1,1));
map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl;
map.clear();
+
+ d1 = map.make_combinatorial_polygon(4);
+ d2 = map.make_combinatorial_polygon(4);
+ map.insert_cell_1_between_two_cells_2(d1, d2);
+ if(!map.is_valid())
+ {
+ map.display_characteristics(cout) << ", valid=" << map.is_valid() << endl;
+ std::cout<<"ERROR after map.insert_cell_1_between_two_cells_2(d1, d2);"<d1\f$ \not \in \f$ \f$ \langle{}\f$\f$ \alpha_0, \alpha_1\f$\f$ \rangle{}\f$(d2) which can be tested thanks to `gm.`\link GenericMap::is_insertable_cell_1_between_two_cells_2 `is_insertable_cell_1_between_two_cells_2(d1,d2)`\endlink.
+
`gm.`\link GenericMap::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 `gm.`\link GenericMap::is_insertable_cell_2_in_cell_3 `is_insertable_cell_2_in_cell_3(itbegin,itend)`\endlink (see example on \cgalFigureRef{fig_gmap_insert_facet}).
\cgalFigureBegin{fig_gmap_insert_facet,gmap_insert_facet.svg}
@@ -478,6 +480,24 @@ The second line is the result after the removal operations. We retrieve the orig
Example of high level operations. Left: Initial 3D generalized map after the creation of the generalized hexahedron. Middle: Generalized map obtained after the two 1-cell insertions. The two 2-cells were split in two. Right: Generalized map obtained after the 2-cell insertion. The 3-cell was split in two.
\cgalFigureEnd
+\subsection Generalized_mapInsertion Insert an edge between two different faces
+
+\anchor ssecexempleinsertiongmap
+
+This example shows the use of \link GenericMap::insert_cell_1_between_two_cells_2 `insert_cell_1_between_two_cells_2`\endlink operation. First we create a combinatorial hexahedron and a face with 4 edges. This face is inserted in the face of the hexahedron containing dart d1. We display the characteristics of the generalized map and check its validity. Then we count and display the number of 2-free darts.
+
+\cgalExample{Generalized_map/gmap_3_insert.cpp}
+
+The output is:
+\verbatim
+#Darts=60, #0-cells=12, #1-cells=17, #2-cells=6, #3-cells=1, #ccs=1, orientable=true, valid=1
+Number of 2-free darts: 8
+\endverbatim
+
+We can verify that there are 6 2-cells after the insertion since the squared face was inserted as a hole in one face of the hexahedron. We can also see that there are 8 2-free darts, which are the darts of the squared face. Since they bound an hole, there is no face filling the hole and thus 8 darts are 2-free.
+
+See also a similar example for Linear cell complex \ref Linear_cell_complexInsert "Insert an Edge Between Two Different Faces".
+
\subsection Generalized_mapA4DGeneralizedMap A 4D Generalized Map
In this example, a 4-dimensional generalized map is used. Two tetrahedral cells are created and sewn by \f$ \alpha_4\f$. Then the numbers of cells of the generalized map are displayed, and its validity is checked.
diff --git a/Generalized_map/doc/Generalized_map/examples.txt b/Generalized_map/doc/Generalized_map/examples.txt
index c38131ac9fb..1ea597a3975 100644
--- a/Generalized_map/doc/Generalized_map/examples.txt
+++ b/Generalized_map/doc/Generalized_map/examples.txt
@@ -7,4 +7,5 @@
\example Generalized_map/gmap_3_with_colored_facets.cpp
\example Generalized_map/gmap_3_dynamic_onmerge.cpp
\example Generalized_map/gmap_3_index.cpp
+\example Generalized_map/gmap_3_insert.cpp
*/
diff --git a/Generalized_map/examples/Generalized_map/gmap_3_insert.cpp b/Generalized_map/examples/Generalized_map/gmap_3_insert.cpp
new file mode 100644
index 00000000000..56c4a5cbd2f
--- /dev/null
+++ b/Generalized_map/examples/Generalized_map/gmap_3_insert.cpp
@@ -0,0 +1,34 @@
+#include
+#include
+#include
+#include
+
+typedef CGAL::Generalized_map<3> GMap_3;
+typedef GMap_3::Dart_descriptor Dart_descriptor;
+
+int main()
+{
+ GMap_3 gm;
+
+ // Create one combinatorial hexahedron
+ Dart_descriptor d1 = gm.make_combinatorial_hexahedron();
+
+ // Create one square face
+ Dart_descriptor d2=gm.make_combinatorial_polygon(4);
+
+ assert(gm.is_insertable_cell_1_between_two_cells_2(d1,d2));
+
+ // Insert the square face as a hole of the face of the hexahedron containing d1
+ gm.insert_cell_1_between_two_cells_2(d1, d2);
+
+ // Display the combinatorial map characteristics.
+ gm.display_characteristics(std::cout)<<", valid="
+ <(dh)) ++nb; }
+ std::cout<<"Number of 2-free darts: "<::value>=0,
"set_attribute but i-attributes are disabled");
- for ( typename Dart_of_cell_range::iterator it(*this, dh);
- it.cont(); ++it)
+ for (typename Dart_of_cell_range::iterator it(*this, dh);
+ it.cont(); ++it)
{
this->template set_dart_attribute(it, ah);
}
+ if(ah!=null_descriptor)
+ // To ensure that the dart of this attribute is dh
+ { this->template set_dart_of_attribute(ah, dh); }
}
/// @return a Attributes_range (range through all the
@@ -3512,7 +3515,9 @@ namespace CGAL {
bool is_insertable_cell_1_in_cell_2(Dart_const_descriptor adart1,
Dart_const_descriptor adart2)
{
- if ( adart1==adart2 || adart1==this->template alpha<0>(adart2) )
+ if (adart2==null_descriptor) return true;
+ if (adart1==adart2 || adart1==this->template alpha<0>(adart2) ||
+ adart1==null_descriptor || this->template is_free<1>(adart2))
return false;
for ( CGAL::GMap_dart_const_iterator_of_orbit it(*this,adart1);
it.cont(); ++it )
@@ -3525,29 +3530,104 @@ namespace CGAL {
/** Insert an edge in a 2-cell between two given darts.
* @param adart1 a first dart of the facet (!=null_descriptor && !=null_dart_descriptor).
* @param adart2 a second dart of the facet. If null_descriptor insert a dangling edge.
+ * @param update_attributes a boolean to update the enabled attributes
* @return a dart of the new edge, and not incident to the
* same vertex than adart1.
*/
Dart_descriptor insert_cell_1_in_cell_2(Dart_descriptor adart1,
- Dart_descriptor adart2,
- bool update_attributes=true,
- typename Attribute_descriptor<0>::type
- ah=null_descriptor)
+ Dart_descriptor adart2,
+ typename Attribute_descriptor<0>::
+ type ah=null_descriptor,
+ bool update_attributes=true)
{
- if ( adart2!=null_descriptor)
- {
- CGAL_assertion(is_insertable_cell_1_in_cell_2(adart1, adart2));
- }
+ CGAL_assertion(is_insertable_cell_1_in_cell_2(adart1, adart2));
+ return generic_insert_cell_1(adart1, adart2, false, update_attributes, ah);
+ }
+ /** Test if an edge can be inserted between two different 2-cells
+ * between two given darts.
+ * @param adart1 a first dart.
+ * @param adart2 a second dart.
+ * @return true iff an edge can be inserted between adart1 and adart2.
+ */
+ bool is_insertable_cell_1_between_two_cells_2(Dart_const_descriptor adart1,
+ Dart_const_descriptor adart2) const
+ {
+ if (adart1==adart2 || adart1==null_descriptor || adart2==null_descriptor)
+ { return false; }
+ for ( CGAL::GMap_dart_const_iterator_of_orbit it(*this,adart1);
+ it.cont(); ++it )
+ {
+ if ( it==adart2 ) return false;
+ }
+ for(unsigned int d=3; d<=dimension; ++d)
+ { if(is_free(adart1, d)!=is_free(adart2, d)) { return false; }}
+
+ return true;
+ }
+
+ /** Insert an edge between two different 2-cells, between two given darts.
+ * @param adart1 a first dart of the first facet (!=null_descriptor && !=null_dart_descriptor).
+ * @param adart2 a second dart of the second facet (!=null_descriptor && !=null_dart_descriptor).
+ * @param update_attributes a boolean to update the enabled attributes
+ * @return a dart of the new edge, and not incident to the
+ * same vertex than adart1.
+ */
+ Dart_descriptor insert_cell_1_between_two_cells_2(Dart_descriptor adart1,
+ Dart_descriptor adart2,
+ bool update_attributes=true)
+ {
+ CGAL_assertion(is_insertable_cell_1_between_two_cells_2(adart1, adart2));
+ return generic_insert_cell_1(adart1, adart2, true, update_attributes);
+ }
+
+ /** Insert an edge between two given darts. If the two darts belong to the same facet, call
+ * insert_cell_1_in_cell_2, otherwise call insert_cell_1_between_two_cells_2.
+ * @param adart1 a first dart (!=null_descriptor && !=null_dart_descriptor).
+ * @param adart2 a second dart.
+ * @param update_attributes a boolean to update the enabled attributes
+ * @return a dart of the new edge, and not incident to the
+ * same vertex than adart1.
+ */
+ Dart_descriptor insert_cell_1(Dart_descriptor adart1,
+ Dart_descriptor adart2,
+ bool update_attributes=true,
+ typename Attribute_descriptor<0>::type
+ ah=null_descriptor)
+ {
+ CGAL_assertion(adart1!=null_descriptor);
+ if(is_insertable_cell_1_in_cell_2(adart1, adart2))
+ { return insert_cell_1_in_cell_2(adart1, adart2, update_attributes, ah); }
+ return insert_cell_1_between_two_cells_2(adart1, adart2, update_attributes);
+ }
+
+ /** Generic method to insert a 1-cell, either in a 2-cell (cf. insert_cell_1_in_cell_2)
+ * or between two different 2-cells (cf. insert_cell_1_between_two_cells_2).
+ * Indeed the code is the same, except for the group/degroup attribute.
+ * merge is true if adart1 and adart2 belongs to two different facets; in this case
+ * the two facets should be merged (they are now linked by the new edge);
+ * merge is false it adart1 and adart2 belongs to the same facet; in this case
+ * the facet is split in two.
+ * Internal method not supposed to be called by users.
+ */
+ Dart_descriptor generic_insert_cell_1(Dart_descriptor adart1,
+ Dart_descriptor adart2,
+ bool merge,
+ bool update_attributes=true,
+ typename Attribute_descriptor<0>::type
+ ah=null_descriptor)
+ {
/* CGAL::GMap_dart_iterator_basic_of_involution will contain all
* alpha_i except alpha_0, alpha_1 and alpha_2, i.e. this is
*
*/
+ Dart_descriptor dart2_a1=null_descriptor;
+ if(adart2!=null_descriptor) { dart2_a1=alpha<1>(adart2); }
+
size_type m1=get_new_mark();
CGAL::GMap_dart_iterator_basic_of_involution it1(*this, adart1, m1);
-
size_type m2=get_new_mark();
- CGAL::GMap_dart_iterator_basic_of_involution it2(*this, adart2, m2);
+ CGAL::GMap_dart_iterator_basic_of_involution it2(*this, dart2_a1, m2);
Dart_descriptor d1=null_descriptor;
Dart_descriptor d2=null_descriptor;
@@ -3565,13 +3645,13 @@ namespace CGAL {
if (!isfree1)
{
- d3 = create_dart();
- d4 = create_dart();
- this->template basic_link_alpha<2>(d1, d3);
- this->template basic_link_alpha<2>(d2, d4);
+ d3 = create_dart();
+ d4 = create_dart();
+ this->template basic_link_alpha<2>(d1, d3);
+ this->template basic_link_alpha<2>(d2, d4);
}
- for ( unsigned int dim=3; dim<=dimension; ++dim)
+ for (unsigned int dim=3; dim<=dimension; ++dim)
{
if ( !is_free(it1, dim) &&
is_marked(alpha(it1, dim), treated) )
@@ -3598,7 +3678,7 @@ namespace CGAL {
}
this->template link_alpha<1>(it1, d1);
- if ( adart2!=null_descriptor )
+ if (adart2!=null_descriptor)
{
CGAL_assertion (it2.cont());
this->template link_alpha<1>(it2, d2);
@@ -3626,9 +3706,25 @@ namespace CGAL {
if (are_attributes_automatically_managed() && update_attributes)
{
- if ( !this->template is_free<2>(d1) && d2!=null_descriptor )
- CGAL::internal::GMap_degroup_attribute_functor_run::
- run(*this, d1, this->template alpha<2>(d1));
+ if(merge)
+ { // Here we group all enabled attributes starting from 2 to dimension
+ Helper::template Foreach_enabled_attributes
+ , 2>::
+ run(*this, adart1, adart2);
+ // And we need to group also alpha_i(adart1) and alpha_i(adart2) for all
+ // enabled attributes starting from 3 dimension. Indeed when two i-cells
+ // are grouped for adart1 and adart2, this group also all alpha_j two by two
+ // except for alpha_i.
+ Helper::template Foreach_enabled_attributes
+ , 3>::run(*this, adart1, adart2);
+
+ }
+ else // Here we degroup 2-attributes
+ {
+ if (!this->template is_free<2>(d1) && d2!=null_descriptor)
+ { CGAL::internal::GMap_degroup_attribute_functor_run::
+ run(*this, d1, this->template alpha<2>(d1)); }
+ }
}
negate_mark(m1);
@@ -3673,7 +3769,8 @@ namespace CGAL {
typename Attribute_descriptor<0>::
type ah=null_descriptor,
bool update_attributes=true )
- { return insert_cell_1_in_cell_2(adart1, null_descriptor, update_attributes, ah); }
+ { return insert_cell_1_in_cell_2(adart1, null_descriptor, ah,
+ update_attributes); }
/** Test if a 2-cell can be inserted onto a given 3-cell along
* a path of edges.
diff --git a/Generalized_map/include/CGAL/Generalized_map/internal/Generalized_map_group_functors.h b/Generalized_map/include/CGAL/Generalized_map/internal/Generalized_map_group_functors.h
index 4b3c17816e4..4d4a98cfdbe 100644
--- a/Generalized_map/include/CGAL/Generalized_map/internal/Generalized_map_group_functors.h
+++ b/Generalized_map/include/CGAL/Generalized_map/internal/Generalized_map_group_functors.h
@@ -132,7 +132,8 @@ struct GMap_group_attribute_functor_run
{
static void run(GMap& amap,
typename GMap::Dart_descriptor adart1,
- typename GMap::Dart_descriptor adart2)
+ typename GMap::Dart_descriptor adart2,
+ bool dart1_deleted=true)
{
static_assert( i<=GMap::dimension );
static_assert( i!=j );
@@ -145,7 +146,13 @@ struct GMap_group_attribute_functor_run
a2=amap.template attribute(adart2);
// If the two attributes are equal, nothing to do.
- if ( a1 == a2 ) return;
+ if ( a1 == a2 )
+ {
+ if(a1!=GMap::null_descriptor && dart1_deleted &&
+ amap.template dart_of_attribute(a1)==adart1)
+ { amap.template set_dart_of_attribute(a1, adart2); }
+ return;
+ }
typename GMap::Dart_descriptor toSet = amap.null_descriptor;
@@ -162,15 +169,18 @@ struct GMap_group_attribute_functor_run
}
}
amap.template set_attribute(toSet, a1);
+ if(dart1_deleted && toSet==adart1)
+ { amap.template set_dart_of_attribute(a1, adart2); }
}
};
// Specialization for void attributes.
template
struct GMap_group_attribute_functor_run
{
- static void run( GMap&,
- typename GMap::Dart_descriptor,
- typename GMap::Dart_descriptor )
+ static void run(GMap&,
+ typename GMap::Dart_descriptor,
+ typename GMap::Dart_descriptor,
+ bool=true)
{}
};
// Specialization for i=j. Do nothing as j is the dimension to not consider.
@@ -179,7 +189,8 @@ struct GMap_group_attribute_functor_run
{
static void run(GMap&,
typename GMap::Dart_descriptor,
- typename GMap::Dart_descriptor)
+ typename GMap::Dart_descriptor,
+ bool=true)
{}
};
// ************************************************************************
diff --git a/Generalized_map/include/CGAL/Generalized_map_operations.h b/Generalized_map/include/CGAL/Generalized_map_operations.h
index 0ebec7a7c5c..4c65af865db 100644
--- a/Generalized_map/include/CGAL/Generalized_map_operations.h
+++ b/Generalized_map/include/CGAL/Generalized_map_operations.h
@@ -91,8 +91,9 @@ namespace CGAL
it.cont(); ++it )
{
to_erase.push_back(it);
- if ( !amap.template is_free(it) && dg1==amap.null_descriptor )
- { dg1=it; dg2=amap.template alpha(it); }
+ if (dg1==amap.null_descriptor && !amap.template is_free(it) &&
+ !amap.template is_free(amap.template alpha(it)))
+ { dg1=it; dg2=amap.template alpha(it); }
amap.mark(it, mark);
++res;
}
@@ -102,7 +103,7 @@ namespace CGAL
// We group the two (i+1)-cells incident if they exist.
if ( dg1!=amap.null_descriptor )
CGAL::internal::GMap_group_attribute_functor_run::
- run(amap, dg1, dg2);
+ run(amap, dg1, dg2, true); // true because dg1 will be deleted
}
// During the operation, we store in modified_darts the darts modified
@@ -136,6 +137,9 @@ namespace CGAL
modified_darts.push_back(d2);
amap.mark(d2, mark_modified_darts);
}
+
+ internal::Set_dart_of_attribute_if_marked::
+ run(amap, d1, mark);
}
}
}
@@ -320,7 +324,7 @@ namespace CGAL
// We group the two (i-1)-cells incident if they exist.
if ( dg1!=amap.null_descriptor )
CGAL::internal::GMap_group_attribute_functor_run::
- run(amap, dg1, dg2);
+ run(amap, dg1, dg2, true); // true because dg1 will be deleted
}
// During the operation, we store in modified_darts the darts modified
diff --git a/Generalized_map/test/Generalized_map/GMap_test_insertions.h b/Generalized_map/test/Generalized_map/GMap_test_insertions.h
index b239bad84c1..1a3f67aabc3 100644
--- a/Generalized_map/test/Generalized_map/GMap_test_insertions.h
+++ b/Generalized_map/test/Generalized_map/GMap_test_insertions.h
@@ -149,7 +149,7 @@ bool test_edge_insertion(GMAP& gmap)
trace_test_begin();
d1 = gmap.make_combinatorial_polygon(4);
- gmap.insert_cell_1_in_cell_2(d1, gmap.alpha(d1,0,1,0));
+ gmap.insert_cell_1_in_cell_2(d1, gmap.alpha(d1,0,1));
if ( !check_number_of_cells_3(gmap, 4, 5, 2, 1, 1) )
return false;
gmap.clear();
@@ -158,7 +158,7 @@ bool test_edge_insertion(GMAP& gmap)
d1 = gmap.make_combinatorial_polygon(4);
d2 = gmap.make_combinatorial_polygon(4);
gmap.template sew<3>(d1, d2);
- gmap.insert_cell_1_in_cell_2(d1, gmap.alpha(d1,0,1,0));
+ gmap.insert_cell_1_in_cell_2(d1, gmap.alpha(d1,0,1));
if ( !check_number_of_cells_3(gmap, 4, 5, 2, 2, 1) )
return false;
gmap.clear();
@@ -167,18 +167,11 @@ bool test_edge_insertion(GMAP& gmap)
d1 = gmap.make_combinatorial_polygon(4);
d2 = gmap.make_combinatorial_polygon(4);
gmap.template sew<2>(d1, d2);
- gmap.insert_cell_1_in_cell_2(d1, gmap.alpha(d1,0,1,0));
+ gmap.insert_cell_1_in_cell_2(d1, gmap.alpha(d1,0,1));
if ( !check_number_of_cells_3(gmap, 6, 8, 3, 1, 1) )
return false;
gmap.clear();
- trace_test_begin();
- d1 = gmap.create_dart();
- gmap.insert_dangling_cell_1_in_cell_2(d1);
- if ( !check_number_of_cells_3(gmap, 2, 2, 1, 1, 1) )
- return false;
- gmap.clear();
-
trace_test_begin();
d1 = gmap.make_edge();
gmap.template sew<1>(d1, gmap.alpha(d1, 0));
diff --git a/Generalized_map/test/Generalized_map/gmap_test_split_attribute.cpp b/Generalized_map/test/Generalized_map/gmap_test_split_attribute.cpp
index 51e5618ce9c..6dd17ee0a84 100644
--- a/Generalized_map/test/Generalized_map/gmap_test_split_attribute.cpp
+++ b/Generalized_map/test/Generalized_map/gmap_test_split_attribute.cpp
@@ -54,7 +54,7 @@ bool test(const std::string& s)
for(std::size_t i=0; i(dd));
+ newd=m.insert_cell_1_in_cell_2(dd, m.template alpha<0,1>(dd));
if(m.template attribute<2>(newd)==GMap::null_descriptor)
{
std::cout<<"ERROR1: "<` is a model of `LinearCellComplexIte
\section Linear_cell_complexOperations Operations
-Several operations defined in the combinatorial maps or generalized maps package can be used on a linear cell complex. This is the case for all the iteration operations that do not modify the model (see example in Section \ref ssec3Dlcc "A 3D Linear Cell Complex"). This is also the case for all the operations that do not create new 0-cells: `sew`, `unsew`, \link GenericMap::remove_cell `remove_cell`\endlink, \link GenericMap::insert_cell_1_in_cell_2 `insert_cell_1_in_cell_2`\endlink or \link GenericMap::insert_cell_2_in_cell_3 `insert_cell_2_in_cell_3`\endlink. Indeed, all these operations update non `void` attributes, and thus update vertex attributes of a linear cell complex. Note that some existing 0-attributes can be duplicated by the `unsew` method, but these 0-attributes are not new but copies of existing old 0-attributes.
+Several operations defined in the combinatorial maps or generalized maps package can be used on a linear cell complex. This is the case for all the iteration operations that do not modify the model (see example in Section \ref ssec3Dlcc "A 3D Linear Cell Complex"). This is also the case for all the operations that do not create new 0-cells: `sew`, `unsew`, \link GenericMap::remove_cell `remove_cell`\endlink, \link GenericMap::insert_cell_1_in_cell_2 `insert_cell_1_in_cell_2`\endlink, \link GenericMap::insert_cell_1_between_two_cells_2 `insert_cell_1_between_two_cells_2`\endlink or \link GenericMap::insert_cell_2_in_cell_3 `insert_cell_2_in_cell_3`\endlink. Indeed, all these operations update non `void` attributes, and thus update vertex attributes of a linear cell complex. Note that some existing 0-attributes can be duplicated by the `unsew` method, but these 0-attributes are not new but copies of existing old 0-attributes.
However, operations that create a new 0-cell can not be directly used since the new 0-cell would not be associated with a vertex attribute. Indeed, it is not possible for these operations to automatically decide which point to create. These operations are: \link GenericMap::insert_cell_0_in_cell_1 `insert_cell_0_in_cell_1`\endlink, \link GenericMap::insert_cell_0_in_cell_2 `insert_cell_0_in_cell_2`\endlink, \link GenericMap::insert_dangling_cell_1_in_cell_2 `insert_dangling_cell_1_in_cell_2`\endlink, plus all the creation operations. For these operations, new versions are proposed taking some points as additional parameters. Lastly, some new operations are defined, which use the geometry (see sections \ref ssecconstructionsop "Construction Operations" and \ref ssecmodifop "Modification Operations").
@@ -278,6 +278,15 @@ The following example shows the incremental builder.
\cgalExample{Linear_cell_complex/linear_cell_complex_3_incremental_builder.cpp}
+\subsection Linear_cell_complexInsert Insert an Edge Between Two Different Faces
+
+The following example shows the use of \link GenericMap::insert_cell_1_between_two_cells_2 `insert_cell_1_between_two_cells_2`\endlink operation that inserts an edge between two different faces, thus creating an hole in the first face.
+
+\cgalExample{Linear_cell_complex/linear_cell_complex_3_insert.cpp}
+
+\cgalFigureBegin{fig_lcc_insert,lcc_insert_example.png}
+Result of the run of the linear_cell_complex_3_insert program. A window shows the 3D cube where one face has a hole.
+\cgalFigureEnd
\section Linear_cell_complexDesign Design and Implementation History
diff --git a/Linear_cell_complex/doc/Linear_cell_complex/examples.txt b/Linear_cell_complex/doc/Linear_cell_complex/examples.txt
index 4f178f666d1..def1f1a28fe 100644
--- a/Linear_cell_complex/doc/Linear_cell_complex/examples.txt
+++ b/Linear_cell_complex/doc/Linear_cell_complex/examples.txt
@@ -5,4 +5,5 @@
\example Linear_cell_complex/linear_cell_complex_3_attributes_management.cpp
\example Linear_cell_complex/linear_cell_complex_3_incremental_builder.cpp
\example Linear_cell_complex/draw_linear_cell_complex.cpp
+\example Linear_cell_complex/linear_cell_complex_3_insert.cpp
*/
diff --git a/Linear_cell_complex/doc/Linear_cell_complex/fig/lcc_insert_example.png b/Linear_cell_complex/doc/Linear_cell_complex/fig/lcc_insert_example.png
new file mode 100644
index 00000000000..959598345aa
Binary files /dev/null and b/Linear_cell_complex/doc/Linear_cell_complex/fig/lcc_insert_example.png differ
diff --git a/Linear_cell_complex/examples/Linear_cell_complex/CMakeLists.txt b/Linear_cell_complex/examples/Linear_cell_complex/CMakeLists.txt
index d0ed1c3a028..871ba893bfd 100644
--- a/Linear_cell_complex/examples/Linear_cell_complex/CMakeLists.txt
+++ b/Linear_cell_complex/examples/Linear_cell_complex/CMakeLists.txt
@@ -17,11 +17,12 @@ create_single_source_cgal_program("gmap_linear_cell_complex_3.cpp")
create_single_source_cgal_program("linear_cell_complex_3.cpp")
create_single_source_cgal_program(
"linear_cell_complex_3_attributes_management.cpp")
+create_single_source_cgal_program("linear_cell_complex_3_incremental_builder.cpp")
+create_single_source_cgal_program("linear_cell_complex_3_insert.cpp")
create_single_source_cgal_program("linear_cell_complex_3_operations.cpp")
create_single_source_cgal_program(
"linear_cell_complex_3_with_colored_vertices.cpp")
create_single_source_cgal_program("linear_cell_complex_3_with_mypoint.cpp")
-create_single_source_cgal_program("linear_cell_complex_3_incremental_builder.cpp")
create_single_source_cgal_program("linear_cell_complex_4.cpp")
create_single_source_cgal_program("plane_graph_to_lcc_2.cpp")
create_single_source_cgal_program("voronoi_2.cpp")
@@ -31,4 +32,5 @@ create_single_source_cgal_program("draw_linear_cell_complex.cpp")
if(CGAL_Qt5_FOUND)
target_link_libraries(draw_linear_cell_complex PUBLIC CGAL::CGAL_Basic_viewer)
target_link_libraries(linear_cell_complex_3_incremental_builder PUBLIC CGAL::CGAL_Basic_viewer)
+ target_link_libraries(linear_cell_complex_3_insert PUBLIC CGAL::CGAL_Basic_viewer)
endif()
diff --git a/Linear_cell_complex/examples/Linear_cell_complex/linear_cell_complex_3_insert.cpp b/Linear_cell_complex/examples/Linear_cell_complex/linear_cell_complex_3_insert.cpp
new file mode 100644
index 00000000000..686ca8ce03a
--- /dev/null
+++ b/Linear_cell_complex/examples/Linear_cell_complex/linear_cell_complex_3_insert.cpp
@@ -0,0 +1,35 @@
+#include
+#include
+#include
+
+typedef CGAL::Linear_cell_complex_for_combinatorial_map<3> LCC1;
+typedef CGAL::Linear_cell_complex_for_generalized_map<3> LCC2;
+
+template
+void test()
+{
+ LCC lcc;
+ using Point=typename LCC::Point;
+
+ typename LCC::Dart_descriptor d1=
+ lcc.make_hexahedron(Point(0,0,0), Point(5,0,0),
+ Point(5,5,0), Point(0,5,0),
+ Point(0,5,4), Point(0,0,4),
+ Point(5,0,4), Point(5,5,4));
+ typename LCC::Dart_descriptor d2=
+ lcc.make_quadrangle(Point(5,2,2), Point(5,1,2),
+ Point(5,1,1), Point(5,2,1));
+
+ lcc.insert_cell_1_between_two_cells_2
+ (lcc.template opposite<2>(lcc.next(lcc.next(d1))),
+ lcc.next(lcc.next(d2)));
+
+ CGAL::draw(lcc);
+}
+
+int main()
+{
+ test();
+ test();
+ return EXIT_SUCCESS;
+}
diff --git a/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_2_test.cpp b/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_2_test.cpp
index 28195f35354..89f981f53d1 100644
--- a/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_2_test.cpp
+++ b/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_2_test.cpp
@@ -32,7 +32,8 @@ struct Myattrib : public CGAL::Cell_attribute_with_point
struct MonInfo
{
- MonInfo(int i=0) : mnb(i==0?rand():i), ptr(reinterpret_cast(this))
+ MonInfo(long long int i=0) : mnb(i==0?rand():static_cast(i)),
+ ptr(reinterpret_cast(this))
{}
bool operator==(const MonInfo& info) const
diff --git a/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_2_test.h b/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_2_test.h
index 55e93de1f2b..b76bbf1d7e6 100644
--- a/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_2_test.h
+++ b/Linear_cell_complex/test/Linear_cell_complex/Linear_cell_complex_2_test.h
@@ -45,20 +45,103 @@ void trace_display_msg(const char* msg)
#endif
}
-template
-struct Alpha1
+template::type::Info>
+struct SetInfoIfNonVoid
{
- static typename LCC::Dart_descriptor run(LCC&, typename LCC::Dart_descriptor dh)
- { return dh; }
+ static void run(Map& map,
+ typename Map::template Attribute_descriptor::type attr,
+ long long int nb)
+ {
+ map.template info_of_attribute(attr)=
+ typename Map::template Attribute_type::type::Info(nb);
+ }
};
-template
-struct Alpha1
+template
+struct SetInfoIfNonVoid