// 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). // You can redistribute it and/or modify it under the terms of the GNU // General Public License as published by the Free Software Foundation, // either version 3 of the License, or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // // Author(s) : Laurent RINEAU, Stephane Tayeb, Maxime Gimeno #ifndef CGAL_VTK_IO_H #define CGAL_VTK_IO_H #include #include #include #include namespace CGAL{ // writes the appended data into the .vtu file template void write_vector(std::ostream& os, const std::vector& vect) { const char* buffer = reinterpret_cast(&(vect[0])); std::size_t size = vect.size()*sizeof(FT); os.write(reinterpret_cast(&size), sizeof(std::size_t)); // number of bytes encoded os.write(buffer, vect.size()*sizeof(FT)); // encoded data } // writes the cells tags before binary data is appended 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"; } // 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"; } // 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"; } os << " \n"; } // writes the cells appended data at the end of the .vtu file template void write_cells(std::ostream& os, const C3T3 & c3t3, std::map & V, std::vector& mids) { 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)]); mids.push_back(cit->subdomain_index()); } write_vector(os,connectivity_table); write_vector(os,offsets); write_vector(os,cell_type); } // writes the polys appended data at the end of the .vtp file template void write_polys(std::ostream& os, const Mesh & mesh, const NamedParameters& np) { typedef typename boost::graph_traits::face_iterator face_iterator; typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), get_const_property_map(CGAL::internal_np::vertex_index, mesh)); typedef typename boost::property_traits::value_type Point_t; typedef typename CGAL::Kernel_traits::Kernel Gt; typedef typename Gt::FT FT; std::vector connectivity_table; std::vector offsets; std::vector cell_type(num_faces(mesh),5); // triangle == 5 std::size_t off = 0; for( face_iterator fit = faces(mesh).begin() ; fit != faces(mesh).end() ; ++fit ) { off += 3; offsets.push_back(off); BOOST_FOREACH(vertex_descriptor v, vertices_around_face(halfedge(*fit, mesh), mesh)) connectivity_table.push_back(V[v]); } write_vector(os,connectivity_table); write_vector(os,offsets); write_vector(os,cell_type); } //overload template void write_polys(std::ostream& os, const Mesh & mesh) { write_polys(os, mesh, CGAL::parameters::all_default()); } //todo use named params for maps template void write_polys_tag(std::ostream& os, const Mesh & mesh, bool binary, std::size_t& offset, const NamedParameters& np) { typedef typename boost::graph_traits::face_iterator face_iterator; typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; typedef typename CGAL::Polygon_mesh_processing::GetVertexIndexMap::type Vimap; Vimap V = choose_param(get_param(np, CGAL::internal_np::vertex_index), get_const_property_map(CGAL::internal_np::vertex_index, mesh)); typedef typename boost::property_traits::value_type Point_t; typedef typename CGAL::Kernel_traits::Kernel Gt; typedef typename Gt::FT FT; 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 += (3 * num_faces(mesh)+ 1) * sizeof(std::size_t); // 3 indices (size_t) per triangle + length of the encoded data (size_t) } else { os << "\">\n"; for( face_iterator fit = faces(mesh).begin() ; fit != faces(mesh).end() ; ++fit ) { BOOST_FOREACH(vertex_descriptor v, vertices_around_face(halfedge(*fit, mesh), mesh)) os << V[v] << " "; } os << " \n"; } // Write offsets os << " \n"; offset += (num_faces(mesh) + 1) * sizeof(std::size_t); // 1 offset (size_t) per triangle + length of the encoded data (size_t) } else { os << "\">\n"; std::size_t polys_offset = 0; for( face_iterator fit = faces(mesh).begin() ; fit != faces(mesh).end() ; ++fit ) { polys_offset += 3; os << polys_offset << " "; } os << " \n"; } // Write cell type (triangle == 5) os << " \n"; offset += num_faces(mesh) + sizeof(std::size_t); // 1 unsigned char per cell + length of the encoded data (size_t) } else { os << "\">\n"; for(std::size_t i = 0; i< num_faces(mesh); ++i) os << "5 "; os << " \n"; } os << " \n"; } //overload template void write_polys_tag(std::ostream& os, const Mesh & mesh, bool binary, std::size_t& offset) { write_polys_tag(os, mesh, binary, offset, CGAL::parameters::all_default()); } // writes the points tags before binary data is appended template void write_points_tag(std::ostream& os, const Tr & tr, std::map & V, bool binary, std::size_t& offset, std::size_t dim) { 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 += dim * tr.number_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) { V[vit] = inum++; os << vit->point().x() << " " << vit->point().y()<< " " ; if(dim == 3) os << vit->point().z() << " "; } os << " \n"; } os << " \n"; } //todo : use namedparams for points and ids //overload for facegraph template void write_points_tag(std::ostream& os, const Mesh & mesh, bool binary, std::size_t& offset, const NamedParameters& np) { typedef typename boost::graph_traits::vertex_iterator vertex_iterator; typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), get_const_property_map(CGAL::vertex_point, mesh)); typedef typename boost::property_traits::value_type Point_t; typedef typename CGAL::Kernel_traits::Kernel Gt; typedef typename Gt::FT FT; std::string format = binary ? "appended" : "ascii"; std::string type = (sizeof(FT) == 8) ? "Float64" : "Float32"; os << " \n" << " \n"; offset += 3 * num_vertices(mesh) * sizeof(FT) + sizeof(std::size_t); // 3 coords per points + length of the encoded data (size_t) } else { os << "\">\n"; for( vertex_iterator vit = vertices(mesh).begin(); vit != vertices(mesh).end(); ++vit) { os << get(vpm, *vit).x() << " " << get(vpm, *vit).y() << " " << get(vpm, *vit).z() << " "; } os << " \n"; } os << " \n"; } //overload template void write_points_tag(std::ostream& os, const Mesh & mesh, bool binary, std::size_t& offset) { write_points_tag(os, mesh, binary, offset, CGAL::parameters::all_default()); } // writes the points appended data at the end of the .vtu file template void write_points(std::ostream& os, const Tr & tr, std::map & V, std::size_t dim) { 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) { V[vit] = inum++; // binary output => the map has not been filled yet coordinates.push_back(vit->point().x()); coordinates.push_back(vit->point().y()); if(dim == 3) coordinates.push_back(vit->point().z()); } write_vector(os,coordinates); } // writes the points appended data at the end of the .vtp file template void write_polys_points(std::ostream& os, const Mesh & mesh, const NamedParameters& np) { typedef typename boost::graph_traits::vertex_iterator vertex_iterator; typedef typename CGAL::Polygon_mesh_processing::GetVertexPointMap::const_type Vpmap; Vpmap vpm = choose_param(get_param(np, CGAL::vertex_point), get_const_property_map(CGAL::vertex_point, mesh)); typedef typename boost::property_traits::value_type Point_t; typedef typename CGAL::Kernel_traits::Kernel Gt; typedef typename Gt::FT FT; std::vector coordinates; for( vertex_iterator vit = vertices(mesh).begin(); vit != vertices(mesh).end(); ++vit) { coordinates.push_back(get(vpm, *vit).x()); coordinates.push_back(get(vpm, *vit).y()); coordinates.push_back(get(vpm, *vit).z()); } write_vector(os,coordinates); } //overload template void write_polys_points(std::ostream& os, const Mesh & mesh) { write_polys_points(os, mesh, CGAL::parameters::all_default()); } // 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 = (sizeof(T) == 8) ? "Float64" : "Float32"; 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"; } } // 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); } template void write_unstructured_grid(std::ostream& os, const C3t3& c3t3, std::size_t dim) { 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"; os << " \n"; bool binary = true; std::size_t offset = 0; write_points_tag(os,tr,V,binary,offset, dim); write_cells_tag(os,c3t3,V,binary,offset); if(dim==3) { os << " \n"; std::vector mids; write_attribute_tag(os,"MeshDomain",mids,binary,offset); os << " \n"; } os << " \n" << " \n"; if (binary) { os << "\n_"; write_points(os,tr,V, dim); // write points before cells to fill the std::map V write_cells(os,c3t3,V, mids);//todo mids should be filled by write_attribute_tag if(dim==3) write_attributes(os,mids); } os << "\n"; } //public API //! //! \brief write_polydata_3 writes the content of a triangulated surface mesh in the .vtp //! XML format. //! //! \tparam TriangleMesh a model of `FaceListGraph` with triangle faces. //! \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" //! //! \param os a `std::ostream`. //! \param mesh an instance of `TriangleMesh` to be written. //! \param binary decides if the data should be written in binary(`true`) //! or in ASCII(`false`). //! \param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the //! ones listed below //! //! \cgalNamedParamsBegin //! \cgalParamBegin{vertex_point_map} the property map with the points associated to //! the vertices of `mesh`. If this parameter is omitted, an internal property map for //! `CGAL::vertex_point_t` must be available in `TriangleMesh`. //! \cgalParamEnd //! \cgalParamBegin{vertex_index_map} the property map with the indices associated to //! the vertices of `mesh`. If this parameter is omitted, an internal property map for //! `CGAL::vertex_index_t` must be available in `TriangleMesh`. //! \cgalParamEnd //! \cgalNamedParamsEnd template void write_polydata(std::ostream& os, const TriangleMesh& mesh, bool binary, const NamedParameters& np) { os << "\n" << "\n" << " " << "\n"; os << " \n"; std::size_t offset = 0; write_points_tag(os,mesh,binary,offset, np); write_polys_tag(os,mesh,binary,offset, np); os << " \n" << " \n"; if (binary) { os << "\n_"; write_polys_points(os,mesh, np); write_polys(os,mesh, np); } os << "\n"; } template void write_polydata(std::ostream& os, const TriangleMesh& mesh, bool binary = true) { write_polydata(os, mesh, binary, CGAL::parameters::all_default()); } //! //! \brief write_unstructured_grid_3 writes the content of a `C3t3` in the .vtu //! XML format. //! //! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. //! //! \param os a `std::ostream`. //! \param c3t3 an instance of `C3T3` to be written. //! \param binary decides if the data should be written in binary(`true`) //! or in ASCII(`false`). //! template void write_unstructured_grid_3(std::ostream& os, const C3T3& c3t3) { write_unstructured_grid(os, c3t3, 3); } //! //! \brief write_unstructured_grid_2 writes the content of a `CDT` in the .vtu //! XML format. //! //! \tparam CDT must be 2D constrained Delaunay triangulation //! //! \param os a `std::ostream`. //! \param tr ????????? //! \param binary decides if the data should be written in binary(`true`) //! or in ASCII(`false`). //! //! template void write_unstructured_grid_2(std::ostream& os, const CDT& tr) { write_unstructured_grid(os, tr, 2); } } //end CGAL #endif // CGAL_VTK_IO_H