mirror of https://github.com/CGAL/cgal
Edge insertion for CMap/GMap (#7409)
_Please use the following template to help us managing pull requests._ ## Summary of Changes Added the function `insert_cell_1_between_two_cells_2()` into `GenericMap` concept, which allows users to insert an edge between two different faces allowing to create faces with holes. ## Release Management * Affected package(s): CMap/GMap * Feature/Small Feature (if any): https://cgal.geometryfactory.com/CGAL/Members/wiki/Features/Small_Features/Insert_edge_CMap/GMap * Link to compiled documentation (obligatory for small feature) [*wrong link name to be changed*](httpssss://wrong_URL_to_be_changed/Manual/Pkg) * License and copyright ownership:
This commit is contained in:
commit
c5cf3d9915
|
|
@ -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 <I>descriptors</I> (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 <I>descriptors</I> (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 <I>d1</I>\f$ \not \in \f$ \f$ \langle{}\f$\f$ \beta_1\f$\f$ \rangle{}\f$(<I>d2</I>) 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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>i</I>-boundary.
|
||||
Returns `true` iff the generic map is without <I>i</I>-boundary.
|
||||
|
||||
The map is without <I>i</I>-boundary if there is no `i`-free dart.
|
||||
\pre 1\f$ \leq \f$ <I>i</I> \f$ \leq \f$ \link GenericMap::dimension `dimension`\endlink.
|
||||
|
|
@ -280,7 +280,7 @@ The map is without <I>i</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>i</I>-attributes descriptors if indices a
|
|||
template <unsigned int i>
|
||||
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>i</I>-free.
|
||||
Returns `true` iff dart `d` is <I>i</I>-free.
|
||||
\pre 0 \f$ \leq \f$ <I>i</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>i</I>-free.
|
||||
Returns `true` iff dart `d` is <I>i</I>-free.
|
||||
\pre 0 \f$ \leq \f$ <I>i</I> \f$ \leq \f$ \link GenericMap::dimension `dimension`\endlink.
|
||||
*/
|
||||
template<unsigned int i>
|
||||
|
|
@ -477,7 +477,7 @@ A shortcut for \link GenericMap::dart_of_attribute(typename Attribute_const_desc
|
|||
template<unsigned int i>
|
||||
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>i</I> \f$ \leq \f$ \link GenericMap::dimension `dimension`\endlink, and <I>i</I>-attributes are non `void`.
|
||||
*/
|
||||
template<unsigned int i>
|
||||
|
|
@ -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<i>::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<int i>
|
||||
boost::function<void(typename Attribute_type< i >::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<i>::type`\endlink as parameters.
|
||||
*/
|
||||
template<int i>
|
||||
|
|
@ -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<i>::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<int i>
|
||||
boost::function<void(typename Attribute_type< i >::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<i>::type`\endlink as parameters.
|
||||
*/
|
||||
template<int i>
|
||||
|
|
@ -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$ <I>m</I> \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(<I>a</I>,<I>a'</I>) is called, with <I>a</I> the original 1-attribute associated with <I>d</I> and <I>a'</I> the new 1-attribute created during the operation. If set, the dynamic onsplit function of 1-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
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(<I>a</I>,<I>a'</I>) is called, with <I>a</I> the original 1-attribute associated with <I>d</I> and <I>a'</I> the new 1-attribute created during the operation. If set, the dynamic on-split function of 1-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
|
||||
\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<InputIterator>`
|
||||
\sa `remove_cell<i>`
|
||||
\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<InputIterator>()`
|
||||
\sa `remove_cell<i>()`
|
||||
*/
|
||||
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(<I>a</I>,<I>a'</I>) is called, with <I>a</I> the original 2-attribute associated with `d` and <I>a'</I> each new 2-attribute created during the operation. If set, the dynamic onsplit function of 2-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
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(<I>a</I>,<I>a'</I>) is called, with <I>a</I> the original 2-attribute associated with `d` and <I>a'</I> each new 2-attribute created during the operation. If set, the dynamic on-split function of 2-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
|
||||
\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<InputIterator>`
|
||||
\sa `remove_cell<i>`
|
||||
\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<InputIterator>()`
|
||||
\sa `remove_cell<i>()`
|
||||
*/
|
||||
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(<I>a</I>,<I>a'</I>) is called, with <I>a</I> the original 2-attribute associated with `d` and <I>a'</I> the new 2-attribute created during the operation. If set, the dynamic onsplit function of 2-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
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(<I>a</I>,<I>a'</I>) is called, with <I>a</I> the original 2-attribute associated with `d1` and <I>a'</I> the new 2-attribute created during the operation. If set, the dynamic on-split function of 2-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
|
||||
\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<InputIterator>`
|
||||
\sa `remove_cell<i>`
|
||||
\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<InputIterator>()`
|
||||
\sa `remove_cell<i>()`
|
||||
*/
|
||||
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<i>::type::On_merge`\endlink(<I>a</I>,<I>a'</I>) is called for all enabled i-attributes, for i>=2, with <I>a</I> the original 2-attribute associated with `d1` and <I>a'</I> the original 2-attribute associated with `d2`. If set, the dynamic on-merge function of i-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
|
||||
\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<InputIterator>()`
|
||||
\sa `remove_cell<i>()`
|
||||
*/
|
||||
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(<I>a</I>,<I>a'</I>) is called, with <I>a</I> the original 3-attribute associated with `d` and <I>a'</I> the new 3-attribute created during the operation. If set, the dynamic onsplit function of 3-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
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(<I>a</I>,<I>a'</I>) is called, with <I>a</I> the original 3-attribute associated with `d` and <I>a'</I> the new 3-attribute created during the operation. If set, the dynamic on-split function of 3-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
|
||||
\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<InputIterator>`
|
||||
\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<i>`
|
||||
\sa `is_insertable_cell_2_in_cell_3<InputIterator>()`
|
||||
\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<i>()`
|
||||
*/
|
||||
template <class InputIterator>
|
||||
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<InputIterator>`
|
||||
\sa `remove_cell<i>`
|
||||
\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<InputIterator>()`
|
||||
\sa `remove_cell<i>()`
|
||||
|
||||
*/
|
||||
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<InputIterator>`
|
||||
\sa `insert_cell_1_in_cell_2()`
|
||||
\sa `is_insertable_cell_2_in_cell_3<InputIterator>()`
|
||||
|
||||
*/
|
||||
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<InputIterator>`
|
||||
\sa `is_insertable_cell_1_in_cell_2`
|
||||
\sa `insert_cell_2_in_cell_3<InputIterator>()`
|
||||
\sa `is_insertable_cell_1_in_cell_2()`
|
||||
|
||||
*/
|
||||
template <class InputIterator>
|
||||
bool is_insertable_cell_2_in_cell_3(InputIterator afirst, InputIterator alast);
|
||||
|
||||
/*!
|
||||
Returns true iff the <I>i</I>-cell containing `d` can be removed.
|
||||
Returns `true` iff the <I>i</I>-cell containing `d` can be removed.
|
||||
|
||||
An <I>i</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>i</I>-cell containing `d` is incident to at most two (<I>i+1</I>)-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<i>`
|
||||
\sa `remove_cell<i>()`
|
||||
*/
|
||||
template <unsigned int i>
|
||||
bool is_removable(Dart_const_descriptor d);
|
||||
|
|
@ -1004,20 +1047,21 @@ Removes the <I>i</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>i+1</I>-attributes are non `void`, and if there are two distinct (<I>i+1</I>)-cells around dart `d`, \link CellAttribute::On_merge `Attribute_type<i+1>::type::On_merge`\endlink(<I>a1</I>,<I>a2</I>) is called, with <I>a1</I> the (<I>i+1</I>)-attribute associated to `d`, and <I>a2</I> the (<I>i+1</I>)-attribute associated to \f$ \beta_{i+1}\f$(<I>d</I>). If set, the dynamic onmerge function of <I>i+1</I>-attributes is also called on <I>a1</I> and <I>a2</I>.
|
||||
If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if `i`\f$ < \f$ \link GenericMap::dimension `dimension`\endlink, and <I>i+1</I>-attributes are non `void`, and if there are two distinct (<I>i+1</I>)-cells around dart `d`, \link CellAttribute::On_merge `Attribute_type<i+1>::type::On_merge`\endlink(<I>a1</I>,<I>a2</I>) is called, with <I>a1</I> the (<I>i+1</I>)-attribute associated to `d`, and <I>a2</I> the (<I>i+1</I>)-attribute associated to \f$ \beta_{i+1}\f$(<I>d</I>). If set, the dynamic on-merge function of <I>i+1</I>-attributes is also called on <I>a1</I> and <I>a2</I>.
|
||||
|
||||
If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if a <I>j</I>-cell is disconnected in two <I>j</I>-cells during the operation, and if <I>j</I>-attributes are non void, \link CellAttribute::On_split `Attribute_type<j>::type::On_split`\endlink(<I>a</I>,<I>a'</I>) is called with <I>a</I> the original <I>j</I>-attribute and <I>a'</I> the new <I>j</I>-attribute created due to the disconnection. If set, the dynamic onsplit function of <i>j</i>-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
If \link GenericMap::are_attributes_automatically_managed `are_attributes_automatically_managed()`\endlink`==true`, if a <I>j</I>-cell is disconnected in two <I>j</I>-cells during the operation, and if <I>j</I>-attributes are non void, \link CellAttribute::On_split `Attribute_type<j>::type::On_split`\endlink(<I>a</I>,<I>a'</I>) is called with <I>a</I> the original <I>j</I>-attribute and <I>a'</I> the new <I>j</I>-attribute created due to the disconnection. If set, the dynamic on-split function of <i>j</i>-attributes is also called on <I>a</I> and <I>a'</I>.
|
||||
|
||||
\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<i>`
|
||||
\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<InputIterator>`
|
||||
\sa `is_removable<i>()`
|
||||
\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<InputIterator>()`
|
||||
*/
|
||||
template <unsigned int i>
|
||||
size_type remove_cell(Dart_descriptor d);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#include <CGAL/Combinatorial_map.h>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
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="
|
||||
<<cm.is_valid()<<std::endl;
|
||||
|
||||
std::size_t nb=0;
|
||||
for(Dart_descriptor dh=cm.darts().begin(); dh!=cm.darts().end(); ++dh)
|
||||
{ if (cm.is_free<2>(dh)) ++nb; }
|
||||
std::cout<<"Number of 2-free darts: "<<nb<<std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1639,11 +1639,14 @@ namespace CGAL {
|
|||
static_assert(i<=dimension);
|
||||
static_assert(Helper::template Dimension_index<i>::value>=0,
|
||||
"set_attribute<i> but i-attributes are disabled");
|
||||
for ( typename Dart_of_cell_range<i>::iterator it(*this, dh);
|
||||
it.cont(); ++it)
|
||||
for (typename Dart_of_cell_range<i>::iterator it(*this, dh);
|
||||
it.cont(); ++it)
|
||||
{
|
||||
this->template set_dart_attribute<i>(it, ah);
|
||||
}
|
||||
if(ah!=null_descriptor)
|
||||
// To ensure that the dart of this attribute is dh
|
||||
{ this->template set_dart_of_attribute<i>(ah, dh); }
|
||||
}
|
||||
|
||||
/// @return a Attributes_range<i> (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<Self,1> 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<Self,1> 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<Self,1> 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<Self, 2>::run(*this, d1, d2);
|
||||
if(merge)
|
||||
{ // Here we group all enabled attributes starting from 2 to dimension
|
||||
Helper::template Foreach_enabled_attributes
|
||||
<internal::Group_attribute_functor<Self>, 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
|
||||
<internal::Group_neighboor_attribute<Self>, 3>::run(*this, adart1, adart2);
|
||||
}
|
||||
else // Here we degroup 2-attributes
|
||||
{ internal::Degroup_attribute_functor_run<Self, 2>::run(*this, adart1, adart2); }
|
||||
}
|
||||
|
||||
negate_mark(m1);
|
||||
|
|
|
|||
|
|
@ -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 <i>-attributes of beta_i(d1) and
|
||||
* beta_i(d2) if they exist.
|
||||
*
|
||||
* Degroup_attribute_functor_run<CMap> to degroup one i-attributes in two
|
||||
* (except for j-adim).
|
||||
*
|
||||
* Test_split_attribute_functor<CMap,i> 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<CMap, i> 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<i>(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<i>(a1)==adart1)
|
||||
{ amap.template set_dart_of_attribute<i>(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<i>(toSet, a1);
|
||||
if(dart1_deleted && toSet==adart1)
|
||||
{ amap.template set_dart_of_attribute<i>(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<CMap, 0, j, T>
|
|||
{
|
||||
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<CMap, 0, j, T>
|
|||
}
|
||||
}
|
||||
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<CMap, 0, 0, T>
|
|||
{
|
||||
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<CMap, 0, 0, T>
|
|||
}
|
||||
}
|
||||
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<CMap, 0, 1, T>
|
|||
{
|
||||
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<CMap,i,i,T>
|
|||
{
|
||||
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<CMap,1,0,T>
|
|||
{
|
||||
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<CMap, i, j, T>::run(amap, d1, d2); }
|
||||
typename CMap::Dart_descriptor d2,
|
||||
bool dart1_deleted=true)
|
||||
{ Group_nonvoid_attribute_functor_run<CMap, i, j, T>::
|
||||
run(amap, d1, d2, dart1_deleted); }
|
||||
};
|
||||
// Specialization for void attributes.
|
||||
template<typename CMap, unsigned int i, unsigned int j>
|
||||
|
|
@ -441,7 +467,8 @@ struct Group_attribute_functor_run<CMap, i, j, CGAL::Void>
|
|||
{
|
||||
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<typename CMap>
|
||||
struct Group_neighboor_attribute
|
||||
{
|
||||
template<unsigned int i>
|
||||
static void run(CMap& amap, typename CMap::Dart_descriptor d1,
|
||||
typename CMap::Dart_descriptor d2)
|
||||
{
|
||||
if(!amap.template is_free<i>(d1) && !amap.template is_free<i>(d2))
|
||||
{
|
||||
CGAL::internal::Group_attribute_functor_run<CMap, i>::run
|
||||
(amap, amap.template opposite<i>(d1), amap.template opposite<i>(d2), false);
|
||||
}
|
||||
}
|
||||
};
|
||||
// ************************************************************************
|
||||
// Functor used to degroup one i-attribute of one i-cell in two, except the
|
||||
// attribute of j.
|
||||
template<typename CMap, unsigned int i, unsigned int j=CMap::dimension+1,
|
||||
|
|
@ -1022,6 +1065,28 @@ struct Test_split_attribute_functor
|
|||
}
|
||||
};
|
||||
// ************************************************************************
|
||||
template<typename CMap, unsigned int i,
|
||||
typename T=typename CMap::template Attribute_type<i>::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<i>(d1)!=CMap::null_descriptor &&
|
||||
amap.template dart<i>(d1)!=CMap::null_descriptor &&
|
||||
amap.is_marked(amap.template dart<i>(d1), amark))
|
||||
{ amap.template dart<i>(d1)=d1; }
|
||||
}
|
||||
};
|
||||
// Specialization for void attributes.
|
||||
template<typename CMap, unsigned int i>
|
||||
struct Set_dart_of_attribute_if_marked<CMap, i, CGAL::Void>
|
||||
{
|
||||
static void run(CMap&, typename CMap::Dart_descriptor,
|
||||
typename CMap::size_type)
|
||||
{}
|
||||
};
|
||||
// ************************************************************************
|
||||
} // namespace internal
|
||||
} // namespace CGAL
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <class Functor,class T,int n=0>
|
||||
template <class Functor,class T,int n=0, int startn=0>
|
||||
struct Foreach_static_restricted;
|
||||
|
||||
template <class Functor,class Head, class ... Items,int n>
|
||||
template <class Functor,class Head, class ... Items,int n, int startn>
|
||||
struct Foreach_static_restricted<Functor,
|
||||
std::tuple<Head,Items...>,n>
|
||||
std::tuple<Head,Items...>,n, startn>
|
||||
{
|
||||
template <class ... T>
|
||||
static void run(T& ... t){
|
||||
Conditionnal_run<Functor,n,Head>::run(t...);
|
||||
if(n>=startn)
|
||||
{ Conditionnal_run<Functor,n,Head>::run(t...); }
|
||||
Foreach_static_restricted
|
||||
<Functor,std::tuple<Items...>,n+1>::run(t...);
|
||||
<Functor,std::tuple<Items...>, n+1, startn>::run(t...);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Functor,int n>
|
||||
struct Foreach_static_restricted<Functor,std::tuple<>,n>{
|
||||
template <class Functor,int n, int startn>
|
||||
struct Foreach_static_restricted<Functor,std::tuple<>,n, startn>{
|
||||
template <class ... T>
|
||||
static void run(T& ... ){}
|
||||
};
|
||||
|
|
@ -609,13 +610,13 @@ namespace CGAL
|
|||
struct Attribute_const_range<d, CGAL::Void>
|
||||
{ typedef CGAL::Void type; };
|
||||
|
||||
// To iterate onto each enabled attributes
|
||||
template <class Functor>
|
||||
// To iterate onto each enabled attributes, starting from startn-attributes (0 by default)
|
||||
template <class Functor, int startn=0>
|
||||
struct Foreach_enabled_attributes
|
||||
{
|
||||
template <class ...Ts>
|
||||
static void run(Ts& ... t)
|
||||
{ Foreach_static_restricted<Functor, Attributes>::run(t...); }
|
||||
{ Foreach_static_restricted<Functor, Attributes, 0, startn>::run(t...); }
|
||||
};
|
||||
// To iterate onto each enabled attributes, except j-attributes
|
||||
template <class Functor, unsigned int j>
|
||||
|
|
|
|||
|
|
@ -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<CMap, i+1>::
|
||||
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<CMap, i+1>::
|
||||
run(amap, d1, mark);
|
||||
|
||||
if ( d2!=amap.null_dart_descriptor && d1!=d2 )
|
||||
{
|
||||
amap.template basic_link_beta<i>(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<CMap, 1>::
|
||||
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<CMap, 1>::
|
||||
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<CMap,i-1>::
|
||||
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<CMap, 0, 1>::
|
||||
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
|
||||
|
|
|
|||
|
|
@ -738,6 +738,9 @@ public:
|
|||
size_type index(const_iterator cit) const
|
||||
{ return static_cast<size_type>(cit); }
|
||||
|
||||
size_type index(Index idx) const
|
||||
{ return static_cast<size_type>(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.
|
||||
|
|
|
|||
|
|
@ -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);"<<std::endl;
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
map.clear();
|
||||
|
||||
cout << "***************************** TEST INSERT EDGE 3D DONE."
|
||||
|
|
|
|||
|
|
@ -399,6 +399,8 @@ Example of \link GenericMap::insert_cell_1_in_cell_2 `insert_cell_1_in_cell_2`\e
|
|||
|
||||
`gm.`\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 `gm.darts()`\endlink.
|
||||
|
||||
`gm.`\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 <I>d1</I>\f$ \not \in \f$ \f$ \langle{}\f$\f$ \alpha_0, \alpha_1\f$\f$ \rangle{}\f$(<I>d2</I>) 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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
#include <CGAL/Generalized_map.h>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
|
||||
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="
|
||||
<<gm.is_valid()<<std::endl;
|
||||
|
||||
std::size_t nb=0;
|
||||
for(Dart_descriptor dh=gm.darts().begin(); dh!=gm.darts().end(); ++dh)
|
||||
{ if (gm.is_free<2>(dh)) ++nb; }
|
||||
std::cout<<"Number of 2-free darts: "<<nb<<std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1464,11 +1464,14 @@ namespace CGAL {
|
|||
static_assert(i<=dimension);
|
||||
static_assert(Helper::template Dimension_index<i>::value>=0,
|
||||
"set_attribute<i> but i-attributes are disabled");
|
||||
for ( typename Dart_of_cell_range<i>::iterator it(*this, dh);
|
||||
it.cont(); ++it)
|
||||
for (typename Dart_of_cell_range<i>::iterator it(*this, dh);
|
||||
it.cont(); ++it)
|
||||
{
|
||||
this->template set_dart_attribute<i>(it, ah);
|
||||
}
|
||||
if(ah!=null_descriptor)
|
||||
// To ensure that the dart of this attribute is dh
|
||||
{ this->template set_dart_of_attribute<i>(ah, dh); }
|
||||
}
|
||||
|
||||
/// @return a Attributes_range<i> (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<Self,0,1> 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<Self,0,1> 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<Self,1> will contain all
|
||||
* alpha_i except alpha_0, alpha_1 and alpha_2, i.e. this is
|
||||
* <alpha_3,...,alpha_d>
|
||||
*/
|
||||
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<Self,1> it1(*this, adart1, m1);
|
||||
|
||||
size_type m2=get_new_mark();
|
||||
CGAL::GMap_dart_iterator_basic_of_involution<Self,1> it2(*this, adart2, m2);
|
||||
CGAL::GMap_dart_iterator_basic_of_involution<Self,1> 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<Self, 2>::
|
||||
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
|
||||
<internal::Group_attribute_functor<Self>, 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
|
||||
<internal::Group_neighboor_attribute<Self>, 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<Self, 2>::
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -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<i>(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<i>(a1)==adart1)
|
||||
{ amap.template set_dart_of_attribute<i>(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<i>(toSet, a1);
|
||||
if(dart1_deleted && toSet==adart1)
|
||||
{ amap.template set_dart_of_attribute<i>(a1, adart2); }
|
||||
}
|
||||
};
|
||||
// Specialization for void attributes.
|
||||
template<typename GMap, unsigned int i, unsigned int j>
|
||||
struct GMap_group_attribute_functor_run<GMap, i, j, CGAL::Void>
|
||||
{
|
||||
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<GMap,i,i,T>
|
|||
{
|
||||
static void run(GMap&,
|
||||
typename GMap::Dart_descriptor,
|
||||
typename GMap::Dart_descriptor)
|
||||
typename GMap::Dart_descriptor,
|
||||
bool=true)
|
||||
{}
|
||||
};
|
||||
// ************************************************************************
|
||||
|
|
|
|||
|
|
@ -91,8 +91,9 @@ namespace CGAL
|
|||
it.cont(); ++it )
|
||||
{
|
||||
to_erase.push_back(it);
|
||||
if ( !amap.template is_free<i+1>(it) && dg1==amap.null_descriptor )
|
||||
{ dg1=it; dg2=amap.template alpha<i+1>(it); }
|
||||
if (dg1==amap.null_descriptor && !amap.template is_free<i+1>(it) &&
|
||||
!amap.template is_free<i>(amap.template alpha<i+1>(it)))
|
||||
{ dg1=it; dg2=amap.template alpha<i+1, i>(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<GMap, i+1>::
|
||||
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<GMap, i+1>::
|
||||
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<GMap,i-1>::
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ bool test(const std::string& s)
|
|||
for(std::size_t i=0; i<NB; ++i)
|
||||
{
|
||||
typename GMap::Dart_descriptor
|
||||
newd=m.insert_cell_1_in_cell_2(dd, m.template alpha<0,1,0>(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: "<<s<<": "
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ Release date: October 2023
|
|||
- **Breaking change**: C++17 is now required
|
||||
- Support for Visual `C++` 14.0 (Visual studio 2015) is dropped.
|
||||
|
||||
### [Combinatorial Maps](https://doc.cgal.org/6.0/Manual/packages.html#PkgCombinatorialMaps) and [Generalized Maps](https://doc.cgal.org/6.0/Manual/packages.html#PkgGeneralizedMaps)
|
||||
|
||||
- Added the function `insert_cell_1_between_two_cells_2()` to the `GenericMap` concept, which enables users to insert an edge between two different faces in order to create faces with holes.
|
||||
|
||||
[Release 5.6](https://github.com/CGAL/cgal/releases/tag/v5.6)
|
||||
-----------
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ The class `Linear_cell_complex_min_items<d>` 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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
#include <CGAL/Linear_cell_complex_for_combinatorial_map.h>
|
||||
#include <CGAL/Linear_cell_complex_for_generalized_map.h>
|
||||
#include <CGAL/draw_linear_cell_complex.h>
|
||||
|
||||
typedef CGAL::Linear_cell_complex_for_combinatorial_map<3> LCC1;
|
||||
typedef CGAL::Linear_cell_complex_for_generalized_map<3> LCC2;
|
||||
|
||||
template<typename LCC>
|
||||
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<LCC1>();
|
||||
test<LCC2>();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -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<char*>(this))
|
||||
MonInfo(long long int i=0) : mnb(i==0?rand():static_cast<int>(i)),
|
||||
ptr(reinterpret_cast<char*>(this))
|
||||
{}
|
||||
|
||||
bool operator==(const MonInfo& info) const
|
||||
|
|
|
|||
|
|
@ -45,20 +45,103 @@ void trace_display_msg(const char* msg)
|
|||
#endif
|
||||
}
|
||||
|
||||
template<typename LCC,
|
||||
typename Map=typename LCC::Combinatorial_data_structure>
|
||||
struct Alpha1
|
||||
template<typename Map, int i, typename Info=
|
||||
typename Map::template Attribute_type<i>::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<i>::type attr,
|
||||
long long int nb)
|
||||
{
|
||||
map.template info_of_attribute<i>(attr)=
|
||||
typename Map::template Attribute_type<i>::type::Info(nb);
|
||||
}
|
||||
};
|
||||
template<typename LCC>
|
||||
struct Alpha1<LCC, CGAL::Generalized_map_tag>
|
||||
template<typename Map, int i>
|
||||
struct SetInfoIfNonVoid<Map, i, void>
|
||||
{
|
||||
static typename LCC::Dart_descriptor run(LCC& lcc, typename LCC::Dart_descriptor dh)
|
||||
{ return lcc.template alpha<1>(dh); }
|
||||
static void run(Map&, typename Map::template Attribute_descriptor<i>::type,
|
||||
long long int)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename Map, unsigned int i, typename Attr=typename Map::
|
||||
template Attribute_type<i>::type>
|
||||
struct CreateAttributes
|
||||
{
|
||||
static void run(Map& map)
|
||||
{
|
||||
long long int nb=0;
|
||||
for(typename Map::Dart_range::iterator it=map.darts().begin(),
|
||||
itend=map.darts().end(); it!=itend; ++it)
|
||||
{
|
||||
if ( map.template attribute<i>(it)==map.null_descriptor )
|
||||
{
|
||||
map.template set_attribute<i>(it, map.template create_attribute<i>());
|
||||
SetInfoIfNonVoid<Map, i>::run(map, map.template attribute<i>(it), ++nb);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Map, typename Attr>
|
||||
struct CreateAttributes<Map, 0, Attr>
|
||||
{
|
||||
static void run(Map& amap)
|
||||
{
|
||||
long long int nb=0;
|
||||
for ( typename Map::template Attribute_range<0>::type::iterator
|
||||
it=amap.template attributes<0>().begin(),
|
||||
itend=amap.template attributes<0>().end(); it!=itend; ++it )
|
||||
SetInfoIfNonVoid<Map, 0>::run(amap, it, ++nb);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Map, unsigned int i>
|
||||
struct CreateAttributes<Map, i, CGAL::Void>
|
||||
{
|
||||
static void run(Map&)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename Map>
|
||||
struct CreateAttributes<Map, 0, CGAL::Void>
|
||||
{
|
||||
static void run(Map&)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename Map, typename Info=typename Map::Dart_info>
|
||||
struct InitDartInfo
|
||||
{
|
||||
static void run(Map& map)
|
||||
{
|
||||
long long int nb=0;
|
||||
for(typename Map::Dart_range::iterator it=map.darts().begin(),
|
||||
itend=map.darts().end(); it!=itend; ++it)
|
||||
{
|
||||
nb=CGAL::get_default_random().get_int(0,20000);
|
||||
map.info(it)=Info(nb);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Map>
|
||||
struct InitDartInfo<Map, CGAL::Void>
|
||||
{
|
||||
static void run(Map&)
|
||||
{}
|
||||
};
|
||||
|
||||
template<typename Map>
|
||||
void create_attributes_2(Map& map)
|
||||
{
|
||||
CreateAttributes<Map, 0>::run(map);
|
||||
CreateAttributes<Map, 1>::run(map);
|
||||
CreateAttributes<Map, 2>::run(map);
|
||||
InitDartInfo<Map>::run(map);
|
||||
}
|
||||
|
||||
// Test orientation specialized below only for CMap. For GMap return true.
|
||||
template<typename LCC, typename Map=typename LCC::Combinatorial_data_structure>
|
||||
struct Test_change_orientation_LCC_2
|
||||
|
|
|
|||
|
|
@ -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<char*>(this))
|
||||
MonInfo(long long int i=0) : mnb(i==0?rand():static_cast<int>(i)),
|
||||
ptr(reinterpret_cast<char*>(this))
|
||||
{}
|
||||
|
||||
bool operator==(const MonInfo& info) const
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
#include "Linear_cell_complex_2_test.h"
|
||||
#include <fstream>
|
||||
#include <typeinfo>
|
||||
|
||||
template<typename LCC>
|
||||
bool check_number_of_cells_3(LCC& lcc, unsigned int nbv, unsigned int nbe,
|
||||
unsigned int nbf, unsigned int nbvol,
|
||||
|
|
@ -63,6 +62,13 @@ bool check_number_of_cells_3(LCC& lcc, unsigned int nbv, unsigned int nbe,
|
|||
return true;
|
||||
}
|
||||
|
||||
template<typename Map>
|
||||
void create_attributes_3(Map& map)
|
||||
{
|
||||
create_attributes_2(map);
|
||||
CreateAttributes<Map, 3>::run(map);
|
||||
}
|
||||
|
||||
template<typename LCC>
|
||||
typename LCC::Dart_descriptor make_loop(LCC& lcc, const typename LCC::Point& p1)
|
||||
{
|
||||
|
|
@ -96,6 +102,7 @@ bool test_LCC_3()
|
|||
Dart_descriptor dh1=lcc.make_segment(Point(0,0,0),Point(1,0,0), true);
|
||||
Dart_descriptor dh2=lcc.make_segment(Point(2,0,0),Point(2,1,0), true);
|
||||
Dart_descriptor dh3=lcc.make_segment(Point(2,2,0),Point(3,1,0), true);
|
||||
create_attributes_3(lcc);
|
||||
if ( !check_number_of_cells_3(lcc, 6, 3, 6, 3, 3) )
|
||||
return false;
|
||||
|
||||
|
|
@ -320,6 +327,7 @@ bool test_LCC_3()
|
|||
dh1 = lcc.make_triangle(Point(5,5,3),Point(7,5,3),Point(6,6,3));
|
||||
dh2 = lcc.make_triangle(Point(5,4,3),Point(7,4,3),Point(6,3,3));
|
||||
lcc.template sew<3>(dh1, dh2);
|
||||
create_attributes_3(lcc);
|
||||
dh2 = lcc.previous(dh1); dh3 = lcc.next(dh1);
|
||||
|
||||
lcc.template contract_cell<1>(dh1);
|
||||
|
|
@ -341,6 +349,7 @@ bool test_LCC_3()
|
|||
trace_test_begin();
|
||||
dh1 = lcc.make_triangle(Point(5,5,3),Point(7,5,3),Point(6,6,3));
|
||||
dh2 = lcc.make_triangle(Point(5,4,3),Point(7,4,3),Point(6,3,3));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<2>(dh1, dh2);
|
||||
|
||||
dh2 = lcc.next(dh2);
|
||||
|
|
@ -373,6 +382,7 @@ bool test_LCC_3()
|
|||
trace_test_begin();
|
||||
dh1 = lcc.make_triangle(Point(5,5,3),Point(7,5,3),Point(6,6,3));
|
||||
dh2 = lcc.make_triangle(Point(5,4,3),Point(7,4,3),Point(6,3,3));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<2>(dh1, dh2);
|
||||
|
||||
dh2 = lcc.next(dh2);
|
||||
|
|
@ -405,6 +415,7 @@ bool test_LCC_3()
|
|||
trace_test_begin();
|
||||
dh1 = lcc.make_triangle(Point(5,5,3),Point(7,5,3),Point(6,6,3));
|
||||
dh2 = lcc.make_triangle(Point(5,4,3),Point(7,4,3),Point(6,3,3));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<2>(dh1, dh2);
|
||||
|
||||
dh3 = lcc.make_triangle(Point(5,5,4),Point(7,5,4),Point(6,6,4));
|
||||
|
|
@ -445,6 +456,7 @@ bool test_LCC_3()
|
|||
trace_test_begin();
|
||||
dh1 = lcc.make_triangle(Point(5,5,3),Point(7,5,3),Point(6,6,3));
|
||||
dh2 = lcc.make_triangle(Point(5,4,3),Point(7,4,3),Point(6,3,3));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<2>(dh1, dh2);
|
||||
|
||||
dh3 = lcc.make_triangle(Point(5,5,4),Point(7,5,4),Point(6,6,4));
|
||||
|
|
@ -483,6 +495,7 @@ bool test_LCC_3()
|
|||
trace_test_begin();
|
||||
dh1 = lcc.make_tetrahedron(Point(9, 9, 0),Point(9, 0, 9),
|
||||
Point(0, 9, 9),Point(0, 0, 0));
|
||||
create_attributes_3(lcc);
|
||||
typename LCC::Vector v=CGAL::compute_normal_of_cell_0(lcc, dh1);
|
||||
if (v!=typename LCC::Vector(-9,-9,9))
|
||||
{
|
||||
|
|
@ -496,7 +509,7 @@ bool test_LCC_3()
|
|||
dh1 = lcc.
|
||||
make_hexahedron(Point(0,0,0),Point(1,0,0),Point(1,2,0),Point(0,2,0),
|
||||
Point(0,3,4),Point(0,0,4),Point(6,0,4),Point(6,3,4));
|
||||
|
||||
create_attributes_3(lcc);
|
||||
v=CGAL::compute_normal_of_cell_2(lcc, lcc.template
|
||||
opposite<2>(lcc.previous(dh1)));
|
||||
if (v!=typename LCC::Vector(0,0,1))
|
||||
|
|
@ -529,6 +542,7 @@ bool test_LCC_3()
|
|||
make_hexahedron(Point(0,3,0),Point(1,3,0),Point(1,4,0),Point(0,4,0),
|
||||
Point(0,4,1),Point(0,3,1),Point(1,3,1),Point(1,4,1));
|
||||
dh2 = lcc.template opposite<2>(lcc.next(lcc.next(lcc.template opposite<2>(dh2))));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<3>(dh1,dh2);
|
||||
|
||||
lcc.template contract_cell<1>(lcc.previous(dh1));
|
||||
|
|
@ -560,12 +574,14 @@ bool test_LCC_3()
|
|||
|
||||
trace_test_begin();
|
||||
dh1 = make_loop<LCC>(lcc, Point(0,0,0));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template contract_cell<2>(dh1);
|
||||
if ( !check_number_of_cells_3(lcc, 0, 0, 0, 0, 0) )
|
||||
return false;
|
||||
|
||||
trace_test_begin();
|
||||
dh1 = lcc.make_segment(Point(0,0,0),Point(1,0,0), true);
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<1>(lcc.template opposite<2>(dh1),
|
||||
lcc.other_orientation(lcc.template opposite<2>(dh1)));
|
||||
lcc.template contract_cell<2>(dh1);
|
||||
|
|
@ -575,6 +591,7 @@ bool test_LCC_3()
|
|||
|
||||
trace_test_begin();
|
||||
dh1 = lcc.make_segment(Point(0,0,0),Point(1,0,0),true);
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<1>(dh1, lcc.other_orientation(dh1));
|
||||
lcc.template sew<1>(lcc.template opposite<2>(dh1),
|
||||
lcc.other_orientation(lcc.template opposite<2>(dh1)));
|
||||
|
|
@ -586,6 +603,7 @@ bool test_LCC_3()
|
|||
trace_test_begin();
|
||||
dh1 = make_face_two_edges(lcc, Point(0,0,0), Point(1,0,0));
|
||||
dh2 = make_face_two_edges(lcc, Point(0,0,1), Point(1,0,1));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<2>(dh1, dh2);
|
||||
lcc.template contract_cell<2>(dh1);
|
||||
if ( !check_number_of_cells_3(lcc, 2, 2, 1, 1, 1) )
|
||||
|
|
@ -600,6 +618,7 @@ bool test_LCC_3()
|
|||
dh1 = lcc.make_triangle(Point(5,5,3),Point(7,5,3),Point(6,6,3));
|
||||
dh2 = lcc.make_triangle(Point(5,4,3),Point(7,4,3),Point(6,3,3));
|
||||
dh3 = lcc.make_triangle(Point(5,3,3),Point(7,3,3),Point(6,0,3));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<2>(dh1, dh2);
|
||||
lcc.template sew<2>(lcc.next(dh2), dh3);
|
||||
|
||||
|
|
@ -615,6 +634,7 @@ bool test_LCC_3()
|
|||
|
||||
trace_test_begin();
|
||||
dh1 = lcc.create_dart(Point(0,0,0));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<3>(dh1, lcc.create_dart(Point(1,0,0)));
|
||||
lcc.template contract_cell<2>(dh1);
|
||||
if ( !check_number_of_cells_3(lcc, 0, 0, 0, 0, 0) )
|
||||
|
|
@ -623,6 +643,7 @@ bool test_LCC_3()
|
|||
trace_test_begin();
|
||||
dh1 = make_loop(lcc, Point(0,0,0));
|
||||
dh2 = make_loop(lcc, Point(0,0,1));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<3>(dh1, dh2);
|
||||
lcc.template contract_cell<2>(dh1);
|
||||
if ( !check_number_of_cells_3(lcc, 0, 0, 0, 0, 0) )
|
||||
|
|
@ -630,6 +651,7 @@ bool test_LCC_3()
|
|||
|
||||
trace_test_begin();
|
||||
dh1 = lcc.make_segment(Point(0,0,0),Point(1,0,0), true);
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<3>(dh1, lcc.make_segment(Point(0,0,1),Point(1,0,1), true));
|
||||
lcc.template sew<3>(lcc.template opposite<2>(dh1),
|
||||
lcc.template opposite<2>(lcc.template opposite<3>(dh1)));
|
||||
|
|
@ -640,8 +662,10 @@ bool test_LCC_3()
|
|||
|
||||
trace_test_begin();
|
||||
dh1 = lcc.make_segment(Point(0,0,0),Point(1,0,0), true);
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<1>(dh1, lcc.other_orientation(dh1));
|
||||
dh2 = lcc.make_segment(Point(0,0,1),Point(1,0,1), true);
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<1>(dh2, lcc.other_orientation(dh2));
|
||||
lcc.template sew<3>(dh1, dh2);
|
||||
lcc.template contract_cell<2>(dh1);
|
||||
|
|
@ -651,10 +675,12 @@ bool test_LCC_3()
|
|||
|
||||
trace_test_begin();
|
||||
dh1 = lcc.make_segment(Point(0,0,0),Point(1,0,0), true);
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<1>(dh1, lcc.other_orientation(dh1));
|
||||
lcc.template sew<1>(lcc.template opposite<2>(dh1),
|
||||
lcc.other_orientation(lcc.template opposite<2>(dh1)));
|
||||
dh2 = lcc.make_segment(Point(0,0,1),Point(1,0,1), true);
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<1>(dh2, lcc.other_orientation(dh2));
|
||||
lcc.template sew<1>(lcc.template opposite<2>(dh2),
|
||||
lcc.other_orientation(lcc.template opposite<2>(dh2)));
|
||||
|
|
@ -669,6 +695,7 @@ bool test_LCC_3()
|
|||
trace_test_begin();
|
||||
dh1 = make_face_two_edges(lcc, Point(0,0,0), Point(1,0,0));
|
||||
dh2 = make_face_two_edges(lcc, Point(0,0,1), Point(1,0,1));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<2>(dh1, dh2);
|
||||
lcc.template sew<3>(dh1,
|
||||
make_face_two_edges(lcc, Point(0,0,1), Point(1,0,1)));
|
||||
|
|
@ -686,6 +713,7 @@ bool test_LCC_3()
|
|||
trace_test_begin();
|
||||
dh1 = make_face_two_edges(lcc, Point(0,0,0), Point(1,0,0));
|
||||
dh2 = make_face_two_edges(lcc, Point(0,0,1), Point(1,0,1));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<2>(dh1, dh2);
|
||||
lcc.template sew<3>(dh1,
|
||||
make_face_two_edges(lcc, Point(0,0,1), Point(1,0,1)));
|
||||
|
|
@ -706,6 +734,7 @@ bool test_LCC_3()
|
|||
dh1 = lcc.make_triangle(Point(5,5,3),Point(7,5,3),Point(6,6,3));
|
||||
dh2 = lcc.make_triangle(Point(5,4,3),Point(7,4,3),Point(6,3,3));
|
||||
dh3 = lcc.make_triangle(Point(5,3,3),Point(7,3,3),Point(6,0,3));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<2>(dh1, dh2);
|
||||
lcc.template sew<2>(lcc.next(dh2), dh3);
|
||||
lcc.template sew<3>(dh1, lcc.make_triangle(Point(5,5,4),Point(7,5,4),
|
||||
|
|
@ -737,18 +766,21 @@ bool test_LCC_3()
|
|||
|
||||
trace_test_begin();
|
||||
dh1 = make_loop<LCC>(lcc, Point(0,0,0));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template contract_cell<3>(dh1);
|
||||
if ( !check_number_of_cells_3(lcc, 0, 0, 0, 0, 0) )
|
||||
return false;
|
||||
|
||||
trace_test_begin();
|
||||
dh1 = lcc.make_segment(Point(0,0,0),Point(1,0,0));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template contract_cell<3>(dh1);
|
||||
if ( !check_number_of_cells_3(lcc, 0, 0, 0, 0, 0) )
|
||||
return false;
|
||||
|
||||
trace_test_begin();
|
||||
dh1 = lcc.make_segment(Point(0,0,0),Point(1,0,0), true);
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<1>(dh1, lcc.other_orientation(dh1));
|
||||
lcc.template sew<1>(lcc.template opposite<2>(dh1),
|
||||
lcc.other_orientation(lcc.template opposite<2>(dh1)));
|
||||
|
|
@ -764,6 +796,7 @@ bool test_LCC_3()
|
|||
dh2 = lcc.
|
||||
make_hexahedron(Point(0,3,0),Point(1,3,0),Point(1,4,0),Point(0,4,0),
|
||||
Point(0,4,1),Point(0,3,1),Point(1,3,1),Point(1,4,1));
|
||||
create_attributes_3(lcc);
|
||||
dh2 = lcc.template opposite<2>(lcc.next(lcc.next(lcc.template opposite<2>(dh2))));
|
||||
lcc.template sew<3>(dh1,dh2);
|
||||
|
||||
|
|
@ -813,6 +846,7 @@ bool test_LCC_3()
|
|||
dh3 = lcc.
|
||||
make_hexahedron(Point(0,6,0),Point(1,6,0),Point(1,7,0),Point(0,7,0),
|
||||
Point(0,7,1),Point(0,6,1),Point(1,6,1),Point(1,7,1));
|
||||
create_attributes_3(lcc);
|
||||
dh3 = lcc.template opposite<2>(lcc.next(lcc.next(lcc.template opposite<2>(dh3))));
|
||||
lcc.template sew<3>(dh2,dh3);
|
||||
dh2 = lcc.template opposite<2>(lcc.next(lcc.next(lcc.template opposite<2>(dh2))));
|
||||
|
|
@ -861,6 +895,12 @@ bool test_LCC_3()
|
|||
Point(1,2,0),Point(0,2,0),
|
||||
Point(0,3,4),Point(0,0,4),
|
||||
Point(6,0,4),Point(6,3,4));
|
||||
|
||||
dh2=lcc.insert_cell_1_in_cell_2(lcc.next(dh1), lcc.previous(dh1));
|
||||
if ( !check_number_of_cells_3(lcc, 8, 13, 7, 1, 1) )
|
||||
return false;
|
||||
lcc.template remove_cell<1>(dh2);
|
||||
|
||||
dh2 = lcc.
|
||||
make_hexahedron(Point(0,0,4),Point(1,0,4),
|
||||
Point(1,2,4),Point(0,2,4),
|
||||
|
|
@ -871,16 +911,24 @@ bool test_LCC_3()
|
|||
Point(6,2,4),Point(5,2,4),
|
||||
Point(5,3,8),Point(5,0,8),
|
||||
Point(11,0,8),Point(11,3,8));
|
||||
lcc.template sew<3>(dh1,lcc.template opposite<2>(lcc.next(lcc.next(lcc.template opposite<2>(dh2)))));
|
||||
lcc.template sew<3>(lcc.template opposite<2>(lcc.next(dh1)), lcc.template opposite<2>(lcc.previous(dh3)));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<3>(dh1,lcc.template opposite<2>
|
||||
(lcc.next(lcc.next(lcc.template opposite<2>(dh2)))));
|
||||
lcc.template sew<3>(lcc.template opposite<2>(lcc.next(dh1)),
|
||||
lcc.template opposite<2>(lcc.previous(dh3)));
|
||||
|
||||
lcc.template close<3>();
|
||||
if ( !check_number_of_cells_3(lcc, 16, 28, 16, 4, 1) )
|
||||
return false;
|
||||
|
||||
lcc.insert_cell_1_in_cell_2(lcc.next(dh1), Alpha1<LCC>::run(lcc, lcc.previous(dh1)));
|
||||
lcc.insert_cell_1_in_cell_2(lcc.next(dh1), lcc.previous(dh1));
|
||||
if ( !check_number_of_cells_3(lcc, 16, 29, 17, 4, 1) )
|
||||
return false;
|
||||
|
||||
dh2=lcc.template opposite<2>(lcc.next(lcc.next(lcc.template opposite<2>(dh1))));
|
||||
lcc.insert_cell_1_in_cell_2(dh2, Alpha1<LCC>::run(lcc, lcc.next(lcc.next(dh2))));
|
||||
lcc.insert_cell_1_in_cell_2(dh2, lcc.next(lcc.next(dh2)));
|
||||
if ( !check_number_of_cells_3(lcc, 16, 30, 18, 4, 1) )
|
||||
return false;
|
||||
|
||||
std::vector<Dart_descriptor> path;
|
||||
path.push_back(lcc.next(dh1));
|
||||
|
|
@ -891,6 +939,51 @@ bool test_LCC_3()
|
|||
if ( !check_number_of_cells_3(lcc, 16, 30, 19, 5, 1) )
|
||||
return false;
|
||||
|
||||
// Test insertion between two different 2-cells
|
||||
trace_test_begin();
|
||||
lcc.clear();
|
||||
dh1 = lcc.
|
||||
make_hexahedron(Point(0,0,0),Point(1,0,0),
|
||||
Point(1,2,0),Point(0,2,0),
|
||||
Point(0,3,4),Point(0,0,4),
|
||||
Point(6,0,4),Point(6,3,4));
|
||||
dh2 = lcc.
|
||||
make_hexahedron(Point(0,0,4),Point(1,0,4),
|
||||
Point(1,2,4),Point(0,2,4),
|
||||
Point(0,3,8),Point(0,0,8),
|
||||
Point(6,0,8),Point(6,3,8));
|
||||
create_attributes_3(lcc);
|
||||
lcc.template sew<3>(dh1,lcc.template opposite<2>(lcc.next(lcc.next(lcc.template opposite<2>(dh2)))));
|
||||
|
||||
lcc.insert_cell_1_between_two_cells_2(lcc.template opposite<2>(dh1),
|
||||
lcc.template opposite<2>(lcc.next(dh1)));
|
||||
if ( !check_number_of_cells_3(lcc, 12, 21, 10, 2, 1) )
|
||||
return false;
|
||||
|
||||
trace_test_begin();
|
||||
lcc.clear();
|
||||
dh1=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));
|
||||
dh2=lcc.make_hexahedron(Point(5,0,0), Point(10,0,0),
|
||||
Point(10,5,0), Point(5,5,0),
|
||||
Point(5,5,4), Point(5,0,4),
|
||||
Point(10,0,4), Point(10,5,4));
|
||||
dh3=lcc.make_quadrangle(Point(5,2,2), Point(5,1,2),
|
||||
Point(5,1,1), Point(5,2,1));
|
||||
lcc.template sew<3>(lcc.template opposite<2>(lcc.next(lcc.next(dh1))),
|
||||
lcc.other_orientation(lcc.template opposite<2>(dh2)));
|
||||
lcc.template sew<3>(dh3, lcc.make_combinatorial_polygon(4));
|
||||
create_attributes_3(lcc);
|
||||
|
||||
// Create an hole in the face between the two cubes
|
||||
lcc.insert_cell_1_between_two_cells_2(lcc.template opposite<2>(lcc.next(lcc.next(dh1))),
|
||||
lcc.next(lcc.next(dh3)));
|
||||
|
||||
if (!check_number_of_cells_3(lcc, 16, 25, 11, 2, 1) )
|
||||
return false;
|
||||
|
||||
// Construction from Polyhedron_3
|
||||
{
|
||||
trace_test_begin();
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ struct Myattrib : public CGAL::Cell_attribute_with_point
|
|||
|
||||
struct MonInfo
|
||||
{
|
||||
MonInfo(int i=0) : mnb(i==0?rand():i), ptr(reinterpret_cast<char*>(this))
|
||||
MonInfo(long long int i=0) : mnb(i==0?rand():static_cast<int>(i)),
|
||||
ptr(reinterpret_cast<char*>(this))
|
||||
{}
|
||||
|
||||
bool operator==(const MonInfo& info) const
|
||||
|
|
|
|||
|
|
@ -377,9 +377,9 @@ bool test_LCC_4()
|
|||
if ( !check_number_of_cells_4(lcc, 16, 28, 16, 4, 2, 1) )
|
||||
return false;
|
||||
|
||||
lcc.insert_cell_1_in_cell_2(lcc.next(dh1), Alpha1<LCC>::run(lcc, lcc.previous(dh1)));
|
||||
lcc.insert_cell_1_in_cell_2(lcc.next(dh1), lcc.previous(dh1));
|
||||
dh2=lcc.template opposite<2>(lcc.next(lcc.next(lcc.template opposite<2>(dh1))));
|
||||
lcc.insert_cell_1_in_cell_2(dh2, Alpha1<LCC>::run(lcc, lcc.next(lcc.next(dh2))));
|
||||
lcc.insert_cell_1_in_cell_2(dh2, lcc.next(lcc.next(dh2)));
|
||||
|
||||
std::vector<Dart_descriptor> path;
|
||||
path.push_back(lcc.next(dh1));
|
||||
|
|
|
|||
Loading…
Reference in New Issue