diff --git a/Triangulation/doc_tex/Triangulation_ref/TriangulationDSFullCell.tex b/Triangulation/doc_tex/Triangulation_ref/TriangulationDSFullCell.tex index c5bf10b6700..436203aaa1c 100644 --- a/Triangulation/doc_tex/Triangulation_ref/TriangulationDSFullCell.tex +++ b/Triangulation/doc_tex/Triangulation_ref/TriangulationDSFullCell.tex @@ -175,10 +175,15 @@ a neighbor of \ccVar\ if the full cell \ccc{n} is a neighbor of the full cell \begin{ccDebug} \ccHeading{Validity check} -\ccMethod{bool is_valid(bool verbose=false) const;}{Performs any -desired test on a full cell. \emph{E.g.}, checks that for each -existing neighbor \ccc{n}, \ccVar\ and \ccc{n} share relevant vertices -and \ccVar\ is the relevant neighbor of \ccc{n}. +\ccMethod{bool is_valid(bool verbose=false) const;}{ +Performs some validity checks on the full cell \ccVar. + +It must \emph{at least} check that for each \emph{existing} neighbor \ccc{n}, +\ccVar\ is also a neighbor of \ccc{n}. + +Returns \ccc{true} if all the tests pass, \ccc{false} if any test fails. See +the documentation for the models of this concept to see the additionnal (if +any) validity checks that they implement.% } \end{ccDebug} diff --git a/Triangulation/doc_tex/Triangulation_ref/TriangulationDSVertex.tex b/Triangulation/doc_tex/Triangulation_ref/TriangulationDSVertex.tex index 7fca5c047f9..fe7f6ba23eb 100644 --- a/Triangulation/doc_tex/Triangulation_ref/TriangulationDSVertex.tex +++ b/Triangulation/doc_tex/Triangulation_ref/TriangulationDSVertex.tex @@ -54,10 +54,15 @@ incident full cell. \ccPrecond \ccc{c} must not be the default-constructed \begin{ccDebug} \ccHeading{Validity check} -\ccMethod{bool is_valid(bool verbose=false) const;}{Performs any -desired test on a vertex. For example, it could check that the incident full -cell exists and contains \ccVar. See the documentation for the models -of this concept to see the validity checks that they implement.% +\ccMethod{bool is_valid(bool verbose=false) const;}{% +Performs some validity checks on the vertex \ccVar. + +It must \emph{at least} check that \ccVar\ has an incident full cell, which in +turn must contain \ccVar\ as one of its vertices. + +Returns \ccc{true} if all the tests pass, \ccc{false} if any test fails. See +the documentation for the models of this concept to see the additionnal (if +any) validity checks that they implement.% } \end{ccDebug} diff --git a/Triangulation/doc_tex/Triangulation_ref/TriangulationDataStructure.tex b/Triangulation/doc_tex/Triangulation_ref/TriangulationDataStructure.tex index 3b5f986cdfc..5dbdaec15e6 100644 --- a/Triangulation/doc_tex/Triangulation_ref/TriangulationDataStructure.tex +++ b/Triangulation/doc_tex/Triangulation_ref/TriangulationDataStructure.tex @@ -559,20 +559,22 @@ and \ccc{current_dimension()!=2}. \begin{ccDebug} \ccHeading{Validity check} % - - - - - - - - - - - - - - - - - - - - VALIDITY -\ccMethod{bool is_valid(bool verbose = true) const;} -{Partially checks whether \ccVar\ is a triangulation. This function -returns \ccc{true} if each vertex is a vertex of the full cell of which it -claims to be a vertex, if the vertices of every full cell are pairwise distinct, -if the adjacency (neighbor) relationship is symmetric, and if adjacent full cells share -exactly \ccVar.\ccc{current_dimension()} vertices and the induced -orientation of these two full cells are compatible. - It prints an error message -if one of these conditions is violated and the \ccc{verbose} parameter is -\ccc{true}. Passing these tests does not guaranty that we have a -triangulation (abstract pure -complex). In particular, for example, it is not -checked whether full cells that share \ccVar.\ccc{current_dimension()} vertices -are neighbors in the data structure.} +\ccMethod{bool is_valid(bool verbose=false) const;}{% +Partially checks whether \ccVar\ is indeed a triangulation. + +It must \emph{at least}\begin{itemize} +\item check the validity of the vertices and full cells of \ccVar\ by calling +their respective \ccc{is_valid} method. +\item check that each full cell has no duplicate vertices and has as many +neighbors as its number of facets (\ccc{current_dimension()+1}). +\item check that each full cell share exactly \ccVar.\ccc{current_dimension()} +vertices with each of its neighbor. +\end{itemize} + +Returns \ccc{true} if all the tests pass, \ccc{false} if any test fails. See +the documentation for the models of this concept to see the additionnal (if +any) validity checks that they implement.% +} \end{ccDebug} diff --git a/Triangulation/doc_tex/Triangulation_ref/Triangulation_data_structure.tex b/Triangulation/doc_tex/Triangulation_ref/Triangulation_data_structure.tex index 49ef6743ce8..a8a2bcebec1 100644 --- a/Triangulation/doc_tex/Triangulation_ref/Triangulation_data_structure.tex +++ b/Triangulation/doc_tex/Triangulation_ref/Triangulation_data_structure.tex @@ -48,6 +48,23 @@ In addition, the class \ccRefName\ provides the following types and methods: {The copy constructor. Creates a copy of the \ccRefName\ \ccc{t2} passed as argument. All vertices and full cells are duplicated.} +\begin{ccDebug} +\ccHeading{Validity check} % - - - - - - - - - - - - - - - - - - - - VALIDITY + +The \ccc{is_valid} method is only minimally defined in the +\ccc{TriangulationDataStructure} concept, so that we document it more precisely +here, for the model \ccRefName: + +\ccMethod{bool is_valid(bool verbose = true) const;}{% +Implements the validity checks required by the concept +\ccc{TriangulationDataStructure}.% + +Note that passing all these tests does not guaranty that we have a +triangulation (abstract pure simplicial complex).% +} + +\end{ccDebug} + \begin{ccAdvanced} \ccTypes diff --git a/Triangulation/doc_tex/Triangulation_ref/Triangulation_ds_full_cell.tex b/Triangulation/doc_tex/Triangulation_ref/Triangulation_ds_full_cell.tex index c6dbbdaf89e..b600bbd30ac 100644 --- a/Triangulation/doc_tex/Triangulation_ref/Triangulation_ds_full_cell.tex +++ b/Triangulation/doc_tex/Triangulation_ref/Triangulation_ds_full_cell.tex @@ -51,9 +51,26 @@ See the user manual for how to choose the second option. \ccc{TriangulationDSFullCell} +\ccCreationVariable{c} + +\begin{ccDebug} +\ccHeading{Validity check} + +The \ccc{is_valid} method is only minimally defined in the +\ccc{TriangulationDSFullCell} concept, so that we document it more precisely +here, for the model \ccRefName: + +\ccMethod{bool is_valid(bool verbose=false) const;}{ +Implements the validity checks required by the concept +\ccc{TriangulationDSFullCell}. In addition, it is checked that there is no +\ccc{NULL} handle to vertices in the middle of non-\ccc{NULL} ones, that is, +that the internal memory layout is not corrupted.% +} +\end{ccDebug} + \begin{ccAdvanced} \ccHeading{Rebind mechanism} -In case oif derivation from that class, the nested class +In case of derivation from that class, the nested class \ccc{Rebind_TDS} need to be provided in the derived class. \end{ccAdvanced} diff --git a/Triangulation/doc_tex/Triangulation_ref/Triangulation_ds_vertex.tex b/Triangulation/doc_tex/Triangulation_ref/Triangulation_ds_vertex.tex index 784d4cdefd2..be94f9fe14b 100644 --- a/Triangulation/doc_tex/Triangulation_ref/Triangulation_ds_vertex.tex +++ b/Triangulation/doc_tex/Triangulation_ref/Triangulation_ds_vertex.tex @@ -33,13 +33,14 @@ The template parameter \ccc{TriangulationDataStructure} must be a model of the \begin{ccDebug} \ccHeading{Validity check} -The \ccc{is_valid} method is only loosely defined in the +The \ccc{is_valid} method is only minimally defined in the \ccc{TriangulationDSVertex} concept, so that we document it more precisely here, for the model \ccRefName: -\ccMethod{bool is_valid(bool verbose=false) const;}{Returns \ccc{true} -if the full cell incident to \ccVar\ actually exists and contains -\ccVar\ as one of its vertices. Returns \ccc{false} otherwise.} +\ccMethod{bool is_valid(bool verbose=false) const;}{% +Implements the validity checks required by the concept +\ccc{TriangulationDSVertex}. Does not implement additional checks.% +} \end{ccDebug} \begin{ccAdvanced} diff --git a/Triangulation/include/CGAL/Triangulation_data_structure.h b/Triangulation/include/CGAL/Triangulation_data_structure.h index 6e46b9b62a7..3a048919f5a 100644 --- a/Triangulation/include/CGAL/Triangulation_data_structure.h +++ b/Triangulation/include/CGAL/Triangulation_data_structure.h @@ -476,15 +476,6 @@ public: // SANITY CHECKS bool is_valid(bool = true, int = 0) const; /* Concept */ - /* op Partially checks whether |\Mvar| is an abstract simplicial - complex. This function terminates without error if each vertex is a - vertex of the full_cell of which it claims to be a vertex, if the - vertices of all full_cells are pairwise distinct, if the neighbor - relationship is symmetric, and if neighboring full_cells share exactly - |dcur_| vertices. It returns an error message if one of these - conditions is violated. Note that it is not checked whether full_cells - that share |dcur_| vertices are neighbors in the data structure. - */ // NOT DOCUMENTED template< class OutStream> void write_graph(OutStream &); @@ -1179,7 +1170,7 @@ bool Triangulation_data_structure Vertex_const_handle v; int i, j, k; - if( dcur_ == -2 ) + if( current_dimension() == -2 ) { if( ! vertices_.empty() || ! full_cells_.empty() ) { @@ -1188,7 +1179,7 @@ bool Triangulation_data_structure } } - if( dcur_ == -1 ) + if( current_dimension() == -1 ) { if ( (number_of_vertices() != 1) || (number_of_full_cells() != 1) ) { @@ -1197,39 +1188,25 @@ bool Triangulation_data_structure } } - int fake_dcur = (dcur_ > 0) ? dcur_ : 0; for( v = vertices_begin(); v != vertices_end(); ++v ) { if( ! v->is_valid(verbose) ) return false; - bool ok(false); - // check that |v|'s full_cell actually contains |v| - for( i = 0; i <= fake_dcur; ++i ) - { - if( v->full_cell()->vertex(i) == v ) - { - ok = true; - break; - } - } - if( ! ok ) - { - if( verbose ) CGAL_warning_msg(false, "the full_cell incident to some vertex does not contain that vertex."); - return false; - } } + // FUTURE: for each vertex v, gather incident full_cells. then, check that // any full_cell containing v is among those gathered full_cells... - if( dcur_ < 0 ) + if( current_dimension() < 0 ) return true; for( s = full_cells_begin(); s != full_cells_end(); ++s ) { if( ! s->is_valid(verbose) ) return false; - for( i = 0; i <= dcur_; ++i ) - for( j = i + 1; j <= dcur_; ++j ) + // check that the full cell has no duplicate vertices + for( i = 0; i <= current_dimension(); ++i ) + for( j = i + 1; j <= current_dimension(); ++j ) if( vertex(s,i) == vertex(s,j) ) { CGAL_warning_msg(false, "a full_cell has two equal vertices"); @@ -1239,7 +1216,7 @@ bool Triangulation_data_structure for( s = full_cells_begin(); s != full_cells_end(); ++s ) { - for( i = 0; i <= dcur_; ++i ) + for( i = 0; i <= current_dimension(); ++i ) if( (t = neighbor(s,i)) != Full_cell_const_handle() ) { int l = mirror_index(s,i); @@ -1248,13 +1225,13 @@ bool Triangulation_data_structure if( verbose ) CGAL_warning_msg(false, "neighbor relation is not symmetric"); return false; } - for( j = 0; j <= dcur_; ++j ) + for( j = 0; j <= current_dimension(); ++j ) if( j != i ) { // j must also occur as a vertex of t - for( k = 0; k <= dcur_ && ( vertex(s,j) != vertex(t,k) || k == l); ++k ) + for( k = 0; k <= current_dimension() && ( vertex(s,j) != vertex(t,k) || k == l); ++k ) ; - if( k > dcur_ ) + if( k > current_dimension() ) { if( verbose ) CGAL_warning_msg(false, "too few shared vertices between neighbors full_cells."); return false; diff --git a/Triangulation/include/CGAL/Triangulation_ds_full_cell.h b/Triangulation/include/CGAL/Triangulation_ds_full_cell.h index 4893eda0485..5f424da8e70 100644 --- a/Triangulation/include/CGAL/Triangulation_ds_full_cell.h +++ b/Triangulation/include/CGAL/Triangulation_ds_full_cell.h @@ -208,21 +208,36 @@ public: void* for_compact_container() const { return combinatorics_.for_compact_container(); } void* & for_compact_container() { return combinatorics_.for_compact_container(); } - bool is_valid(bool verbose = true, int /* level */ = 0) const /* Concept */ + bool is_valid(bool verbose = false, int level = 0) const /* Concept */ { const int d = maximal_dimension(); - for( int i = 0; i <= d; ++i ) + int i(0); + // test that the non-null Vertex_handles come first, before all null ones + while( i <= d && vertex(i) != Vertex_handle() ) ++i; + while( i <= d && vertex(i) == Vertex_handle() ) ++i; + if( i <= d ) { - if( Vertex_handle() != vertex(i) ) + if( verbose ) CGAL_warning_msg(false, "full cell has garbage handles to vertices."); + return false; + } + for( i = 0; i <= d; ++i ) + { + if( Vertex_handle() == vertex(i) ) + break; // there are no more vertices + Full_cell_handle n(neighbor(i)); + if( Full_cell_handle() != n ) { - if( Full_cell_handle() == neighbor(i) ) + int mirror_idx(mirror_index(i)); + if( n->neighbor(mirror_idx) == Full_cell_handle() ) { - if( verbose ) CGAL_warning_msg(false, "vertex has no opposite full cell."); + if( verbose ) CGAL_warning_msg(false, "neighbor has no back-neighbor."); + return false; + } + if( &(*(n->neighbor(mirror_idx))) != this ) + { + if( verbose ) CGAL_warning_msg(false, "neighbor does not point back to correct full cell."); return false; } - // Here, we can't check if neighbor(i) counts *this as a neighbor - // because we can't construct a Full_cell_handle to *this... - // So we have to do this check in the `parent' class (TDS) } } return true;