// ============================================================================ // // Copyright (c) 1999 The CGAL Consortium // // This software and related documentation is part of an INTERNAL release // of the Computational Geometry Algorithms Library (CGAL). It is not // intended for general use. // // ---------------------------------------------------------------------------- // // release : // release_date : // // file : include/CGAL/Triangulation_ds_cell_3.h // revision : $Revision$ // author(s) : Monique Teillaud // // coordinator : INRIA Sophia Antipolis () // // ============================================================================ // cell of a combinatorial triangulation of any dimension <=3 // use to store vertices if dimension <=0, edges if dimension 1, // faces if dimension 2, plain cells if dimension 3 #ifndef CGAL_TRIANGULATION_DS_CELL_3_H #define CGAL_TRIANGULATION_DS_CELL_3_H #include #include #include CGAL_BEGIN_NAMESPACE template < class Vb, class Cb > class Triangulation_ds_vertex_3; template < class Vb, class Cb > class Triangulation_data_structure_3; template < class Tds> class Triangulation_ds_cell_iterator_3; template < class Tds> class Triangulation_ds_facet_iterator_3; template < class Tds> class Triangulation_ds_edge_iterator_3; template < class Tds> class Triangulation_ds_vertex_iterator_3; template < class Vb, class Cb > class Triangulation_ds_cell_3 : public Cb, public Triangulation_utils_3 { public: typedef Triangulation_data_structure_3 Tds; friend class Triangulation_data_structure_3; friend class Triangulation_ds_cell_iterator_3; friend class Triangulation_ds_facet_iterator_3; friend class Triangulation_ds_edge_iterator_3; friend class Triangulation_ds_vertex_iterator_3; typedef Triangulation_ds_vertex_3 Vertex; typedef Triangulation_ds_cell_3 Cell; Triangulation_ds_cell_3() : Cb(), in_conflict_flag(0) {} Triangulation_ds_cell_3(Cell* c) : Cb(*c), in_conflict_flag(0) {} Triangulation_ds_cell_3(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3) : Cb(v0,v1,v2,v3), in_conflict_flag(0) {} Triangulation_ds_cell_3(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, Cell* n0, Cell* n1, Cell* n2, Cell* n3) : Cb(v0,v1,v2,v3,n0,n1,n2,n3), in_conflict_flag(0) {} // not documented // only used by copy_tds in the TDS class Triangulation_ds_cell_3(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, const Cell& old_cell) : Cb(old_cell), in_conflict_flag(0) { set_vertices(v0,v1,v2,v3); } // SETTING void set_vertex(int i, Vertex* v) { Cb::set_vertex(i,v); } void set_neighbor(int i, Cell* n) { Cb::set_neighbor(i,n); } void set_vertices(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3) { Cb::set_vertices(v0,v1,v2,v3); } void set_neighbors(Cell* n0, Cell* n1, Cell* n2, Cell* n3) { Cb::set_neighbors(n0,n1,n2,n3); } // VERTEX ACCESS Vertex* vertex(int i) const { return (Vertex*) (Cb::vertex(i)); } bool has_vertex(const Vertex* v) const { return Cb::has_vertex(v); } bool has_vertex(const Vertex* v, int & i) const { return Cb::has_vertex(v,i); } int index(const Vertex* v) const { return Cb::vertex_index(v); } // NEIGHBOR ACCESS Cell* neighbor(int i) const { return (Cell*) Cb::neighbor(i); } bool has_neighbor(const Cell* n) const { return Cb::has_neighbor(n); } bool has_neighbor(const Cell* n, int & i) const { return Cb::has_neighbor(n,i); } int index(const Cell* n) const { return Cb::cell_index(n); } int mirror_index(int i) const { CGAL_triangulation_precondition ( (i>=0) && (i<4) ); CGAL_triangulation_precondition ( is_valid() && neighbor(i).is_valid() ); return neighbor(i)->index(this); } // CHECKING Vertex* mirror_vertex(int i) const { return neighbor(i)->vertex(mirror_index(i)); } bool is_valid(int dim = 3, bool verbose = false, int level = 0) const; private: // to maintain the list of cells Cell* _previous_cell; Cell* _next_cell; int in_conflict_flag; void set_in_conflict_flag(int f) { in_conflict_flag = f; } int get_in_conflict_flag() const { return in_conflict_flag; } void error_orient( Cell * , int i ) const { std::cerr << " pb orientation with neighbor " << i << std::endl; } void error_neighbor( Cell* , int , int ) const { std::cerr << "neighbor of c has not c as neighbor" << std::endl; } }; // __attribute__((__aligned__(16))); // Memory alignment. For GCC only template bool Triangulation_ds_cell_3::is_valid (int dim, bool verbose, int level) const { if ( ! Cb::is_valid(verbose,level) ) return false; switch (dim) { case -2: case -1: { if ( vertex(0) == NULL ) { if (verbose) std::cerr << "vertex 0 NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } vertex(0)->is_valid(verbose,level); if ( vertex(1) != NULL || vertex(2) != NULL || vertex(3) != NULL ) { if (verbose) std::cerr << "vertex 1,2 or 3 != NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( neighbor(0) != NULL || neighbor(1) != NULL || neighbor(2) != NULL || neighbor(3) != NULL ) { if (verbose) std::cerr << "one neighbor != NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } break; } case 0: { if ( vertex(0) == NULL ) { if (verbose) std::cerr << "vertex 0 NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } vertex(0)->is_valid(verbose,level); if ( neighbor (0) == NULL ) { if (verbose) std::cerr << "neighbor 0 NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( vertex(1) != NULL || vertex(2) != NULL || vertex(3) != NULL ) { if (verbose) std::cerr << "vertex 1, 2 or 3 != NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( neighbor(1) != NULL || neighbor(2) != NULL || neighbor(3) != NULL ) { if (verbose) std::cerr << "neighbor 1, 2 or 3 != NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( ! neighbor(0)->has_vertex(vertex(0)) ) { if (verbose) std::cerr << "neighbor 0 does not have vertex 0" << std::endl; CGAL_triangulation_assertion(false); return false; } break; } case 1: { Vertex* v0 = vertex(0); Vertex* v1 = vertex(1); Cell* n0 = neighbor(0); Cell* n1 = neighbor(1); if ( v0 == NULL || v1 == NULL ) { if (verbose) std::cerr << "vertex 0 or 1 NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } vertex(0)->is_valid(verbose,level); vertex(1)->is_valid(verbose,level); if ( n0 == NULL || n1 == NULL ) { if (verbose) std::cerr << "neighbor 0 or 1 NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( vertex(2) != NULL || vertex(3) != NULL ) { if (verbose) std::cerr << "vertex 2 or 3 != NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( neighbor(2) != NULL || neighbor(3) != NULL ) { if (verbose) std::cerr << "neighbor 2 or 3 != NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( v0 != n1->vertex(1) ) { if (verbose) std::cerr << "neighbor 1 does not have vertex 0 as vertex 1" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( v1 != n0->vertex(0) ) { if (verbose) std::cerr << "neighbor 0 does not have vertex 1 as vertex 0" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( this != n0->neighbor(1) ) { if (verbose) std::cerr << "neighbor 0 does not have this as neighbor 1" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( this != n1->neighbor(0) ) { if (verbose) std::cerr << "neighbor 1 does not have this as neighbor 0" << std::endl; CGAL_triangulation_assertion(false); return false; } break; } case 2: { if ( vertex(0) == NULL || vertex(1) == NULL || vertex(2) == NULL ) { if (verbose) std::cerr << "vertex 0, 1, or 2 NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } vertex(0)->is_valid(verbose,level); vertex(1)->is_valid(verbose,level); vertex(2)->is_valid(verbose,level); if ( vertex(3) != NULL ) { if (verbose) std::cerr << "vertex 3 != NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( neighbor(3) != NULL ) { if (verbose) std::cerr << "neighbor 3 != NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } int in; Cell* n; for(int i = 0; i < 3; i++) { n = neighbor(i); if ( n == NULL ) { if (verbose) std::cerr << "neighbor " << i << " NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } if ( ! n->has_vertex(vertex(cw(i)),in ) ) { if (verbose) std::cerr << "vertex " << cw(i) << " not vertex of neighbor " << i << std::endl; CGAL_triangulation_assertion(false); return false; } in = cw(in); if ( this != n->neighbor(in) ) { if (verbose) std::cerr << "neighbor " << i << " does not have this as neighbor " << in << std::endl; CGAL_triangulation_assertion(false); return false; } if ( vertex(ccw(i)) != n->vertex(cw(in)) ) { if (verbose) std::cerr << "vertex " << ccw(i) << " is not vertex " << cw(in) << " of neighbor " << i << std::endl; CGAL_triangulation_assertion(false); return false; } } break; } case 3: { int i; for(i = 0; i < 4; i++) { if ( vertex(i) == NULL ) { if (verbose) std::cerr << "vertex " << i << " NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } vertex(i)->is_valid(verbose,level); } for(i = 0; i < 4; i++) { Cell* n = neighbor(i); if ( n == NULL ) { if (verbose) std::cerr << "neighbor " << i << " NULL" << std::endl; CGAL_triangulation_assertion(false); return false; } int in; if ( ! n->has_neighbor(this,in) ) { if (verbose) error_neighbor(n,i,in); CGAL_triangulation_assertion(false); return false; } int j1n,j2n,j3n; if ( ! n->has_vertex(vertex((i+1)&3),j1n) ) { if (verbose) { std::cerr << "vertex " << ((i+1)&3) << " not vertex of neighbor " << i << std::endl; } CGAL_triangulation_assertion(false); return false; } if ( ! n->has_vertex(vertex((i+2)&3),j2n) ) { if (verbose) { std::cerr << "vertex " << ((i+2)&3) << " not vertex of neighbor " << i << std::endl; } CGAL_triangulation_assertion(false); return false; } if ( ! n->has_vertex(vertex((i+3)&3),j3n) ) { if (verbose) { std::cerr << "vertex " << ((i+3)&3) << " not vertex of neighbor " << i << std::endl; } CGAL_triangulation_assertion(false); return false; } if ( in+j1n+j2n+j3n != 6) { if (verbose) { std::cerr << "sum of the indices != 6 " << std::endl; } CGAL_triangulation_assertion(false); return false; } // tests whether the orientations of this and n are consistent if ( ((i+in)&1) == 0 ) { // i and in have the same parity if ( j1n == ((in+1)&3) ) { if ( ( j2n != ((in+3)&3) ) || ( j3n != ((in+2)&3) ) ) { if (verbose) { error_orient(n,i); } CGAL_triangulation_assertion(false); return false; } } if ( j1n == ((in+2)&3) ) { if ( ( j2n != ((in+1)&3) ) || ( j3n != ((in+3)&3) ) ) { if (verbose) { error_orient(n,i); } CGAL_triangulation_assertion(false); return false; } } if ( j1n == ((in+3)&3) ) { if ( ( j2n != ((in+2)&3) ) || ( j3n != ((in+1)&3) ) ) { if (verbose) { error_orient(n,i); } CGAL_triangulation_assertion(false); return false; } } } else { // i and in do not have the same parity if ( j1n == ((in+1)&3) ) { if ( ( j2n != ((in+2)&3) ) || ( j3n != ((in+3)&3) ) ) { if (verbose) { error_orient(n,i); } CGAL_triangulation_assertion(false); return false; } } if ( j1n == ((in+2)&3) ) { if ( ( j2n != ((in+3)&3) ) || ( j3n != ((in+1)&3) ) ) { if (verbose) { error_orient(n,i); } CGAL_triangulation_assertion(false); return false; } } if ( j1n == ((in+3)&3) ) { if ( ( j2n != ((in+1)&3) ) || ( j3n != ((in+2)&3) ) ) { if (verbose) { error_orient(n,i); } CGAL_triangulation_assertion(false); return false; } } } } // end looking at neighbors }// end case dim 3 } // end switch return true; } // end is_valid CGAL_END_NAMESPACE #endif // CGAL_TRIANGULATION_DS_CELL_3_H