cgal/Mesh_3/test/Mesh_3/test_c3t3_io.cpp

399 lines
13 KiB
C++

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Mesh_3/io_signature.h>
#include <CGAL/Mesh_triangulation_3.h>
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
#include <boost/variant.hpp>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
//
// Define two fake Mesh_domain, with index types
//
// One with all types equal to int.
struct MD_homogeneous_types {
typedef CGAL::Tag_false Has_features;
typedef int Subdomain_index;
typedef int Surface_patch_index;
typedef int Curve_segment_index;
typedef int Corner_index;
typedef int Index;
static Subdomain_index get_sub_domain_index_1() { return 1; }
static Subdomain_index get_sub_domain_index_2() { return 2; }
static Surface_patch_index get_surface_patch_index_1() { return 3; }
static Surface_patch_index get_surface_patch_index_2() { return 4; }
static Curve_segment_index get_curve_segment_index_1() { return 5; }
static Curve_segment_index get_curve_segment_index_2() { return 6; }
static Corner_index get_corner_index_1() { return 7; }
static Corner_index get_corner_index_2() { return 8; }
};
// One with heterogeneous index types
struct MD_heterogeneous_types {
typedef CGAL::Tag_true Has_features;
enum Subdomain_index_enum { Z = 0, A, B, C, D};
typedef Subdomain_index_enum Subdomain_index;
typedef std::pair<int, int> Surface_patch_index;
typedef int Curve_segment_index;
typedef double Corner_index;
typedef boost::variant<Subdomain_index,
Surface_patch_index,
Curve_segment_index,
Corner_index> Index;
static Subdomain_index get_sub_domain_index_1() { return A; }
static Subdomain_index get_sub_domain_index_2() { return B; }
static Surface_patch_index get_surface_patch_index_1() { return std::make_pair(1, 2); }
static Surface_patch_index get_surface_patch_index_2() { return std::make_pair(3, 4); }
static Curve_segment_index get_curve_segment_index_1() { return 5; }
static Curve_segment_index get_curve_segment_index_2() { return 6; }
static Corner_index get_corner_index_1() { return 7.; }
static Corner_index get_corner_index_2() { return 8.; }
};
//
// Define I/O for MD_heterogeneous_types::Subdomain_index (then enum)
//
// First, new technique: specialization of Output_rep and Input_rep (from
// CGAL/IO/io.h). That works for CGAL::read and CGAL::write, and ease the
// overload of << and >>
namespace CGAL {
template <>
class Output_rep<MD_heterogeneous_types::Subdomain_index> {
typedef MD_heterogeneous_types::Subdomain_index T;
const T& t;
public:
//! initialize with a const reference to \a t.
Output_rep( const T& tt) : t(tt) {}
//! perform the output, calls \c operator\<\< by default.
std::ostream& operator()( std::ostream& out) const {
if(is_ascii(out)) {
out << (int)t;
} else {
CGAL::write(out, (int)t);
}
return out;
}
};
template <>
class Input_rep<MD_heterogeneous_types::Subdomain_index> {
typedef MD_heterogeneous_types::Subdomain_index T;
T& t;
public:
//! initialize with a const reference to \a t.
Input_rep( T& tt) : t(tt) {}
//! perform the output, calls \c operator\<\< by default.
std::istream& operator()( std::istream& in) const {
int i;
if(is_ascii(in)) {
in >> i;
} else {
CGAL::read(in, i);
}
t = (T)i;
return in;
}
};
} // end namespace CGAL
// Second: operator<< and >>
namespace std {
std::ostream& operator<<(std::ostream& out,
MD_heterogeneous_types::Subdomain_index index) {
return out << CGAL::oformat(index);
}
std::istream& operator>>(std::istream& in,
MD_heterogeneous_types::Subdomain_index& index) {
return in >> CGAL::iformat(index);
}
} // end namespace std
// Second: the specialization of CGAL::Get_io_signature (in
// <CGAL/Mesh_3/io_signature.h>).
namespace CGAL {
template <>
struct Get_io_signature<MD_heterogeneous_types::Subdomain_index> {
std::string operator()() const {
return "enum";
}
};
//
// Define I/O for MD_heterogeneous_types::Surface_patch_index (pair of int)
//
// First, new technique: specialization of Output_rep and Input_rep (from
// CGAL/IO/io.h). That works for CGAL::read and CGAL::write, and ease the
// overload of << and >>
template <>
class Output_rep<MD_heterogeneous_types::Surface_patch_index> {
typedef MD_heterogeneous_types::Surface_patch_index T;
const T& t;
public:
//! initialize with a const reference to \a t.
Output_rep( const T& tt) : t(tt) {}
//! perform the output, calls \c operator\<\< by default.
std::ostream& operator()( std::ostream& out) const {
if(is_ascii(out)) {
out << t.first << " " << t.second;
} else {
CGAL::write(out, t.first);
CGAL::write(out, t.second);
}
return out;
}
};
template <>
class Input_rep<MD_heterogeneous_types::Surface_patch_index> {
typedef MD_heterogeneous_types::Surface_patch_index T;
T& t;
public:
//! initialize with a const reference to \a t.
Input_rep( T& tt) : t(tt) {}
//! perform the output, calls \c operator\<\< by default.
std::istream& operator()( std::istream& in) const {
if(is_ascii(in)) {
in >> t.first >> t.second;
} else {
CGAL::read(in, t.first);
CGAL::read(in, t.second);
}
return in;
}
};
} // end namespace CGAL
// Second: operator<< and >>
namespace std {
std::ostream& operator<<(std::ostream& out,
MD_heterogeneous_types::Surface_patch_index index) {
return out << CGAL::oformat(index);
}
std::istream& operator>>(std::istream& in,
MD_heterogeneous_types::Surface_patch_index& index) {
return in >> CGAL::iformat(index);
}
} // end namespace std
//
// Class to test I/O of Mesh_complex_3_in_triangulation_3<Mesh_domain,K>
//
template <typename Mesh_domain>
struct Test_c3t3_io {
typedef typename Mesh_domain::Subdomain_index Subdomain_index;
typedef typename Mesh_domain::Surface_patch_index Surface_patch_index;
typedef typename Mesh_domain::Curve_segment_index Curve_segment_index;
typedef typename Mesh_domain::Corner_index Corner_index;
typedef typename Mesh_domain::Index Index;
typedef typename CGAL::Mesh_triangulation_3<Mesh_domain, K>::Type Tr;
typedef CGAL::Mesh_complex_3_in_triangulation_3<
Tr,
Corner_index,
Curve_segment_index
> C3t3;
typedef typename Tr::Point Point;
typedef typename Tr::Vertex_handle Vertex_handle;
typedef typename Tr::Edge Edge;
typedef typename Tr::Facet Facet;
typedef typename Tr::Cell_handle Cell_handle;
static bool check_equality(const C3t3& c1, const C3t3& c2) {
const Tr& t1 = c1.triangulation();
const Tr& t2 = c2.triangulation();
if(t1.number_of_vertices() != t2.number_of_vertices()) {
assert(false);
return false;
}
if(t1.number_of_vertices() != t2.number_of_vertices()) {
assert(false);
return false;
}
if(c1.number_of_cells_in_complex() != c2.number_of_cells_in_complex()) {
assert(false);
return false;
}
if(c1.number_of_facets_in_complex() != c2.number_of_facets_in_complex()) {
assert(false);
return false;
}
for(typename Tr::Finite_vertices_iterator
vit1 = t1.finite_vertices_begin(),
vit2 = t2.finite_vertices_begin(),
end1 = t1.finite_vertices_end();
vit1 != end1; ++vit1, ++vit2)
{
if(!( vit1->in_dimension() == vit2->in_dimension() &&
vit1->index() == vit2->index()) )
{
std::cerr << "Error: vertices are different:\n";
std::cerr << *vit1 << "\n"
<< *vit2 << std::endl;
assert(false);
return false;
}
}
#if 0
// Note: The Triangulation_3 facets iterator order changes after a reload
for(typename Tr::Finite_facets_iterator
fit1 = t1.finite_facets_begin(),
fit2 = t2.finite_facets_begin(),
end1 = t1.finite_facets_end();
fit1 != end1; ++fit1, ++fit2)
{
typename Tr::Cell_handle c1 = fit1->first;
typename Tr::Cell_handle c2 = fit2->first;
int i1 = fit1->second;
int i2 = fit2->second;
assert(i1 == i2);
if( c1->surface_patch_index(i1) !=
c2->surface_patch_index(i2) )
{
std::cerr << "Error: facets #" << i1
<< "of the following cells are different:\n";
std::cerr << *c1 << "\n"
<< *c2 << std::endl;
assert(false);
return false;
}
}
#endif // not WIN32
for(typename Tr::Finite_cells_iterator
cit1 = t1.finite_cells_begin(),
cit2 = t2.finite_cells_begin(),
end1 = t1.finite_cells_end();
cit1 != end1; ++cit1, ++cit2)
{
if(cit1->subdomain_index() != cit2->subdomain_index() )
{
std::cerr << "Error: cells are different:\n";
std::cerr << *cit1 << "\n"
<< *cit2 << std::endl;
assert(false);
return false;
}
for(int i = 0; i < 4; ++i) {
if( cit1->surface_patch_index(i) !=
cit2->surface_patch_index(i) )
{
std::cerr << "Error: cells are different:\n";
std::cerr << *cit1 << "\n"
<< *cit2 << "\n"
<< "surface_patch_index(" << i << "):\n"
<< cit1->surface_patch_index(i) << "\n"
<< cit2->surface_patch_index(i) << "\n";
assert(false);
return false;
}
}
}
return true;
}
static bool test_io(const C3t3& c3t3, bool binary) {
std::cout << "test_io";
std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out;
if(binary) {
std::cout << " in binary mode";
mode |= std::ios_base::binary;
}
std::cout << std::endl;
std::cout << "IO format: " << CGAL::Get_io_signature<C3t3>()() << std::endl;
std::stringstream stream(mode);
if(binary) {
CGAL::set_binary_mode(stream);
}
stream << c3t3;
if(!binary) {
std::cout << "Content of the stream:\n"
<< "*****begin*****\n"
<< stream.str()
<< "\n******end******" << std::endl;
}
stream.seekg(0);
assert(stream);
C3t3 c3t3_bis;
stream >> c3t3_bis;
std::cout << "Content of c3t3_bis:\n"
<< "*****begin*****\n"
<< c3t3_bis
<< "\n******end******" << std::endl;
assert(stream);
std::ostringstream ss_c3t3, ss_c3t3_bis;
ss_c3t3 << c3t3;
ss_c3t3_bis << c3t3_bis;
assert(ss_c3t3.str() == ss_c3t3_bis.str());
return check_equality(c3t3, c3t3_bis);
}
bool operator()() const {
// Create a C3t3
C3t3 c3t3;
Tr& tr = c3t3.triangulation();
Vertex_handle v1 = tr.insert(Point(10,11,12));
Vertex_handle v2 = tr.insert(Point(11,13,10));
Vertex_handle v3 = tr.insert(Point(7,4,6));
Vertex_handle v4 = tr.insert(Point(5,2,14));
Vertex_handle v5 = tr.insert(Point(1,2,3));
Vertex_handle v6 = tr.insert(Point(3,9,13));
Edge e1 = *(c3t3.triangulation().finite_edges_begin());
Edge e2 = *(++c3t3.triangulation().finite_edges_begin());
Facet f1 = *(c3t3.triangulation().finite_facets_begin());
Facet f2 = *(++c3t3.triangulation().finite_facets_begin());
Cell_handle c1 = c3t3.triangulation().finite_cells_begin();
Cell_handle c2 = ++c3t3.triangulation().finite_cells_begin();
c3t3.add_to_complex(c1, Mesh_domain::get_sub_domain_index_1());
c3t3.add_to_complex(c2, Mesh_domain::get_sub_domain_index_2());
c3t3.add_to_complex(f1, Mesh_domain::get_surface_patch_index_1());
c3t3.add_to_complex(f2, Mesh_domain::get_surface_patch_index_2());
c3t3.add_to_complex(e1, Mesh_domain::get_curve_segment_index_1());
c3t3.add_to_complex(e2, Mesh_domain::get_curve_segment_index_2());
c3t3.add_to_complex(v1, Mesh_domain::get_corner_index_1());
c3t3.add_to_complex(v2, Mesh_domain::get_corner_index_2());
// Fill indices in various faces (with different dimensions)
v1->set_dimension(0);
v1->set_index(Mesh_domain::get_corner_index_1());
v2->set_dimension(0);
v2->set_index(Mesh_domain::get_corner_index_2());
v3->set_dimension(1);
v3->set_index(Mesh_domain::get_curve_segment_index_1());
v4->set_dimension(1);
v4->set_index(Mesh_domain::get_curve_segment_index_2());
v5->set_dimension(2);
v5->set_index(Mesh_domain::get_surface_patch_index_1());
v6->set_dimension(3);
v6->set_index(Mesh_domain::get_sub_domain_index_1());
// then test I/O
return test_io(c3t3, false) && test_io(c3t3, true);
}
};
int main()
{
std::cout << "First test I/O when all indices are integers" << std::endl;
bool ok = Test_c3t3_io<MD_homogeneous_types>()();
if(!ok) {
std::cerr << "Error\n";
return -1;
}
std::cout << "Then test I/O when all indices are different types" << std::endl;
ok = Test_c3t3_io<MD_heterogeneous_types>()();
if(!ok) {
std::cerr << "Error\n";
return -1;
}
}