mirror of https://github.com/CGAL/cgal
533 lines
13 KiB
C++
533 lines
13 KiB
C++
// ============================================================================
|
|
//
|
|
// 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 <Monique.Teillaud@sophia.inria.fr>
|
|
//
|
|
// coordinator : INRIA Sophia Antipolis (<Mariette.Yvinec@sophia.inria.fr>)
|
|
//
|
|
// ============================================================================
|
|
|
|
// 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 <CGAL/basic.h>
|
|
#include <CGAL/Triangulation_short_names_3.h>
|
|
#include <CGAL/Triangulation_utils_3.h>
|
|
|
|
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<Vb,Cb> Tds;
|
|
|
|
friend class Triangulation_data_structure_3<Vb,Cb>;
|
|
|
|
friend class Triangulation_ds_cell_iterator_3<Tds>;
|
|
friend class Triangulation_ds_facet_iterator_3<Tds>;
|
|
friend class Triangulation_ds_edge_iterator_3<Tds>;
|
|
friend class Triangulation_ds_vertex_iterator_3<Tds>;
|
|
|
|
typedef Triangulation_ds_vertex_3<Vb,Cb> Vertex;
|
|
typedef Triangulation_ds_cell_3<Vb,Cb> 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 <class Vb, class Cb >
|
|
bool
|
|
Triangulation_ds_cell_3<Vb,Cb>::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
|