// Copyright (c) 2018 GeometryFactory Sarl (France). // All rights reserved. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Maxime Gimeno #ifndef CGAL_IO_VTK_H #define CGAL_IO_VTK_H #include #include #include #ifdef CGAL_USE_VTK #include #include #include #include #include #include namespace CGAL { namespace IO { namespace internal { //append the content of poly_data to a soup. template bool vtkPointSet_to_polygon_soup(vtkPointSet* poly_data, PointRange& points, PolygonRange& polygons, const NamedParameters&) { typedef typename boost::range_value::type Point; using parameters::get_parameter; using parameters::choose_parameter; vtkIdType nb_points = poly_data->GetNumberOfPoints(); vtkIdType nb_cells = poly_data->GetNumberOfCells(); polygons.reserve(nb_cells); std::size_t initial_number_of_pts = points.size(); // extract points points.reserve(initial_number_of_pts+nb_points); for(vtkIdType i=0; iGetPoint(i, coords); points.push_back(Point(coords[0], coords[1], coords[2])); } // extract cells for(vtkIdType i=0; iGetCellType(i); if(cell_type != 5 && cell_type != 7 && cell_type != 9) // only supported cells are triangles, quads and polygons continue; vtkCell* cell_ptr = poly_data->GetCell(i); vtkIdType nb_vertices = cell_ptr->GetNumberOfPoints(); if(nb_vertices < 3) return false; std::vector ids(nb_vertices); for(vtkIdType k=0; kGetPointId(k); ids[k] = id+initial_number_of_pts; } polygons.push_back(ids); } return true; } }//end internal }//end IO //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// /// Read template bool read_VTP(const char* fname, PointRange& points, PolygonRange& polygons, const NamedParameters& np) { vtkSmartPointer data; vtkSmartPointer obs = vtkSmartPointer::New(); data = vtkPolyData::SafeDownCast(IO::internal::read_vtk_file(fname, obs)->GetOutput()); return IO::internal::vtkPointSet_to_polygon_soup(data, points, polygons, np); } template bool read_VTP(const std::string& fname, PointRange& points, PolygonRange& polygons, const NamedParameters& np) { return read_VTP(fname.c_str(), points, polygons, np); } /*! * \ingroup IOstreamFunctions * * reads the content of `is` into `points` and `polygons`, in the VTPformat. * * \see \ref IOStreamVTK */ template bool read_VTP(const char* fname, PointRange& points, PolygonRange& polygons) { return read_VTP(fname, points, polygons, parameters::all_default()); } template bool read_VTP(const std::string& fname, PointRange& points, PolygonRange& polygons) { return read_VTP(fname.c_str(), points, polygons, parameters::all_default()); } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// /// Write namespace IO { namespace internal { // writes the polys appended data at the end of the .vtp file template void write_soup_polys(std::ostream& os, const PolygonRange& polygons, const std::vector& offsets, const std::vector& cell_type) { std::vector connectivity_table; std::size_t off = 0; std::vector cumul_offsets(offsets); for(size_t i = 0; i < polygons.size(); ++i) { const auto& poly = polygons[i]; off+=offsets[i]; cumul_offsets[i]=off; for(const std::size_t& i : poly) connectivity_table.push_back(i); } write_vector(os, connectivity_table); write_vector(os, cumul_offsets); write_vector(os, cell_type); } template void write_soup_points_tag(std::ostream& os, const PointRange& points, bool binary, std::size_t& offset) { typedef typename boost::range_value::type Point; 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 * points.size() * sizeof(FT) + sizeof(std::size_t); // 3 coords per points + length of the encoded data (size_t) } else { os << "\">\n"; for(const Point& p : points) os << p.x() << " " << p.y() << " " << p.z() << " "; os << " \n"; } os << " \n"; } template void write_soup_polys_tag(std::ostream& os, const PolygonRange& polygons, bool binary, std::size_t& offset, std::vector& size_map, std::vector& cell_type) { 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" << " =3); total_size +=size_map[i]; } // if binary output, just write the xml tag if(binary) { os << " offset=\"" << offset << "\"/>\n"; offset += (total_size + 1) * sizeof(std::size_t); // n indices (size_t) per triangle + length of the encoded data (size_t) } else { os << ">\n"; for(const auto& poly : polygons) { for(const std::size_t& id : poly) os << id << " "; } os << " \n"; } // Write offsets os << " \n"; offset += (polygons.size() + 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(std::size_t i = 0; i < polygons.size(); ++i) { polys_offset += size_map[i]; os << polys_offset << " "; } os << " \n"; } // Write cell type (triangle == 5) os << " \n"; offset += polygons.size() + 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< polygons.size(); ++i) { switch(size_map[i]){ case 3: cell_type[i]=5; os << "5 ";//triangle break; case 4: cell_type[i]=7; os << "7 ";//quad break; default: cell_type[i]=9; os << "9 ";//polygon break; } } os << " \n"; } os << " \n"; } // writes the points appended data at the end of the .vtp file template void write_soup_polys_points(std::ostream& os, const PointRange& points) { typedef typename boost::range_value::type Point; typedef typename CGAL::Kernel_traits::Kernel Gt; typedef typename Gt::FT FT; std::vector coordinates; for(const Point& p : points) { coordinates.push_back(p.x()); coordinates.push_back(p.y()); coordinates.push_back(p.z()); } write_vector(os, coordinates); } }//end internal }//end IO template bool write_VTP(std::ostream& os, const PointRange& points, const PolygonRange& polygons, const CGAL_BGL_NP_CLASS& np) { using parameters::get_parameter; using parameters::choose_parameter; os << "\n" << "\n" << " " << "\n"; os << " \n"; std::size_t offset = 0; const bool binary = choose_parameter(get_parameter(np, internal_np::use_binary_mode), true); std::vector size_map; std::vector cell_type; IO::internal::write_soup_points_tag(os, points, binary, offset); IO::internal::write_soup_polys_tag(os, polygons, binary, offset, size_map, cell_type); os << " \n" << " \n"; if(binary) { os << "\n_"; IO::internal::write_soup_polys_points(os, points); IO::internal::write_soup_polys(os, polygons,size_map, cell_type); } os << "\n"; } /*! * \ingroup IOstreamFunctions * * writes the content of `points` and `polygons` in `out`, in the VTP format. * * \cgalNamedParamsBegin * \cgalParamBegin{use_binary_mode} a Boolean indicating if the * data should be written in binary (`true`, the default) or in ASCII (`false`). * \cgalParamEnd * \cgalNamedParamsEnd * \see \ref IOStreamVTK */ template bool write_VTP(std::ostream& os, const PointRange& points, const PolygonRange& polygons) { return write_VTP(os, points, polygons, parameters::all_default()); } template bool write_VTP(const char* fname, const PointRange& points, const PolygonRange& polygons, const CGAL_BGL_NP_CLASS& np) { std::ofstream out(fname); return write_VTP(out, points, polygons, np); } /*! * \ingroup IOstreamFunctions * * writes the content of `points` and `polygons` in a file named `fname`, in the VTP format. * * \cgalNamedParamsBegin * \cgalParamBegin{use_binary_mode} a Boolean indicating if the * data should be written in binary (`true`, the default) or in ASCII (`false`). * \cgalParamEnd * \cgalNamedParamsEnd * \see \ref IOStreamVTK */ template bool write_VTP(const char* fname, const PointRange& points, const PolygonRange& polygons) { return write_VTP(fname, points, polygons, parameters::all_default()); } template bool write_VTP(const std::string& fname, const PointRange& points, const PolygonRange& polygons, const CGAL_BGL_NP_CLASS& np) { return write_VTP(fname.c_str(), points, polygons, np); } template bool write_VTP(const std::string& fname, const PointRange& points, const PolygonRange& polygons) { return write_VTP(fname, points, polygons, parameters::all_default()); } }//end CGAL #endif //CGAL_USE_VTK #endif // CGAL_IO_VTK_H