// Copyright (c) 2018 GeometryFactory (France). // Copyright (c) 2004-2006 INRIA Sophia-Antipolis (France). // Copyright (c) 2009 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Mesh_3/include/CGAL/IO/output_to_vtu.h $ // $Id: output_to_vtu.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno #ifndef CGAL_OUTPUT_TO_VTU_H #define CGAL_OUTPUT_TO_VTU_H #include #include #include #include #include #include #include #include //todo try to factorize with functors namespace CGAL{ template void write_cells_tag(std::ostream& os, const C3T3 & c3t3, std::map & V, bool binary, std::size_t& offset) { typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; std::string formatattribute = binary ? " format=\"appended\"" : " format=\"ascii\""; std::string typeattribute; switch(sizeof(std::size_t)) { case 8: typeattribute = " type=\"UInt64\""; break; case 4: typeattribute = " type=\"UInt32\""; break; default: CGAL_error_msg("Unknown size of std::size_t"); } // Write connectivity table os << " \n" << " \n"; offset += (4 * c3t3.number_of_cells() + 1) * sizeof(std::size_t); // 4 indices (size_t) per cell + length of the encoded data (size_t) } else { os << ">\n"; for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; cit != c3t3.cells_in_complex_end() ; ++cit ) { for (int i=0; i<4; i++) os << V[cit->vertex(i)] << " "; } os << "\n \n"; } // Write offsets os << " \n"; offset += (c3t3.number_of_cells() + 1) * sizeof(std::size_t); // 1 offset (size_t) per cell + length of the encoded data (size_t) } else { os << ">\n"; std::size_t cells_offset = 0; for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; cit != c3t3.cells_in_complex_end() ; ++cit ) { cells_offset += 4; os << cells_offset << " "; } os << "\n \n"; } // Write cell type (tetrahedra == 10) os << " \n"; offset += c3t3.number_of_cells() + sizeof(std::size_t); // 1 unsigned char per cell + length of the encoded data (size_t) } else { os << ">\n"; for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; cit != c3t3.cells_in_complex_end() ; ++cit ) os << "10 "; os << "\n \n"; } os << " \n"; } template void write_cells(std::ostream& os, const C3T3 & c3t3, std::map & V) { typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; std::vector connectivity_table; std::vector offsets; std::vector cell_type(c3t3.number_of_cells(),10); // tetrahedra == 10 std::size_t off = 0; for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; cit != c3t3.cells_in_complex_end() ; ++cit ) { off += 4; offsets.push_back(off); for (int i=0; i<4; i++) connectivity_table.push_back(V[cit->vertex(i)]); } write_vector(os,connectivity_table); write_vector(os,offsets); write_vector(os,cell_type); } template void write_c3t3_points_tag(std::ostream& os, const Tr & tr, std::size_t size_of_vertices, std::map & V, bool binary, std::size_t& offset) { std::size_t dim = 3; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Geom_traits Gt; typedef typename Gt::FT FT; std::size_t inum = 0; std::string format = binary ? "appended" : "ascii"; std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; os << " \n" << " \n"; offset += 3 * size_of_vertices * sizeof(FT) + sizeof(std::size_t); // dim coords per points + length of the encoded data (size_t) } else { os << "\">\n"; for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); vit != tr.finite_vertices_end(); ++vit) { if(vit->in_dimension() <= -1) continue; V[vit] = inum++; os << vit->point()[0] << " "; os << vit->point()[1] << " "; if(dim == 3) os << vit->point()[2] << " "; else os << 0.0 << " "; } os << "\n \n"; } os << " \n"; } // writes the points appended data at the end of the .vtu file template void write_c3t3_points(std::ostream& os, const Tr & tr, std::map & V) { std::size_t dim = 3; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Geom_traits Gt; typedef typename Gt::FT FT; std::size_t inum = 0; std::vector coordinates; for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); vit != tr.finite_vertices_end(); ++vit) { if(vit->in_dimension() <= -1) continue; V[vit] = inum++; // binary output => the map has not been filled yet coordinates.push_back(vit->point()[0]); coordinates.push_back(vit->point()[1]); coordinates.push_back(dim == 3 ? vit->point()[2] : 0.0); } write_vector(os,coordinates); } // writes the attribute tags before binary data is appended template void write_attribute_tag(std::ostream& os, const std::string& attr_name, const std::vector& attribute, bool binary, std::size_t& offset) { std::string format = binary ? "appended" : "ascii"; std::string type = ""; if(std::is_floating_point::value) { type = (sizeof(T) == 8) ? "Float64" : "Float32"; } else { if(sizeof(T) == 1) type = "UInt8"; else if(sizeof(T) == 4) type = "UInt32"; else type = "UInt64"; } os << " \n"; offset += attribute.size() * sizeof(T) + sizeof(std::size_t); } else { typedef typename std::vector::const_iterator Iterator; os << "\">\n"; for (Iterator it = attribute.begin(); it != attribute.end(); ++it ) os << *it << " "; os << "\n \n"; } } // writes the attributes appended data at the end of the .vtu file template void write_attributes(std::ostream& os, const std::vector& att) { write_vector(os,att); } enum VTU_ATTRIBUTE_TYPE{ DOUBLE=0, UNIT_8, SIZE_TYPE }; typedef boost::variant*, const std::vector*, const std::vector* > Vtu_attributes; template void output_to_vtu_with_attributes(std::ostream& os, const C3T3& c3t3, std::vector >&attributes, IO::Mode mode = IO::BINARY) { //CGAL_assertion(attributes.size() == attribute_types.size()); typedef typename C3T3::Triangulation Tr; typedef typename Tr::Vertex_handle Vertex_handle; const Tr& tr = c3t3.triangulation(); std::map V; //write header os << "\n" << "\n" << " " << "\n"; const std::size_t number_of_vertices = tr.number_of_vertices() - c3t3.number_of_far_points(); os << " \n"; std::size_t offset = 0; const bool binary = (mode == IO::BINARY); write_c3t3_points_tag(os,tr,number_of_vertices,V,binary,offset); write_cells_tag(os,c3t3,V,binary,offset); // fills V if the mode is ASCII os << " \n"; for(std::size_t i = 0; i< attributes.size(); ++i) { switch(attributes[i].second.which()){ case 0: write_attribute_tag(os,attributes[i].first, *boost::get* >(attributes[i].second), binary,offset); break; case 1: write_attribute_tag(os,attributes[i].first, *boost::get* >(attributes[i].second), binary,offset); break; default: write_attribute_tag(os,attributes[i].first, *boost::get* >(attributes[i].second), binary,offset); break; } } os << " \n"; os << " \n" << " \n"; if (binary) { os << "\n_"; write_c3t3_points(os,tr,V); // fills V if the mode is BINARY write_cells(os,c3t3,V); for(std::size_t i = 0; i< attributes.size(); ++i) switch(attributes[i].second.which()){ case 0: write_attributes(os, *boost::get* >(attributes[i].second)); break; case 1: write_attributes(os, *boost::get* >(attributes[i].second)); break; default: write_attributes(os, *boost::get* >(attributes[i].second)); break; } } os << "\n"; } //public API template void output_to_vtu(std::ostream& os, const C3T3& c3t3, IO::Mode mode = IO::BINARY) { typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; std::vector mids; for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; cit != c3t3.cells_in_complex_end() ; ++cit ) { double v = cit->subdomain_index(); mids.push_back(v); } std::vector > atts; Vtu_attributes v = &mids; atts.push_back(std::make_pair("MeshDomain", v)); output_to_vtu_with_attributes(os, c3t3, atts, mode); } } //end CGAL #endif // CGAL_VTK_IO_H