diff --git a/.gitattributes b/.gitattributes index c0947049cd9..53234b2f162 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4051,8 +4051,8 @@ Testsuite/test/run_testsuite_with_cmake -text Triangulation/TODO -text Triangulation/benchmark/Triangulation/delaunay.cpp -text Triangulation/doc_tex/Triangulation/PkgDescription.tex -text -Triangulation/doc_tex/Triangulation/fig/detail.png -text -Triangulation/doc_tex/Triangulation/fig/illustration.png -text +Triangulation/doc_tex/Triangulation/fig/barycentric-subdivision.pdf -text +Triangulation/doc_tex/Triangulation/fig/barycentric-subdivision.png -text Triangulation/doc_tex/Triangulation/fig/simplex-structure.pdf -text Triangulation/doc_tex/Triangulation/fig/simplex-structure.png -text Triangulation/doc_tex/Triangulation/main.tex -text diff --git a/Triangulation/TODO b/Triangulation/TODO index ef0cca92e51..1db0e7d146a 100644 --- a/Triangulation/TODO +++ b/Triangulation/TODO @@ -1,4 +1,33 @@ +-------------------------------------------------- +En lisant les reviews +-------------------------------------------------- + +example delaunay does not execute properly + +in Triangulation_data_structure : +put a default value for dim in the constructor +(does not work, I do not understand why). + +check that the perturbation scheme is independant of the order of insertion + + + + + + + + + + + + + + + +-------------------------------------------------- +Vieille liste (mais pas forcement perimee) +-------------------------------------------------- Je me replonge dans Triangulation en dim d ma liste de trucs à faire ou questions à résoudre: diff --git a/Triangulation/doc_tex/Triangulation/fig/barycentric-subdivision.pdf b/Triangulation/doc_tex/Triangulation/fig/barycentric-subdivision.pdf new file mode 100644 index 00000000000..45f49ffedad Binary files /dev/null and b/Triangulation/doc_tex/Triangulation/fig/barycentric-subdivision.pdf differ diff --git a/Triangulation/doc_tex/Triangulation/fig/barycentric-subdivision.png b/Triangulation/doc_tex/Triangulation/fig/barycentric-subdivision.png new file mode 100644 index 00000000000..e9faeb34787 Binary files /dev/null and b/Triangulation/doc_tex/Triangulation/fig/barycentric-subdivision.png differ diff --git a/Triangulation/doc_tex/Triangulation/fig/detail.png b/Triangulation/doc_tex/Triangulation/fig/detail.png deleted file mode 100644 index dfbdd276c12..00000000000 Binary files a/Triangulation/doc_tex/Triangulation/fig/detail.png and /dev/null differ diff --git a/Triangulation/doc_tex/Triangulation/fig/illustration.png b/Triangulation/doc_tex/Triangulation/fig/illustration.png deleted file mode 100644 index 29e5a7a47e7..00000000000 Binary files a/Triangulation/doc_tex/Triangulation/fig/illustration.png and /dev/null differ diff --git a/Triangulation/doc_tex/Triangulation/triangulation.tex b/Triangulation/doc_tex/Triangulation/triangulation.tex index 8e1710887ea..d3f05c35a41 100644 --- a/Triangulation/doc_tex/Triangulation/triangulation.tex +++ b/Triangulation/doc_tex/Triangulation/triangulation.tex @@ -83,6 +83,7 @@ If the maximal dimension of a simplex in the triangulation is $d$, we call:\begin{itemize} \item an $i$-face for some $i\in[0,d]$ a \textbf{face}; \item a $0$-face a \textbf{vertex}; +\item a $1$-face an \textbf{edge}; \item a $(d-2)$-face a \textbf{ridge}; \item a $(d-1)$-face a \textbf{facet}; and \item a $d$-face a \textbf{full cell}. @@ -102,7 +103,7 @@ which \cgal\ provides one model class: \ccc{CGAL::Triangulation_data_structure}. For simplicity, we use the abbreviation \tds. -A \tds\ cannot represent any abstract pure complex, but rather the +A \tds\ cannot represent every abstract pure complex, but rather the combinatorial nature of a (geometric) triangulation. For example, a facet may be incident to arbitrarily many simplices in an abstract pure complex, but to at most two in a \tds\ (and in fact exactly two as we explain below). @@ -115,6 +116,7 @@ A \tds\ also knows the \textbf{current dimension} of its full cells, which can be queried with \ccc{tds.current_dimension()}. In the sequel, let us denote the ambient dimension with \ad\ and the current dimension with \cd. It always holds that $-2\leq\cd\leq\ad$ and $0<\ad$. +The special meaning of negative values for $d$ will be explain below. %\note{I remove some comments about 3D vs dD which are not exact. % %in T3D package in degenerate dimension \ccc{Cell} is actually used with the % @@ -180,14 +182,14 @@ implementing the concept \ccc{TriangulationDataStructure}. \subsubsection{Storage} -A \tds\ explicitely stores its vertices and full cells. +A \tds\ explicitly stores its vertices and full cells. Each vertex stores a reference (a \ccc{handle}) to one of its incident -full cell. +full cells. Each full cell stores references to its $\cd+1$ vertices and -neighbors. Its vertices and neighbors are indexed from $0$ to \cd. The indexes +neighbors. Its vertices and neighbors are indexed from $0$ to \cd. The indices of its neighbors have the following meaning: the $i$-th neighbor of $\sigma$ is the unique neighbor of $\sigma$ that does not contain the $i$-th vertex of $\sigma$; in other words, it is the neighbor of $\sigma$ \textbf{opposite} to @@ -209,7 +211,7 @@ the $i$-th vertex of $\sigma$. \label{triangulation:fig:simplex} \end{figure} -\subsubsection{Instanciating the class template} +\subsubsection{Instantiating the class template} The \ccc{Triangulation_data_structure} class template is designed in such a way that its user can choose @@ -223,12 +225,13 @@ template parameter and The last two parameters have default values and are thus not necessary, unless the user needs custom types (see the reference manual page for this class -template). The first template parameter, \ccc{Dimensionality}, must be either +template). The first template parameter, \ccc{Dimensionality}, must be +one of the following: \begin{itemize} \item \ccPureGlobalScope\ccc{Dimension_tag} for some integer \ad. This indicates that the pure complex can store simplices of dimension at most \ad. The maximum dimension \ad\ is known by the compiler, which -triggers some optimizations. Or +triggers some optimizations. \item \ccPureGlobalScope\ccc{Dynamic_dimension_tag}. In this case, the maximum dimension of the simplices must be passed as an integer argument to an instance constructor (see \ccc{TriangulationDataStructure}). @@ -284,6 +287,24 @@ obtained by enumerating all the faces of \ccc{fc} in order of decreasing dimension, from the dimension of~\ccc{fc} to dimension~1, and inserting a new vertex in each face. For the enumeration, we use a combinatorial enumerator, which is not documented, but provided in \cgal. + + +\begin{figure}[htbp] +\begin{ccTexOnly} +\begin{center} +\includegraphics{Triangulation/fig/barycentric-subdivision.pdf} +\end{center} +\end{ccTexOnly} +\begin{ccHtmlOnly} +
+ +
+\end{ccHtmlOnly} +\caption{Barycentric subdivision in dimension $\cd=2$.} +\label{triangulation:fig:simplex} +\end{figure} + \ccIncludeExampleCode{Triangulation/barycentric_subdivision.cpp} @@ -296,7 +317,8 @@ triangulation into Euclidean space. More precisely, it maintains a triangulation (a partition into pairwise interior-disjoint full cells) of the convex hull of the points (the embedded vertices) of the triangulation, as well as a triangulation of the complement of the convex hull -\textbf{in the affine subspace} spanned by the triangulation's points. +\textbf{in the affine subspace} spanned by the triangulation's points +using a special vertex at infinity. Methods are provided for the insertion of points in the triangulation, the contraction of faces, the traversal of various elements of the triangulation @@ -320,7 +342,7 @@ the oriented hyperplane defined by the cell's finite facet. \subsection{Implementation} The class \ccc{CGAL::Triangulation} stores a model \ccc{TDS} -of the concept \ccc{TriangulationDataStructure} which is instanciated with a +of the concept \ccc{TriangulationDataStructure} which is instantiated with a vertex type that stores a point, and a full cell type that allows the retrieval of the point of its vertices. @@ -352,16 +374,22 @@ points. This gives us a handy way to count the convex hull vertices. \subsubsection{Traversing the facets of the convex hull} -Remember that a triangulation triangulates the convex hull of its vertices. Each +Remember that a triangulation triangulates the convex hull of its +vertices. +In general position, each facet of the convex hull is incident to one finite cell and one infinite cell. In fact there is a bijection between the infinite cells and the -facets of the convex hull. So, in order to traverse the convex hull facets, +facets of the convex hull. +If vertices are not in general position, convex hull faces that are +not simplices are triangulated. +So, in order to traverse the convex hull facets, there are (at least) two possibilities: The first is to iterate over the cells of the triangulation and check if they are infinite or not: \begin{ccExampleCode} +{int i=0; typedef Triangulation::Full_cell_iterator Full_cell_iterator; typedef Triangulation::Facet Facet; @@ -370,8 +398,9 @@ for( Full_cell_iterator fcit = t.full_cells_begin(); if( ! t.is_infinite(fcit) ) continue; Facet ft(fcit, fcit->index(t.infinite_vertex() ) ); - // |ft| is a facet of the convex hull + ++i;// |ft| is a facet of the convex hull } +std::cout << "There are " << i << " facets on the convex hull."<< std::endl;} \end{ccExampleCode}% \textbf{Remark}: the code example above is not self contained, it can be cut and paste at STEP 2 of {\tt triangulation.cpp} program above. @@ -381,6 +410,7 @@ incident to the infinite vertex: they form precisely the set of infinite cells: \begin{ccExampleCode} +{int i=0; typedef Triangulation::Full_cell_handle Full_cell_handle; typedef Triangulation::Facet Facet; typedef std::vector Full_cells; @@ -392,8 +422,10 @@ t.incident_full_cells(t.infinite_vertex(), out); for( Full_cells::iterator sit = infinite_full_cells.begin(); sit != infinite_full_cells.end(); ++sit ) { - Facet ft(*sit, 0); // |ft| is a facet of the convex hull + Facet ft(*sit, (*sit)->index(t.infinite_vertex()) ); + ++i// |ft| is a facet of the convex hull } +std::cout << "There are " << i << " facets on the convex hull."<< std::endl;} \end{ccExampleCode} \textbf{Remark}: the code example above is not self contained, it can be cut and paste at STEP 2 of {\tt triangulation.cpp} program above. @@ -416,6 +448,10 @@ of the triangulation. The \textbf{circumscribing ball} of a full cell \ccc{fc} is the ball having all vertices of the full cell on its boundary. +In case of degeneracies (co-spherical points) the triangulation is not +uniquely defined, +note however that the \cgal\ implementation computes a unique +triangulation even in these cases. %The \textbf{circumscribing sphere} of a face \ccc{s} is the smallest sphere %touching all vertices of the face. A triangulation of the convex %hull of a finite point set has the Delaunay (or empty-ball) property if all @@ -426,7 +462,7 @@ having all vertices of the full cell on its boundary. %interior of its circumscribing sphere. When a new point \ccc{p} is inserted into a Delaunay triangulation, the -finite cells whose circumscribing sphere contains \ccc{p} are said to +finite cells whose circumscribing sphere contain \ccc{p} are said to \textbf{be in conflict} with point \ccc{p}. The set of cells that are in conflict with \ccc{p} form the \textbf{conflict zone}. That conflict zone is augmented with the infinite cells whose finite facet does not lie @@ -434,7 +470,7 @@ anymore on the convex hull of the triangulation (with \ccc{p} added). The cells in the conflict zone are removed, leaving a hole that contains \ccc{p}. That hole is then re-triangulated in a ``star shape'' centered at \ccc{p}. -Delaunay triangulation also supports vertex removal. +Delaunay triangulations also support vertex removal. % - - - - - - - - - - - - - - - - - - - - - - - - - DELAUNAY IMPLEMENTATION @@ -442,9 +478,9 @@ Delaunay triangulation also supports vertex removal. The class \ccc{CGAL::Delaunay_triangulation} derives from \ccc{CGAL::Triangulation}. It thus stores a model \ccc{TDS} of -the concept \ccc{TriangulationDataStructure} which is instanciated with a vertex +the concept \ccc{TriangulationDataStructure} which is instantiated with a vertex type that stores a geometric point, and a full cell type that allows the -retrieval of the point of its vertices. +retrieval of the points of its vertices. The template parameter \ccc{DTTraits} must be a model of the concept \ccc{DelaunayTriangulationTraits} which provides the geometric \ccc{Point} type as @@ -467,7 +503,7 @@ created cells. The second part of code example below shows how one can have effi access to both the conflict zone and the created cells, while still retaining an efficient update of the Delaunay triangulation. -\ccIncludeExampleCode{Triangulation/triangulation.cpp} +\ccIncludeExampleCode{Triangulation/delaunay.cpp} \section{Complexity and Performances} diff --git a/Triangulation/examples/Triangulation/barycentric_subdivision.cpp b/Triangulation/examples/Triangulation/barycentric_subdivision.cpp index ce67b3ce72c..c82cbe7e7c1 100644 --- a/Triangulation/examples/Triangulation/barycentric_subdivision.cpp +++ b/Triangulation/examples/Triangulation/barycentric_subdivision.cpp @@ -25,7 +25,7 @@ void barycentric_subdivide(TDS & tds, typename TDS::Full_cell_handle fc) tds.insert_in_full_cell(fc); // From now on, we can't use the variable |fc|... - // Then, subdivide facets of |fc| in order of decreasing dimension + // Then, subdivide faces of |fc| in order of decreasing dimension for( int d = dim-1; d > 0; --d ) { face_vertices.resize(d+1); @@ -36,9 +36,9 @@ void barycentric_subdivide(TDS & tds, typename TDS::Full_cell_handle fc) { for( int i = 0; i <= d; ++i ) face_vertices[i] = vertices[combi[i]]; - // we need to build a face with face_vertices + // we need to find a face with face_vertices Face face(dim); - make_face_from_vertices(tds, face_vertices, face); + find_face_from_vertices(tds, face_vertices, face); tds.insert_in_face(face); ++combi; } @@ -47,7 +47,7 @@ void barycentric_subdivide(TDS & tds, typename TDS::Full_cell_handle fc) template< typename TDS > void -make_face_from_vertices( const TDS & tds, +find_face_from_vertices( const TDS & tds, const std::vector & face_vertices, typename TDS::Face & face) { /* The main goal of this function is to find a full cell that diff --git a/Triangulation/examples/Triangulation/delaunay.cpp b/Triangulation/examples/Triangulation/delaunay.cpp index c9926671c2c..4d3228ce1c0 100644 --- a/Triangulation/examples/Triangulation/delaunay.cpp +++ b/Triangulation/examples/Triangulation/delaunay.cpp @@ -58,6 +58,7 @@ int main(int argc, char **argv) Full_cells zone, new_full_cells; std::back_insert_iterator out(zone); c = t.locate(*++rand_it, lt, f, ft, v); + // previously inserted vertex v is a hint for point location (if defined) T::Facet ftc = t.compute_conflict_zone(*rand_it, c, out); std::cout< "< > - TDS; - typedef TDS::Face Face; - typedef TDS::Facet Facet; - typedef TDS::Vertex_handle Vertex_handle; - typedef TDS::Full_cell_handle Full_cell_handle; + typedef CGAL::Triangulation_data_structure > TDS; - TDS S(58); // the argument is not taken into account. dimension is 7. + TDS S(0); // the argument is not taken into account. dimension is 7. assert( 7 == S.ambient_dimension() ); assert( -2 == S.current_dimension() ); assert( S.is_valid() ); - std::vector V(10); + std::vector V(10); V[0] = S.insert_increase_dimension(); //insert first vertex assert( -1 == S.current_dimension() ); @@ -27,32 +22,33 @@ int main() assert( 6 == S.number_of_vertices() ); assert( 6 == S.number_of_full_cells() ); - Full_cell_handle c = V[5]->full_cell(); + TDS::Full_cell_handle c = V[5]->full_cell(); V[6] = S.insert_in_full_cell(c); // full cell c is split in 5 assert( 7 == S.number_of_vertices() ); assert( 10 == S.number_of_full_cells() ); c = V[3]->full_cell(); - Facet ft(c, 2); // the Facet opposite to vertex 2 in c + TDS::Facet ft(c, 2); // the Facet opposite to vertex 2 in c V[7] = S.insert_in_facet(ft); // facet ft is split in 4 and the two incident cells are split accordingly assert( 8 == S.number_of_vertices() ); assert( 16 == S.number_of_full_cells() ); c = V[3]->full_cell(); - Face face(c); // an edge joining vertices of full_cell c + TDS::Face face(c); + // meant to contain the edge joining vertices 2 and 4 of full_cell c face.set_index(0, 2); // namely vertex 2 face.set_index(1, 4); // and vertex 4 V[8] = S.insert_in_face(face); // face is split in 2, and all incident full cells also assert( S.is_valid() ); - Full_cell_handle hole[2]; + TDS::Full_cell_handle hole[2]; hole[0] = V[8]->full_cell(); hole[1] = hole[0]->neighbor(0); // the hole is made of two adjacent full cells - ft = Facet(hole[0], 1); // a face on the boundary of hole[0] + ft = TDS::Facet(hole[0], 1); // a face on the boundary of hole[0] V[9] = S.insert_in_hole(hole, hole+2, ft); // the hole is triangulated by linking a new vertex to its boundary assert( S.is_valid() ); diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 5a870953fed..f85eeaa4815 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -147,13 +147,13 @@ private: }; public: - - Triangulation_data_structure(const int dim) /* Concept */ - : dmax_(get_ambient_dimension::value(dim)), dcur_(-2), vertices_(), full_cells_() + Triangulation_data_structure( int dim) /* Concept */ + : dmax_(get_ambient_dimension::value(dim)), dcur_(-2), + vertices_(), full_cells_() { CGAL_assertion_msg(dmax_ > 0, "ambient dimension must be positive."); } - + ~Triangulation_data_structure() { clean_dynamic_memory();