diff --git a/Linear_cell_complex/include/CGAL/Linear_cell_complex/IO/VTK.h b/Linear_cell_complex/include/CGAL/Linear_cell_complex/IO/VTK.h index 11d3afcb46e..0a70ee38e22 100644 --- a/Linear_cell_complex/include/CGAL/Linear_cell_complex/IO/VTK.h +++ b/Linear_cell_complex/include/CGAL/Linear_cell_complex/IO/VTK.h @@ -11,8 +11,11 @@ #ifndef CGAL_LCC_IO_VTK_H #define CGAL_LCC_IO_VTK_H 1 + #include #include +#include + #include #include #include @@ -24,7 +27,8 @@ namespace CGAL { namespace IO { /** \file VTK.h - * Functions to import/export 3D Linear_cell_complex from/to VTK legacy ASCII format. + * Functions to import/export 3D Linear_cell_complex from/to VTK legacy ASCII + * format. * * Only supports: * - Linear_cell_complex_for_combinatorial_map<3,3> @@ -47,7 +51,8 @@ namespace IO { // ============================================================================ /** - * \brief Read a VTK legacy ASCII file and load it into a 3D Linear_cell_complex. + * \brief Read a VTK legacy ASCII file and load it into a 3D + * Linear_cell_complex. * \ingroup PkgLinearCellComplexExamples * * \tparam LCC must be a Linear_cell_complex_for_combinatorial_map<3,3> @@ -61,11 +66,12 @@ namespace IO { * If provided, will be resized to match number of volumes. * \return `true` if loading was successful, `false` otherwise */ -template +template bool read_VTK(LCC& alcc, const char* filename, - std::vector* vertex_scalars = nullptr, - std::vector* volume_scalars = nullptr); + std::vector* vertex_scalars, + std::vector* volume_scalars); /** * \brief Write a 3D Linear_cell_complex to a VTK legacy ASCII file. @@ -82,208 +88,205 @@ bool read_VTK(LCC& alcc, * same size as number of 3-cells in the LCC. * \return `true` if writing was successful, `false` otherwise */ -template +template bool write_VTK(const LCC& alcc, const char* filename, - const std::vector* vertex_scalars = nullptr, - const std::vector* volume_scalars = nullptr); - -// Advanced versions with functors -template -bool read_VTK(LCC& alcc, const char* filename, VertexScalarReader vertex_reader, CellScalarReader cell_reader); + const std::vector* vertex_scalars, + const std::vector* volume_scalars); +// "Advanced" versions with functors template -bool write_VTK(const LCC& alcc, const char* filename, PointFunctor ptval, CellFunctor cellval); +bool write_VTK_with_fct(const LCC& alcc, const char* filename, + PointFunctor ptval, CellFunctor cellval); // ============================================================================ // Implementation details // ============================================================================ -namespace internal { +namespace internal +{ + ///////////////////////////////////////////////////////////////////////////// + // VTK type name mapping + // bit, unsigned_char, char, unsigned_short, short, unsigned_int, int, + // unsigned_long, long, float, double. + template + struct gettype + { static std::string name() { return "unknown"; }}; + template<> + struct gettype + { static std::string name() { return "bit"; }}; + template<> + struct gettype + { static std::string name() { return "unsigned_char"; }}; + template<> + struct gettype + { static std::string name() { return "char"; }}; + template<> + struct gettype + { static std::string name() { return "unsigned_short"; }}; + template<> + struct gettype + { static std::string name() { return "short"; }}; + template<> + struct gettype + { static std::string name() { return "unsigned_int"; }}; + template<> + struct gettype + { static std::string name() { return "int"; }}; + template<> + struct gettype + { static std::string name() { return "unsigned_long"; }}; + template<> + struct gettype + { static std::string name() { return "long"; }}; + template<> + struct gettype + { static std::string name() { return "float"; }}; + template<> + struct gettype + { static std::string name() { return "double"; }}; + ///////////////////////////////////////////////////////////////////////////// + // VTK cell type constants + enum VTK_Cell_Type + { + VTK_TETRA = 10, + VTK_VOXEL = 11, + VTK_HEXAHEDRON = 12, + VTK_WEDGE = 13, // Prism + VTK_PYRAMID = 14, + VTK_PENTAGONAL_PRISM = 15, + VTK_HEXAGONAL_PRISM = 16, + VTK_POLYHEDRON = 42 // Generic cell + }; + ///////////////////////////////////////////////////////////////////////////// + /// Write cell_data. + template + struct Write_cell_data + { + /// nb is the number of cells, + /// fct is a function having 3 parameters: a lcc, a dart_descriptor, + /// an the index of the cell. + template + static void run(std::ofstream& fo, LCC& lcc, std::size_t nb, FCT fct) + { + fo<<"CELL_DATA "<::name() + <<" 1"<().begin(), + itvolend=lcc.template one_dart_per_cell<3>().end(); + itvol!=itvolend; ++itvol, ++i) + { fo< + struct Write_cell_data + { + template + static void run(std::ofstream&, LCC&, std::size_t, std::nullptr_t) + {} + }; + ///////////////////////////////////////////////////////////////////////////// + /// Write point_data. + template + struct Write_point_data + { + /// nb is the number of cells, + /// fct is a function having 3 parameters: a lcc, a dart_descriptor, + /// an the index of the cell. + template + static void run(std::ofstream& fo, LCC& lcc, std::size_t nb, FCT fct) + { + fo<<"POINT_DATA "<::name() + <<" 1"<(itv), i)< + struct Write_point_data + { + template + static void run(std::ofstream&, LCC&, std::size_t, std::nullptr_t) + {} + }; + ///////////////////////////////////////////////////////////////////////////// + // Read data, stored values as T. + template + bool read_data(std::istream& fi, std::string& line, std::vector& data) + { + std::string txt, data_type; + std::size_t nb; + std::istringstream inputline(line); + inputline>>txt>>nb; // "CELL_DATA xxx" + fi>>txt>>txt; // "SCALARS cell_scalars " + fi>>data_type>>txt; // type for data + fi>>txt>>txt; // "LOOKUP_TABLE default" + if(!fi.good()) + { return false; } + data.clear(); + data.reserve(nb); + for(std::size_t i=0; i>txt)) + { return false; } -// Helper: read a scalar of the right type from stream -template -bool read_scalar_by_vtk_type(std::istream& is, const std::string& vtk_type, std::size_t n, Functor f) { - if(vtk_type == "float") { - for(std::size_t i = 0; i < n; ++i) { - float v; - if(!(is >> v)) - return false; - f(i, v); + std::stringstream ss{txt}; + T t; + ss>>t; + + data.push_back(t); } - } else if(vtk_type == "double") { - for(std::size_t i = 0; i < n; ++i) { - double v; - if(!(is >> v)) - return false; - f(i, v); - } - } else if(vtk_type == "int") { - for(std::size_t i = 0; i < n; ++i) { - int v; - if(!(is >> v)) - return false; - f(i, v); - } - } else if(vtk_type == "unsigned_int") { - for(std::size_t i = 0; i < n; ++i) { - unsigned int v; - if(!(is >> v)) - return false; - f(i, v); - } - } else if(vtk_type == "short") { - for(std::size_t i = 0; i < n; ++i) { - short int v; - if(!(is >> v)) - return false; - f(i, v); - } - } else if(vtk_type == "unsigned_short") { - for(std::size_t i = 0; i < n; ++i) { - unsigned short int v; - if(!(is >> v)) - return false; - f(i, v); - } - } else if(vtk_type == "char") { - for(std::size_t i = 0; i < n; ++i) { - char v; - int tmp; - if(!(is >> tmp)) - return false; - v = static_cast(tmp); - f(i, v); - } - } else if(vtk_type == "unsigned_char") { - for(std::size_t i = 0; i < n; ++i) { - unsigned char v; - int tmp; - if(!(is >> tmp)) - return false; - v = static_cast(tmp); - f(i, v); - } - } else if(vtk_type == "long") { - for(std::size_t i = 0; i < n; ++i) { - long int v; - if(!(is >> v)) - return false; - f(i, v); - } - } else if(vtk_type == "unsigned_long") { - for(std::size_t i = 0; i < n; ++i) { - unsigned long int v; - if(!(is >> v)) - return false; - f(i, v); - } - } else { - std::cerr << "[ERROR] read_VTK: unsupported scalar type: " << vtk_type << std::endl; - return false; + return true; } - return true; -} - -// VTK type name mapping -template struct gettype + ///////////////////////////////////////////////////////////////////////////// + // Helper: detect VTK cell type from a 3-cell + template + VTK_Cell_Type get_vtk_cell_type(const LCC& lcc, + typename LCC::Dart_const_descriptor itvol, + typename LCC::Dart_const_descriptor& sd) + { + using namespace CGAL::CMap::Element_topo; + cell_topo vol_type=get_cell_topo<3>(lcc, itvol, sd); + switch(vol_type) + { + case TETRAHEDRON: return VTK_TETRA; + case PYRAMID: return VTK_PYRAMID; + case PRISM: return VTK_WEDGE; + case HEXAHEDRON: return VTK_HEXAHEDRON; + // case PENTAGONAL_PRISM: return VTK_PENTAGONAL_PRISM; + // case HEXAGONAL_PRISM: return VTK_HEXAGONAL_PRISM; + // 24 QUADRATIC_TETRA + // 25 QUADRATIC_HEXAHEDRON + // 26 QUADRATIC_WEDGE + // 27 QUADRATIC_PYRAMID + default: break; + } + return VTK_POLYHEDRON; + } + ///////////////////////////////////////////////////////////////////////////// +template +bool read_lcc_from_vtk_ascii(std::istream& is, LCC& alcc, + std::vector* vertex_scalars=nullptr, + std::vector* cell_scalars=nullptr) { - static std::string name() { return "unknown"; } -}; -template <> struct gettype -{ - static std::string name() { return "bit"; } -}; -template <> struct gettype -{ - static std::string name() { return "unsigned_char"; } -}; -template <> struct gettype -{ - static std::string name() { return "char"; } -}; -template <> struct gettype -{ - static std::string name() { return "unsigned_short"; } -}; -template <> struct gettype -{ - static std::string name() { return "short"; } -}; -template <> struct gettype -{ - static std::string name() { return "unsigned_int"; } -}; -template <> struct gettype -{ - static std::string name() { return "int"; } -}; -template <> struct gettype -{ - static std::string name() { return "unsigned_long"; } -}; -template <> struct gettype -{ - static std::string name() { return "long"; } -}; -template <> struct gettype -{ - static std::string name() { return "float"; } -}; -template <> struct gettype -{ - static std::string name() { return "double"; } -}; - -// VTK cell type constants -enum VTK_Cell_Type { - VTK_TETRA = 10, - VTK_VOXEL = 11, - VTK_HEXAHEDRON = 12, - VTK_WEDGE = 13, - VTK_PYRAMID = 14, - VTK_PENTAGONAL_PRISM = 15, - VTK_HEXAGONAL_PRISM = 16, - VTK_POLYHEDRON = 42 -}; - -// Helper: detect VTK cell type from a 3-cell -template inline VTK_Cell_Type get_vtk_cell_type(const LCC& lcc, Dart itvol) { - // Heuristic: count number of vertices and faces - std::size_t nbv = 0, nbf = 0; - for(auto itv = lcc.template one_dart_per_incident_cell<0, 3>(itvol).begin(), - itvend = lcc.template one_dart_per_incident_cell<0, 3>(itvol).end(); - itv != itvend; ++itv) - ++nbv; - for(auto itf = lcc.template one_dart_per_incident_cell<2, 3>(itvol).begin(), - itfend = lcc.template one_dart_per_incident_cell<2, 3>(itvol).end(); - itf != itfend; ++itf) - ++nbf; - - if(nbv == 4 && nbf == 4) - return VTK_TETRA; - if(nbv == 5 && nbf == 5) - return VTK_PYRAMID; - if(nbv == 6 && nbf == 5) - return VTK_WEDGE; - if(nbv == 8 && nbf == 6) - return VTK_HEXAHEDRON; - if(nbv == 10 && nbf == 7) - return VTK_PENTAGONAL_PRISM; - if(nbv == 12 && nbf == 8) - return VTK_HEXAGONAL_PRISM; - return VTK_POLYHEDRON; -} - -template -bool read_lcc_from_vtk_ascii(std::istream& is, LCC& alcc, VertexScalarReader vertex_reader, CellScalarReader cell_reader) { - static_assert(LCC::dimension == 3 && LCC::ambient_dimension == 3, + static_assert(LCC::dimension==3 && LCC::ambient_dimension==3, "read_VTK() only supports 3D Linear_cell_complexes (3,3)"); - using Point = typename LCC::Point; - using FT = typename LCC::FT; - - alcc.clear(); + using Point=typename LCC::Point; + using FT=typename LCC::FT; Linear_cell_complex_incremental_builder_3 ib(alcc); @@ -291,297 +294,295 @@ bool read_lcc_from_vtk_ascii(std::istream& is, LCC& alcc, VertexScalarReader ver std::size_t npoints, ncells; // Skip to POINTS section - while(std::getline(is, line)) { - if(line.find("POINTS") != std::string::npos) - break; - } - if(is.eof()) { - std::cerr << "[ERROR] read_VTK: POINTS section not found" << std::endl; + while(std::getline(is, line) && line.find("POINTS")==std::string::npos) + {} + if(is.eof()) + { + std::cerr<<"[ERROR] read_VTK: POINTS section not found"<> npoints; + ss>>npoints; // Read points std::vector points(npoints); - for(std::size_t i = 0; i < npoints; ++i) { + for(std::size_t i=0; i> x >> y >> z)) { - std::cerr << "[ERROR] read_VTK: failed to read point " << i << std::endl; + if(!(is>>x>>y>>z)) + { + std::cerr<<"[ERROR] read_VTK: failed to read point "<> ncells; + ss>>ncells; // Read connectivity std::vector> faces(ncells); std::size_t points_per_cell; - for(std::size_t i = 0; i < ncells; ++i) { - if(!(is >> points_per_cell)) { - std::cerr << "[ERROR] read_VTK: failed to read cell " << i << std::endl; + for(std::size_t i=0; i>points_per_cell)) + { + std::cerr<<"[ERROR] read_VTK: failed to read cell "<> faces[i][j])) { - std::cerr << "[ERROR] read_VTK: failed to read cell " << i << " vertex " << j << std::endl; + for(std::size_t j=0; j>faces[i][j])) + { + std::cerr<<"[ERROR] read_VTK: failed to read cell "<> cell_type)) { - std::cerr << "[ERROR] read_VTK: failed to read cell type " << i << std::endl; + for(std::size_t i = 0; i>cell_type)) + { + std::cerr<<"[ERROR] read_VTK: failed to read cell type "<(itv) == alcc.null_descriptor) { - alcc.erase_vertex_attribute(itv); - } else { - ++itv; - } + for(auto itv=alcc.vertex_attributes().begin(); + itv!=alcc.vertex_attributes().end(); ++itv) + { + if(alcc.template dart_of_attribute<0>(itv)==alcc.null_descriptor) + { alcc.erase_vertex_attribute(itv); } } - // Read POINT_DATA scalars if present - while(std::getline(is, line)) { - if(line.find("POINT_DATA") != std::string::npos) { - std::size_t ndata; - ss = std::stringstream(line); - std::getline(ss, tmp, ' '); // skip "POINT_DATA" - ss >> ndata; - - std::getline(is, line); // SCALARS line - std::stringstream scalars_line(line); - std::string scalars, name, vtk_type; - scalars_line >> scalars >> name >> vtk_type; - - std::getline(is, line); // LOOKUP_TABLE line - - if(!read_scalar_by_vtk_type(is, vtk_type, ndata, vertex_reader)) { - std::cerr << "[ERROR] read_VTK: failed to read POINT_DATA" << std::endl; + while(std::getline(is, line)) + { + // Read POINT_DATA scalars if present + if(vertex_scalars!=nullptr && line.find("POINT_DATA")!=std::string::npos) + { + if(!read_data(is, line, *vertex_scalars)) + { + std::cerr<<"[ERROR] read_VTK: error when reading POINT_DATA." + <> ndata; - - std::getline(is, line); // SCALARS line - std::stringstream scalars_line(line); - std::string scalars, name, vtk_type; - scalars_line >> scalars >> name >> vtk_type; - - std::getline(is, line); // LOOKUP_TABLE line - - if(!read_scalar_by_vtk_type(is, vtk_type, ndata, cell_reader)) { - std::cerr << "[ERROR] read_VTK: failed to read CELL_DATA" << std::endl; + // Read CELL_DATA scalars if present + else if(cell_scalars!=nullptr && line.find("CELL_DATA")!=std::string::npos) + { + if(!read_data(is, line, *cell_scalars)) + { + std::cerr<<"[ERROR] read_VTK: error when reading CELL_DATA." + < -bool write_lcc_to_vtk_ascii(std::ostream& os, const LCC& alcc, PointFunctor ptval, CellFunctor cellval) { - static_assert(LCC::dimension == 3 && LCC::ambient_dimension == 3, +///////////////////////////////////////////////////////////////////////////// +template +bool write_lcc_topo_to_vtk_ascii(std::ostream& os, const LCC& alcc, + std::size_t& nbpts, std::size_t& nbcells) +{ + static_assert(LCC::dimension==3 && LCC::ambient_dimension==3, "write_VTK() only supports 3D Linear_cell_complexes (3,3)"); // Write VTK header - os << "# vtk DataFile Version 2.0\n"; - os << "CGAL Linear_cell_complex\n"; - os << "ASCII\n"; - os << "DATASET UNSTRUCTURED_GRID\n\n"; + os<<"# vtk DataFile Version 2.0\n"; + os<<"CGAL Linear_cell_complex\n"; + os<<"ASCII\n"; + os<<"DATASET UNSTRUCTURED_GRID\n\n"; - // Build vertex index map - std::unordered_map vertex_index; - std::size_t nbpts = 0; - - for(auto itv = alcc.vertex_attributes().begin(), itvend = alcc.vertex_attributes().end(); itv != itvend; ++itv) { - vertex_index[itv] = nbpts++; + // Build vertex index map and write points + std::unordered_map + index; + nbpts=0; + os<<"POINTS "<point()<point(); - os << p.x() << " " << p.y() << " " << p.z() << "\n"; - } - os << "\n"; + os<().begin(), itvolend = alcc.template one_dart_per_cell<3>().end(); - itvol != itvolend; ++itvol) - { - ++nbcells; - VTK_Cell_Type cell_type = get_vtk_cell_type(alcc, itvol); - type_stream << static_cast(cell_type) << "\n"; - - if(cell_type == VTK_POLYHEDRON) { - // Generic polyhedron format write as face-vertex connectivity - std::vector> faces; - std::size_t cell_size = 1; // Start with 1 for number of faces - - for(auto itface = alcc.template one_dart_per_incident_cell<2, 3>(itvol).begin(), - itfaceend = alcc.template one_dart_per_incident_cell<2, 3>(itvol).end(); - itface != itfaceend; ++itface) - { - faces.push_back(std::vector()); - auto& face = faces.back(); - - for(auto itvert = alcc.template darts_of_orbit<1>(itface).begin(), - itvertend = alcc.template darts_of_orbit<1>(itface).end(); - itvert != itvertend; ++itvert) - { - face.push_back(vertex_index[alcc.vertex_attribute(itvert)]); - } - cell_size += face.size() + 1; // +1 for face size - } - - cell_stream << cell_size << " " << faces.size(); - for(const auto& face : faces) { - cell_stream << " " << face.size(); - for(auto v : face) { - cell_stream << " " << v; - } - } - cell_stream << "\n"; - total_size += cell_size + 1; // +1 for cell size - - } else { - // Standard cell types write vertex connectivity directly - std::vector vertices; - - for(auto itvert = alcc.template one_dart_per_incident_cell<0, 3>(itvol).begin(), - itvertend = alcc.template one_dart_per_incident_cell<0, 3>(itvol).end(); - itvert != itvertend; ++itvert) - { - vertices.push_back(vertex_index[alcc.vertex_attribute(itvert)]); - } - - cell_stream << vertices.size(); - for(auto v : vertices) { - cell_stream << " " << v; - } - cell_stream << "\n"; - total_size += vertices.size() + 1; - } - } + nbcells=0; + std::size_t total_size=0; + std::ostringstream cell_stream, type_stream; + typename LCC::Dart_const_descriptor sd; // Write cells section - os << "CELLS " << nbcells << " " << total_size << "\n"; - os << cell_stream.str(); - os << "\n"; + for(typename LCC::template One_dart_per_cell_range<3>::const_iterator + itvol=alcc.template one_dart_per_cell<3>().begin(), + itvolend=alcc.template one_dart_per_cell<3>().end(); + itvol!=itvolend; ++itvol) + { + ++nbcells; + ++total_size; // for the number of vertices + VTK_Cell_Type cell_type=get_vtk_cell_type(alcc, itvol, sd); + type_stream<(cell_type)<(sd))]<<" " + <(sd))]<<" " + <(sd))]<(sd))]<<" " + <(sd))]<<" " + <(sd))]<<" " + <(sd))]<(sd))]<<" " + <(sd))]<<" "; + // Move to the up face + typename LCC::Dart_const_descriptor d2=alcc.template beta<2, 1, 1, 2>(sd); + cell_stream<(d2))]<<" " + <(d2))]<(sd); + } + typename LCC::Dart_const_descriptor d2=alcc.template beta<2, 1, 1, 2, 1>(sd); + // Darts associated with particles 4, 5, 6, 7 + for(unsigned int i = 0; i < 4; i++) + { + cell_stream<(d2); + } + cell_stream<> faces; + std::size_t cell_size=1; // Start with 1 for number of faces + ++total_size; // for the same reason + for(auto itface=alcc.template one_dart_per_incident_cell<2, 3, 2>(itvol).begin(), + itfaceend=alcc.template one_dart_per_incident_cell<2, 3, 2>(itvol).end(); + itface!=itfaceend; ++itface) + { + faces.push_back(std::vector()); + typename LCC::Dart_const_descriptor curdh=itface; + do + { + faces.back().push_back(index[alcc.vertex_attribute(curdh)]); + curdh=alcc.template beta<1>(curdh); + } + while(curdh!=itface); + cell_size+=faces.back().size()+1; // +1 for the number of vertices in the face + } + cell_stream<) { - os << "POINT_DATA " << nbpts << "\n"; - os << "SCALARS vertex_scalars " << gettype::name() << " 1\n"; - os << "LOOKUP_TABLE default\n"; - for(auto itv = alcc.vertex_attributes().begin(), itvend = alcc.vertex_attributes().end(); itv != itvend; ++itv) { - auto dart = alcc.template dart_of_attribute<0>(itv); - CGAL_assertion(dart != alcc.null_dart_descriptor); - os << ptval(alcc, dart) << "\n"; - } - } - - // Write cell scalars if cellval is not nullptr/pointer - if constexpr(!std::is_same_v && !std::is_pointer_v) { - os << "CELL_DATA " << nbcells << "\n"; - os << "SCALARS volume_scalars " << gettype::name() << " 1\n"; - os << "LOOKUP_TABLE default\n"; - for(auto itvol = alcc.template one_dart_per_cell<3>().begin(), - itvolend = alcc.template one_dart_per_cell<3>().end(); - itvol != itvolend; ++itvol) - { - os << cellval(alcc, itvol) << "\n"; - } - } + os<<"CELL_TYPES "< -inline bool read_VTK(LCC& alcc, const char* filename, VertexScalarReader vertex_reader, CellScalarReader cell_reader) { - CGAL_assertion(filename != nullptr); - std::ifstream file(filename); - if(!file.is_open()) { - std::cerr << "[ERROR] read_VTK: cannot open file " << filename << std::endl; - return false; - } - return internal::read_lcc_from_vtk_ascii(file, alcc, vertex_reader, cell_reader); -} - -template -inline bool write_VTK(const LCC& alcc, const char* filename, PointFunctor ptval, CellFunctor cellval) { - CGAL_assertion(filename != nullptr); - std::ofstream file(filename); - if(!file.is_open()) { - std::cerr << "[ERROR] write_VTK: cannot open file " << filename << std::endl; - return false; - } - return internal::write_lcc_to_vtk_ascii(file, alcc, ptval, cellval); -} - -// Vector-based versions (convenience wrappers) +//////////////////////////////////////////////////////////////////////////////////// template -inline bool read_VTK(LCC& alcc, +bool read_VTK(LCC& alcc, const char* filename, std::vector* vertex_scalars, - std::vector* volume_scalars) { - auto v_writer = [&](std::size_t i, auto val) { - if(vertex_scalars) { - if(vertex_scalars->size() <= i) - vertex_scalars->resize(i + 1); - (*vertex_scalars)[i] = static_cast(val); - } - }; - auto c_writer = [&](std::size_t i, auto val) { - if(volume_scalars) { - if(volume_scalars->size() <= i) - volume_scalars->resize(i + 1); - (*volume_scalars)[i] = static_cast(val); - } - }; - return read_VTK(alcc, filename, v_writer, c_writer); + std::vector* volume_scalars) +{ + CGAL_assertion(filename!=nullptr); + std::ifstream file(filename); + if(!file.is_open()) + { + std::cerr<<"[ERROR] read_VTK: cannot open file "< +bool read_VTK(LCC& alcc, + const char* filename) +{ return read_VTK + (alcc, filename, nullptr, nullptr); } + +template +bool read_VTK(LCC& alcc, + const char* filename, + std::vector* vertex_scalars) +{ return read_VTK + (alcc, filename, vertex_scalars, nullptr); } + +template +bool read_VTK(LCC& alcc, + const char* filename, + std::nullptr_t, + std::vector* volume_scalars) +{ return read_VTK + (alcc, filename, nullptr, volume_scalars); } +//////////////////////////////////////////////////////////////////////////////////// +template +inline bool write_VTK_with_fct(const LCC& alcc, const char* filename, + PointFunctor pointfct, CellFunctor cellfct) +{ + CGAL_assertion(filename!=nullptr); + std::ofstream file(filename); + if(!file.good()) + { + std::cerr<<"[ERROR] write_VTK: cannot open file "<:: + run(file, alcc, nbpts, pointfct); } + if(cellfct) + { internal::Write_cell_data:: + run(file, alcc, nbcells, cellfct); } + } + file.close(); + return true; +} +//////////////////////////////////////////////////////////////////////////////////// template -inline bool write_VTK(const LCC& alcc, - const char* filename, +bool write_VTK(const LCC& alcc, const char* filename, const std::vector* vertex_scalars, - const std::vector* volume_scalars) { - // Build index maps - std::unordered_map vertex_indices; - std::size_t idx = 0; - for(auto itv = alcc.vertex_attributes().begin(), itvend = alcc.vertex_attributes().end(); itv != itvend; ++itv) - vertex_indices[itv] = idx++; + const std::vector* volume_scalars) +{ + std::function vertexfct; + std::function cellfct; + if(vertex_scalars!=nullptr) + { + vertexfct=[&vertex_scalars](const LCC&, typename LCC::Dart_const_descriptor, + std::size_t i) -> VertexScalarType + { return (*vertex_scalars)[i]; }; + } - std::unordered_map volume_indices; - idx = 0; - for(auto itvol = alcc.template one_dart_per_cell<3>().begin(), itvolend = alcc.template one_dart_per_cell<3>().end(); - itvol != itvolend; ++itvol) - volume_indices[itvol] = idx++; + if(volume_scalars!=nullptr) + { + cellfct=[&volume_scalars](const LCC&, typename LCC::Dart_const_descriptor, + std::size_t i) -> VolumeScalarType + { return (*volume_scalars)[i]; }; + } - return write_VTK( - alcc, filename, - [vertex_scalars, &vertex_indices](const LCC& lcc, typename LCC::Dart_const_descriptor d) -> VertexScalarType { - if(vertex_scalars) - return (*vertex_scalars)[vertex_indices.at(lcc.template attribute<0>(d))]; - return VertexScalarType(); - }, - [volume_scalars, &volume_indices](const LCC& lcc, typename LCC::Dart_const_descriptor d) -> VolumeScalarType { - if(volume_scalars) - return (*volume_scalars)[volume_indices.at(d)]; - return VolumeScalarType(); - }); + return write_VTK_with_fct(alcc, filename, vertexfct, cellfct); } +template +bool write_VTK(const LCC& alcc, const char* filename) +{ + return write_VTK(alcc, filename, nullptr, nullptr); +} + +template +bool write_VTK(const LCC& alcc, const char* filename, + const std::vector* vertex_scalars) +{ + return write_VTK(alcc, filename, vertex_scalars, + nullptr); +} + +template +bool write_VTK(const LCC& alcc, const char* filename, + std::nullptr_t, + const std::vector* volume_scalars) +{ + return write_VTK(alcc, filename, nullptr, + volume_scalars); +} +//////////////////////////////////////////////////////////////////////////////////// + } // namespace IO } // namespace CGAL -#endif // CGAL_LCC_IO_VTK_H \ No newline at end of file +#endif // CGAL_LCC_IO_VTK_H