diff --git a/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h b/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h index a2a87ee45ca1..2860f3dc877c 100644 --- a/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h +++ b/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h @@ -33,7 +33,7 @@ save_binary_file(std::ostream& os, { typedef typename C3T3::Triangulation::Geom_traits::FT FT; if(binary) os << "binary "; - os << "CGAL c3t3 " << CGAL::Get_io_signature()() << "\n"; + os << "CGAL c3t3 " << CGAL::Get_io_signature()() <<"+C3t3_data<"<()()<<">\n"; if(binary) { CGAL::IO::set_binary_mode(os); } else { @@ -59,20 +59,50 @@ bool load_binary_file(std::istream& is, C3T3& c3t3) { return false; } + bool has_curve_index_type = false; std::getline(is, s); if(!s.empty()) { if(s[s.size()-1] == '\r') { // deal with Windows EOL s.resize(s.size() - 1); } - if(s != std::string(" ") + CGAL::Get_io_signature()()) { - std::cerr << "load_binary_file:" - << "\n expected format: " << CGAL::Get_io_signature()() - << "\n got format:" << s << std::endl; - return false; + if(s.find("+C3t3_data") !=std::string::npos) + { + std::size_t splitter = s.find("+C3t3_data"); + std::string first_part = s.substr(0, splitter); + std::string second_part = s.substr(splitter); + + if(first_part != std::string(" ") + CGAL::Get_io_signature()()) { + std::cerr << "load_binary_file:" + << "\n expected format: " << CGAL::Get_io_signature()() + << "\n got format:" << s << std::endl; + return false; + } + if(second_part != std::string("+C3t3_data<")+Get_io_signature()()+">"){ + std::cout<< "load_binary_file warning:" + << "\n expected format: " << CGAL::Get_io_signature()()<<"+C3t3_data<"<()()<<">" + << "\n got format:" << s << std::endl + << "\n not loading edges in complex."<()()) { + std::cerr << "load_binary_file:" + << "\n expected format: " << CGAL::Get_io_signature()() + << "\n got format:" << s << std::endl; + return false; + } + has_curve_index_type = false; } } if(binary) CGAL::IO::set_binary_mode(is); - is >> c3t3; + if(has_curve_index_type) + is >> c3t3; + else + c3t3.load_without_edges(is); return !!is; // call operator!() twice, because operator bool() is C++11 } diff --git a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h b/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h index 4ccf832bff76..f61c41992c6f 100644 --- a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h +++ b/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h @@ -547,7 +547,87 @@ class Mesh_complex_3_in_triangulation_3 : Vertex_iterator_not_in_complex(*this)); } + std::ostream& write_edges_in_complex(std::ostream& os, + const Unique_hash_map& vertex_index_map) const + { + if(is_ascii(os)) + { + os << number_of_edges_in_complex()<left]<<" "<right]<< " "<< CGAL::oformat(it->info)<left]); + write(os, vertex_index_map[it->right]); + write(os, it->info); + } + } + return os; + } + + std::istream& read_edges_in_complex(std::istream& is, + const std::vector& index_vertex_map) + { + std::size_t n; + if(is_ascii(is)) + { + is >> n; + } + else + { + CGAL::read(is, n); + } + if(!is) + return is; + + if(is_ascii(is)) + { + for(std::size_t i=0; i < n; ++i) + { + //read edge and curve index + std::size_t l,r; + Curve_index c; + is >> CGAL::iformat(l); + is >> CGAL::iformat(r); + is >> CGAL::iformat(c); + if(!is) + return is; + add_to_complex(index_vertex_map[l],index_vertex_map[r], c); + } + } + else + { + for(std::size_t i=0; i < n; ++i) + { + //read edge and curve index + std::size_t l,r; + Curve_index c; + CGAL::read(is,l); + CGAL::read(is,r); + CGAL::read(is,c); + if(!is) + return is; + add_to_complex(index_vertex_map[l],index_vertex_map[r], c); + } + } + return is; + } + + std::istream& load_without_edges(std::istream& is) + { + is >> static_cast< + Mesh_3::Mesh_complex_3_in_triangulation_3_base&>(*this); + rescan_after_load_of_triangulation(); + return is; + + } private: /** * Creates an Internal_edge object (i.e a pair of ordered Vertex_handle) @@ -772,10 +852,28 @@ std::ostream & operator<< (std::ostream& os, const Mesh_complex_3_in_triangulation_3 &c3t3) { - // TODO: implement edge saving typedef typename Mesh_complex_3_in_triangulation_3::Concurrency_tag Concurrency_tag; - return os << static_cast< + os << static_cast< const Mesh_3::Mesh_complex_3_in_triangulation_3_base&>(c3t3); + if(os.good() && c3t3.triangulation().dimension() > 0) + { + Unique_hash_map vertex_index_map; + + + typename Tr::size_type i = 0; + vertex_index_map[c3t3.triangulation().infinite_vertex()] = 0; + auto vit = c3t3.triangulation().vertices_begin(); + //skip infinite vertex + ++vit; + for(; vit != c3t3.triangulation().vertices_end(); ++vit) + { + vertex_index_map[vit] = ++i; + } + CGAL_triangulation_assertion(i == c3t3.triangulation().number_of_vertices()); + CGAL_triangulation_assertion(c3t3.triangulation().is_infinite(c3t3.triangulation().vertices_begin())); + c3t3.write_edges_in_complex(os, vertex_index_map); + } + return os; } @@ -784,11 +882,23 @@ std::istream & operator>> (std::istream& is, Mesh_complex_3_in_triangulation_3 &c3t3) { - // TODO: implement edge loading typedef typename Mesh_complex_3_in_triangulation_3::Concurrency_tag Concurrency_tag; is >> static_cast< Mesh_3::Mesh_complex_3_in_triangulation_3_base&>(c3t3); + c3t3.rescan_after_load_of_triangulation(); + //rebuild index_vertex_map + std::vector< typename Tr::Vertex_handle > V(c3t3.triangulation().number_of_vertices()+1); + //V[0] = c3t3.triangulation().infinite_vertex(); // the infinite vertex is numbered 0 + std::size_t i = 0; + auto vit = c3t3.triangulation().vertices_begin(); + for(vit; vit != c3t3.triangulation().vertices_end(); ++vit) + { + V[i++] = vit; + } + + //load edges_in_complex + c3t3.read_edges_in_complex(is, V); return is; } diff --git a/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.binary.cgal b/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.binary.cgal index f4c958d92393..1706d36032c5 100644 Binary files a/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.binary.cgal and b/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.binary.cgal differ diff --git a/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.cgal b/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.cgal index f0c10161e35f..4c3aed161598 100644 --- a/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.cgal +++ b/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.cgal @@ -44,3 +44,6 @@ CGAL c3t3 Triangulation_3(Weighted_point,Vb(Tvb_3+i+boost::variant,Vb(Tvb_3+i+i),Cb(i+RTcb_3+(i)[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 +1 3 5 +1 4 6 diff --git a/Mesh_3/test/Mesh_3/data/c3t3_io-pairs.binary.cgal b/Mesh_3/test/Mesh_3/data/c3t3_io-pairs.binary.cgal new file mode 100644 index 000000000000..1b9e33d3a3dd Binary files /dev/null and b/Mesh_3/test/Mesh_3/data/c3t3_io-pairs.binary.cgal differ diff --git a/Mesh_3/test/Mesh_3/data/c3t3_io-pairs.cgal b/Mesh_3/test/Mesh_3/data/c3t3_io-pairs.cgal new file mode 100644 index 000000000000..1a7c5b095ae9 --- /dev/null +++ b/Mesh_3/test/Mesh_3/data/c3t3_io-pairs.cgal @@ -0,0 +1,49 @@ +CGAL c3t3 Triangulation_3(Weighted_point,Vb(Tvb_3+i+i),Cb(i+RTcb_3+(i)[4]))+C3t3_data> +3 +6 +10 11 12 0 0 7 +11 13 10 0 0 8 +7 4 6 0 1 5 +5 2 14 0 1 6 +1 2 3 0 2 3 +3 9 13 0 3 1 +12 +0 1 3 4 +4 0 1 6 +4 3 5 6 +5 0 4 6 +3 2 1 0 +3 0 4 5 +0 3 2 5 +4 1 3 6 +5 3 2 6 +2 3 1 6 +2 0 5 6 +0 2 1 6 +7 5 1 4 +11 7 3 0 +8 3 7 5 +1 2 10 5 +11 0 6 9 +3 2 6 0 +8 10 5 4 +9 2 1 0 +9 10 2 6 +7 11 8 4 +3 8 11 6 +9 1 10 4 +0 3 0 0 0 +0 0 4 0 0 +1 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +2 0 0 4 3 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +2 +1 3 5 6 +1 4 6 7 diff --git a/Mesh_3/test/Mesh_3/test_c3t3_io.cpp b/Mesh_3/test/Mesh_3/test_c3t3_io.cpp index a937d691868f..042fe7964468 100644 --- a/Mesh_3/test/Mesh_3/test_c3t3_io.cpp +++ b/Mesh_3/test/Mesh_3/test_c3t3_io.cpp @@ -38,6 +38,11 @@ struct MD_homogeneous_types { { return "Triangulation_3(Weighted_point,Vb(Tvb_3+i+i),Cb(i+RTcb_3+(i)[4]))"; } + + static Index index_from_curve_index (const Curve_index &curve_index) + { + return curve_index; + } }; // One with heterogeneous index types @@ -65,8 +70,38 @@ struct MD_heterogeneous_types { { return "Triangulation_3(Weighted_point,Vb(Tvb_3+i+boost::variant,i,d>),Cb(enum+RTcb_3+(std::pair)[4]))"; } + static Index index_from_curve_index (const Curve_index &curve_index) + { + return curve_index; + } }; +struct MD_curve_pair { + typedef CGAL::Tag_false Has_features; + typedef int Subdomain_index; + typedef int Surface_patch_index; + typedef std::pair Curve_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_index get_curve_index_1() { return std::make_pair(5,6); } + static Curve_index get_curve_index_2() { return std::make_pair(6,7); } + static Corner_index get_corner_index_1() { return 7; } + static Corner_index get_corner_index_2() { return 8; } + + static std::string reference_format_string() + { + return "Triangulation_3(Weighted_point,Vb(Tvb_3+i+i),Cb(i+RTcb_3+(i)[4]))"; + } + static Index index_from_curve_index (const Curve_index &curve_index) + { + return curve_index.first; + } +}; // // Define I/O for MD_heterogeneous_types::Subdomain_index (then enum) // @@ -446,19 +481,137 @@ struct Test_c3t3_io { v2->set_dimension(0); v2->set_index(Mesh_domain::get_corner_index_2()); v3->set_dimension(1); - v3->set_index(Mesh_domain::get_curve_index_1()); + v3->set_index(Mesh_domain::index_from_curve_index(Mesh_domain::get_curve_index_1())); v4->set_dimension(1); - v4->set_index(Mesh_domain::get_curve_index_2()); + v4->set_index(Mesh_domain::index_from_curve_index(Mesh_domain::get_curve_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, prefix, false) && test_io(c3t3, prefix, true); + bool res = test_io(c3t3, prefix, false); + res &= test_io(c3t3, prefix, true); + return res; } }; +bool test_data_type() +{ + + // + struct MD_1 { + typedef CGAL::Tag_false Has_features; + typedef int Subdomain_index; + typedef int Surface_patch_index; + typedef unsigned int Curve_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_index get_curve_index_1() { return 5; } + static Curve_index get_curve_index_2() { return 6; } + static Corner_index get_corner_index_1() { return 7; } + static Corner_index get_corner_index_2() { return 8; } + + static std::string reference_format_string() + { + return "Triangulation_3(Weighted_point,Vb(Tvb_3+i+i),Cb(i+RTcb_3+(i)[4]))"; + } + }; + + typedef CGAL::Mesh_triangulation_3::Type Tr_1; + typedef MD_homogeneous_types MD_2; + typedef MD_1::Curve_index Curve_index_1; + typedef MD_1::Corner_index Corner_index_1; + typedef Tr_1::Point Point; + typedef Tr_1::Vertex_handle Vertex_handle; + typedef Tr_1::Edge Edge; + typedef Tr_1::Facet Facet; + typedef Tr_1::Cell_handle Cell_handle; + + typedef CGAL::Mesh_complex_3_in_triangulation_3< + Tr_1, + Corner_index_1, + Curve_index_1 + > C3t3_1; + + typedef MD_2::Curve_index Curve_index_2; + typedef MD_2::Corner_index Corner_index_2; + + typedef CGAL::Mesh_triangulation_3::Type Tr_2; + typedef CGAL::Mesh_complex_3_in_triangulation_3< + Tr_2, + Corner_index_2, + Curve_index_2 + > C3t3_2; + + + C3t3_1 c3t3; + C3t3_2 c3t3_2; + Tr_1& 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(c2, MD_1::get_sub_domain_index_2()); + c3t3.add_to_complex(c1, MD_1::get_sub_domain_index_1()); + c3t3.add_to_complex(f1, MD_1::get_surface_patch_index_1()); + c3t3.add_to_complex(f2, MD_1::get_surface_patch_index_2()); + c3t3.add_to_complex(e1, MD_1::get_curve_index_1()); + c3t3.add_to_complex(e2, MD_1::get_curve_index_2()); + c3t3.add_to_complex(v1, MD_1::get_corner_index_1()); + c3t3.add_to_complex(v2, MD_1::get_corner_index_2()); + + // Fill indices in various faces (with different dimensions) + v1->set_dimension(0); + v1->set_index(MD_1::get_corner_index_1()); + v2->set_dimension(0); + v2->set_index(MD_1::get_corner_index_2()); + v3->set_dimension(1); + v3->set_index(MD_1::get_curve_index_1()); + v4->set_dimension(1); + v4->set_index(MD_1::get_curve_index_2()); + v5->set_dimension(2); + v5->set_index(MD_1::get_surface_patch_index_1()); + v6->set_dimension(3); + v6->set_index(MD_1::get_sub_domain_index_1()); + + std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out; + std::stringstream stream(mode); + CGAL::Mesh_3::save_binary_file(stream, c3t3, false); + assert(stream); + CGAL::Mesh_3::load_binary_file(stream, c3t3_2); + assert(stream); + std::ostringstream c3t3_1_oss; + c3t3_1_oss << "*****begin*****\n" + << c3t3 + << "\n******end******" << std::endl; + std::ostringstream c3t3_2_oss; + c3t3_2_oss << "*****begin*****\n" + << c3t3_2 + << "\n******end******" << std::endl; + assert(0 == c3t3_1_oss.str().compare(c3t3_2_oss.str())); + + assert(stream); + return true; +} + int main() { std::cout << "First test I/O when all indices are integers" << std::endl; @@ -473,4 +626,17 @@ int main() std::cerr << "Error\n"; return -1; } + std::cout << "Then test I/O when curve_index are pair of integers." << std::endl; + ok = Test_c3t3_io()("data/c3t3_io-pairs"); + if(!ok) { + std::cerr << "Error\n"; + return -1; + } + + std::cout << "Then test I/O with different curve_indices" << std::endl; + ok = test_data_type(); + if(!ok) { + std::cerr << "Error\n"; + return -1; + } } diff --git a/Triangulation_2/test/Triangulation_2/test_triangulation_2.cpp b/Triangulation_2/test/Triangulation_2/test_triangulation_2.cpp index 8c74676f5150..a6cfa48c5a4a 100644 --- a/Triangulation_2/test/Triangulation_2/test_triangulation_2.cpp +++ b/Triangulation_2/test/Triangulation_2/test_triangulation_2.cpp @@ -56,6 +56,5 @@ int main() typedef CGAL::Homogeneous Gt6; typedef CGAL::Triangulation_2 Cls6; _test_cls_triangulation_2( Cls6() ); - return 0; } diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 0b6ca42d4664..c295e7cf7464 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -572,6 +572,7 @@ class Triangulation_3 GT _gt; Vertex_handle infinite; // infinite vertex + public: template // Point or Point_3 typename boost::result_of::type @@ -2350,6 +2351,23 @@ class Triangulation_3 CGAL_triangulation_assertion( is_valid(false) ); return is; } + + size_type fill_map(const size_type& num_vertices, Unique_hash_map& vertex_index_map) const + { + size_type i = 0; + vertex_index_map[infinite_vertex()] = 0; + auto vit = vertices_begin(); + //skip infinite vertex + ++vit; + for(; vit != vertices_end(); ++vit) + { + vertex_index_map[vit] = ++i; + } + CGAL_triangulation_assertion(i == num_vertices); + CGAL_triangulation_assertion(is_infinite(vertices_begin())); + return i; + } + }; @@ -2407,11 +2425,11 @@ std::istream& operator>> (std::istream& is, Triangulation_3& tr) for(std::size_t j=0 ; j < m; j++) if(!(is >> *(C[j]))) return is; - CGAL_triangulation_assertion(tr.is_valid(false)); return is; } + template < class GT, class Tds, class Lds > std::ostream& operator<< (std::ostream& os, const Triangulation_3& tr) { @@ -2428,7 +2446,6 @@ std::ostream& operator<< (std::ostream& os, const Triangulation_3& typedef Triangulation_3 Triangulation; typedef typename Triangulation::size_type size_type; typedef typename Triangulation::Vertex_handle Vertex_handle; - typedef typename Triangulation::Vertex_iterator Vertex_iterator; typedef typename Triangulation::Cell_iterator Cell_iterator; typedef typename Triangulation::Edge_iterator Edge_iterator; typedef typename Triangulation::Facet_iterator Facet_iterator; @@ -2447,29 +2464,22 @@ std::ostream& operator<< (std::ostream& os, const Triangulation_3& if(n == 0) return os; - - std::vector TV(n+1); - size_type i = 0; - // write the vertices - for(Vertex_iterator it = tr.vertices_begin(), end = tr.vertices_end(); it != end; ++it) - TV[i++] = it; - - CGAL_triangulation_assertion(i == n+1); - CGAL_triangulation_assertion(tr.is_infinite(TV[0])); - - Unique_hash_map V; - V[tr.infinite_vertex()] = 0; - for(i=1; i <= n; i++) + auto vit = tr.vertices_begin(); + ++vit; + for(; vit != tr.vertices_end(); ++vit) { - os << *TV[i]; - V[TV[i]] = i; + os << *vit; if(IO::is_ascii(os)) - os << std::endl; + os< vertex_index_map; + tr.fill_map(n, vertex_index_map); + + // Asks the tds for the combinatorial information - tr.tds().print_cells(os, V); + tr.tds().print_cells(os, vertex_index_map); // Write the non combinatorial information on the cells // using the << operator of Cell.