From 277b8cc74bc6ee8c8eb1ec41ac98256d32f3be16 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 25 Nov 2020 13:20:26 +0100 Subject: [PATCH] Fix OFF_reading --- .../CGAL/Linear_cell_complex_constructors.h | 2 +- .../orient_polygon_soup_test.cpp | 2 +- .../include/CGAL/IO/Polyhedron_scan_OFF.h | 6 +- .../examples/Stream_support/off_glue.cpp | 2 +- Stream_support/include/CGAL/IO/OFF.h | 28 +- .../include/CGAL/IO/OFF/File_header_OFF.h | 6 + .../CGAL/IO/OFF/File_header_OFF_impl.h | 14 + .../include/CGAL/IO/OFF/File_scanner_OFF.h | 831 ++++-------------- .../include/CGAL/IO/OFF/Scanner_OFF.h | 2 +- .../include/CGAL/IO/OFF/generic_copy_OFF.h | 2 +- .../CGAL/Triangulation_data_structure_2.h | 2 +- 11 files changed, 220 insertions(+), 677 deletions(-) diff --git a/Linear_cell_complex/include/CGAL/Linear_cell_complex_constructors.h b/Linear_cell_complex/include/CGAL/Linear_cell_complex_constructors.h index 227bfc2acc8..c8c0f8aa49d 100644 --- a/Linear_cell_complex/include/CGAL/Linear_cell_complex_constructors.h +++ b/Linear_cell_complex/include/CGAL/Linear_cell_complex_constructors.h @@ -214,7 +214,7 @@ namespace CGAL { for (std::size_t j=0; j:: operator()(HDS& target) Point p; file_scan_vertex( scanner, p); B.add_vertex( p); - if(scanner.has_colors()) + if(scanner.has_vcolors()) { Color c; file_scan_color(scanner, c); @@ -125,11 +125,9 @@ void Polyhedron_scan_OFF:: operator()(HDS& target) for(std::size_t j=0; j> ci) - { - has_fcolors = true; - std::istringstream iss2(col); - bool dum; - *fc_out++ = scanner.get_color_from_line(iss2, dum); - } - } - else if(has_fcolors) + if(scanner.has_fcolors()) { unsigned char r=0, g=0, b=0; scanner.scan_color(r,g,b); diff --git a/Stream_support/include/CGAL/IO/OFF/File_header_OFF.h b/Stream_support/include/CGAL/IO/OFF/File_header_OFF.h index 70e8e9a9f29..90430f40805 100644 --- a/Stream_support/include/CGAL/IO/OFF/File_header_OFF.h +++ b/Stream_support/include/CGAL/IO/OFF/File_header_OFF.h @@ -40,6 +40,10 @@ private: // Publicly accessible but not that well supported file informations. bool m_textures; // STOFF detected. bool m_colors; // COFF detected. +protected: + bool m_has_vcolors; + bool m_has_fcolors; +private: bool m_normals; // NOFF format stores also normals at vertices. // More privately used file informations to scan the file. @@ -81,6 +85,8 @@ public: std::size_t index_offset() const { return m_offset; } bool has_textures() const { return m_textures; } // STOFF detected. bool has_colors() const { return m_colors; } // COFF detected. + bool has_vcolors() const { return m_has_vcolors; } // COFF detected. + bool has_fcolors() const { return m_has_fcolors; } // COFF detected. bool has_normals() const { return m_normals;} // NOFF format. bool is_homogeneous() const { return m_tag4; } // 4OFF detected. diff --git a/Stream_support/include/CGAL/IO/OFF/File_header_OFF_impl.h b/Stream_support/include/CGAL/IO/OFF/File_header_OFF_impl.h index 42e15555e85..ab6b9ca0183 100644 --- a/Stream_support/include/CGAL/IO/OFF/File_header_OFF_impl.h +++ b/Stream_support/include/CGAL/IO/OFF/File_header_OFF_impl.h @@ -45,6 +45,8 @@ File_header_OFF::File_header_OFF( bool verbose) m_offset(0), m_textures(false), m_colors(false), + m_has_vcolors(false), + m_has_fcolors(false), m_normals(false), m_tag4(false), m_tagDim(false), @@ -62,6 +64,8 @@ File_header_OFF::File_header_OFF( m_offset(0), m_textures(false), m_colors(false), + m_has_vcolors(false), + m_has_fcolors(false), m_normals(false), m_tag4(false), m_tagDim(false), @@ -98,6 +102,8 @@ File_header_OFF::File_header_OFF( std::size_t v, std::size_t h, std::size_t f, m_offset(0), m_textures(false), m_colors(false), + m_has_vcolors(false), + m_has_fcolors(false), m_normals(false), m_tag4(false), m_tagDim(false), @@ -117,6 +123,8 @@ File_header_OFF::File_header_OFF( m_offset(0), m_textures(false), m_colors(false), + m_has_vcolors(false), + m_has_fcolors(false), m_normals(false), m_tag4(false), m_tagDim(false), @@ -135,6 +143,8 @@ File_header_OFF::File_header_OFF( m_offset(0), m_textures(false), m_colors(false), + m_has_vcolors(false), + m_has_fcolors(false), m_normals(false), m_tag4(false), m_tagDim(false), @@ -153,6 +163,8 @@ File_header_OFF::File_header_OFF( m_offset(0), m_textures(false), m_colors(false), + m_has_vcolors(false), + m_has_fcolors(false), m_normals(false), m_tag4(false), m_tagDim(false), @@ -174,6 +186,8 @@ File_header_OFF::File_header_OFF( m_offset(0), m_textures(false), m_colors(false), + m_has_vcolors(false), + m_has_fcolors(false), m_normals(false), m_tag4(false), m_tagDim(false), diff --git a/Stream_support/include/CGAL/IO/OFF/File_scanner_OFF.h b/Stream_support/include/CGAL/IO/OFF/File_scanner_OFF.h index 1c5755316eb..602536b40c1 100644 --- a/Stream_support/include/CGAL/IO/OFF/File_scanner_OFF.h +++ b/Stream_support/include/CGAL/IO/OFF/File_scanner_OFF.h @@ -39,215 +39,24 @@ class File_scanner_OFF int first_color_index; std::istream& m_in; bool normals_read; - bool eol_reached; void skip_comment() { m_in >> skip_comment_OFF; } public: File_scanner_OFF(std::istream& in, bool verbose = false) - : File_header_OFF(verbose), m_in(in), normals_read(false), eol_reached(false) + : File_header_OFF(verbose), m_in(in), normals_read(false) { in >> static_cast(*this); } File_scanner_OFF(std::istream& in, const File_header_OFF& header) : - File_header_OFF(header), m_in(in), normals_read(false), eol_reached(false) + File_header_OFF(header), m_in(in), normals_read(false) { } std::istream& in() { return m_in; } - // The scan_vertex() routine is provided for multiple - // coordinate types to support parameterized polytopes. - void scan_vertex(float& x, float& y, float& z) - { - if(binary()) - { - I_Binary_read_big_endian_float32(m_in, x); - I_Binary_read_big_endian_float32(m_in, y); - I_Binary_read_big_endian_float32(m_in, z); - if(is_homogeneous()) { - float w; - I_Binary_read_big_endian_float32(m_in, w); - x /= w; - y /= w; - z /= w; - } - } - else - { - skip_comment(); - if(!(m_in >> iformat(x) >> iformat(y) >> iformat(z))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(w))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(x) >> iformat(y) >> iformat(z))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(w); - if(!(m_in >> iformat(w))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(fx) >> iformat(fy) >> iformat(fz) >> iformat(fw))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(x) >> iformat(y) >> iformat(z))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(w))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<(entries.size()); color_entries -= 3 + H; // coordinates if(has_normals()){ first_color_index += 3 + H; @@ -300,12 +108,18 @@ public: if(has_textures()){ color_entries -= 2 + H; } - // now color_entries should be 1, 3, or 4 for the color + // now color_entries should be 0, 1, 3, or 4 for the color + if(color_entries > 0) + m_has_vcolors = true; + } - // todo: error checking - if(entries.size() < 3){ - // error: not enough for x y z + if(entries.size() < 3) + { + m_in.clear(std::ios::badbit); + if(verbose()) + std::cerr<<"error while reading vertex."<> iformat(x) >> iformat(y) >> iformat(z))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(w))) - { m_in.clear(std::ios::badbit); if(verbose()) std::cerr<<"error while reading vertex."<(dx); + y = static_cast(dy); + z = static_cast(dz); + w = static_cast(dw); + } + void scan_vertex(int& x, int& y, int& z, int& w) { - w = 1; - if(binary()) - { - float f; - I_Binary_read_big_endian_float32(m_in, f); - x = int(f); - I_Binary_read_big_endian_float32(m_in, f); - y = int(f); - I_Binary_read_big_endian_float32(m_in, f); - z = int(f); - if(is_homogeneous()) - { - I_Binary_read_big_endian_float32(m_in, f); - w = int(f); - } - } - else - { - skip_comment(); - double d; - if(!(m_in >> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading vertex."<(dx); + y = static_cast(dy); + z = static_cast(dz); + w = static_cast(dw); } - void scan_texture(float& x, float& y, float& w) + void scan_vertex(double& x, double& y, double& z) { - w = 1; - if(has_textures()) - { - if(binary()) - { - float fx, fy; - I_Binary_read_big_endian_float32(m_in, fx); - I_Binary_read_big_endian_float32(m_in, fy); - if(is_homogeneous()) - { - float fw; - I_Binary_read_big_endian_float32(m_in, fw); - x = fx / fw; - y = fy / fw; - } else - { - x = fx; - y = fy; - } - } - else - { - if(is_homogeneous()) - { - float fx, fy, fw; - if(!(m_in >> iformat(fx) >> iformat(fy) >> iformat(fw))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading texture."<> iformat(x) >> iformat(y))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading texture."<(dx); + y = static_cast(dy); + z = static_cast(dz); + } + + void scan_vertex(int& x, int& y, int& z) + { + double dx, dy, dz; + scan_vertex(dx, dy, dz); + x = static_cast(dx); + y = static_cast(dy); + z = static_cast(dz); + } + +// Textures void scan_texture(double& x, double& y, double& w) { w=1; @@ -477,262 +211,67 @@ public: { int first_texture_index = first_color_index + color_entries; x = entries[first_texture_index]; - x = entries[first_texture_index+1]; - - if(is_homogeneous()){ - x /= entries[first_texture_index+2]; - y /= entries[first_texture_index+2]; - } - + y = entries[first_texture_index + 1]; if(is_homogeneous()) { - float fx, fy, fw; - if(!(m_in >> iformat(fx) >> iformat(fy) >> iformat(fw))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading texture."<> iformat(x) >> iformat(y))) + if(entries.size() <= first_texture_index + 2) { m_in.clear(std::ios::badbit); if(verbose()) std::cerr<<"error while reading texture."<> iformat(x) >> iformat(y) >> iformat(z))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(w))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<(dx); + y = static_cast(dy); + w = static_cast(dw); } - void scan_normal(double& x, double& y, double& z) + void scan_texture(int& x, int& y, int& w) { - if(has_normals()) - { - normals_read = true; - if(binary()) - { - float fx, fy, fz; - I_Binary_read_big_endian_float32(m_in, fx); - I_Binary_read_big_endian_float32(m_in, fy); - I_Binary_read_big_endian_float32(m_in, fz); - if(is_homogeneous()) - { - float fw; - I_Binary_read_big_endian_float32(m_in, fw); - x = fx / fw; - y = fy / fw; - z = fz / fw; - } else - { - x = fx; - y = fy; - z = fz; - } - } - else - { - if(is_homogeneous()){ - if(entries.size() < 8){ - // not enough data - } - x = entries[4]/entries[7]; - y = entries[5]/entries[7]; - z = entries[6]/entries[7]; - }else{ - x = entries[3]; - y = entries[4]; - z = entries[5]; - } - - if(is_homogeneous()) - { - float fx, fy, fz, fw; - if(!(m_in >> iformat(fx) >> iformat(fy) >> iformat(fz) >> iformat(fw))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(x) >> iformat(y) >> iformat(z))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<(dx); + y = static_cast(dy); + w = static_cast(dw); } - void scan_normal(int& x, int& y, int& z) + void scan_texture(double& x, double& y) { - if(has_normals()) - { - normals_read = true; - if(binary()) - { - float fx, fy, fz; - I_Binary_read_big_endian_float32(m_in, fx); - I_Binary_read_big_endian_float32(m_in, fy); - I_Binary_read_big_endian_float32(m_in, fz); - if(is_homogeneous()) { - float fw; - I_Binary_read_big_endian_float32(m_in, fw); - x = int(fx / fw); - y = int(fy / fw); - z = int(fz / fw); - } else { - x = int(fx); - y = int(fy); - z = int(fz); - } - } - else - { - if(is_homogeneous()) - { - float fx, fy, fz, fw; - if(!(m_in >> iformat(fx) >> iformat(fy) >> iformat(fz) >> iformat(fw))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(x) >> iformat(y) >> iformat(z))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(w))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<(dx); + y = static_cast(dy); } + void scan_texture(int& x, int& y) + { + double dx, dy; + scan_texture(dx, dy); + x = static_cast(dx); + y = static_cast(dy); + } + + // Normals + void scan_normal(double& x, double& y, double& z, double& w) { w = 1; @@ -756,85 +295,77 @@ public: } else { - if(!(m_in >> iformat(x) >> iformat(y) >> iformat(z))) + int first_normal_index = (is_homogeneous())? 4:3; + if(entries.size() <= first_normal_index + 2) { m_in.clear(std::ios::badbit); if(verbose()) std::cerr<<"error while reading normal."<> iformat(w))) - { + { + if(entries.size() <= first_normal_index + 3){ m_in.clear(std::ios::badbit); if(verbose()) std::cerr<<"error while reading normal."<(dx); + y = static_cast(dy); + z = static_cast(dz); + w = static_cast(dw); + } + void scan_normal(int& x, int& y, int& z, int& w) { - w = 1; - if(has_normals()) - { - normals_read = true; - if(binary()) - { - float f; - I_Binary_read_big_endian_float32(m_in, f); - x = int(f); - I_Binary_read_big_endian_float32(m_in, f); - y = int(f); - I_Binary_read_big_endian_float32(m_in, f); - z = int(f); - if(is_homogeneous()) { - I_Binary_read_big_endian_float32(m_in, f); - w = int(f); - } - } - else - { - double d; - if(!(m_in >> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<> iformat(d))) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading normal."<(dx); + y = static_cast(dy); + z = static_cast(dz); + w = static_cast(dw); + } + + void scan_normal(double& x, double& y, double& z) + { + double dx, dy, dz, dw; + scan_normal(dx, dy, dz, dw); + x = dx / dw; + y = dy / dw; + z = dz / dw; + } + + void scan_normal(float& x, float& y, float& z) + { + double dx, dy, dz; + scan_normal(dx, dy, dz); + x = static_cast(dx); + y = static_cast(dy); + z = static_cast(dz); + } + + void scan_normal(int& x, int& y, int& z) + { + double dx, dy, dz; + scan_normal(dx, dy, dz); + x = static_cast(dx); + y = static_cast(dy); + z = static_cast(dz); } static const Color& get_indexed_color(int id) @@ -993,7 +524,7 @@ public: return color[id]; } - static CGAL::Color get_color_from_line(std::istream &is, bool& eol_reached) + static CGAL::Color get_color_from_line(std::istream &is) { std::string color_info; bool is_float = false; @@ -1054,7 +585,6 @@ public: position +=ss_pos; is.seekg(position); } - eol_reached = (ss_pos == -1); return color; } @@ -1073,8 +603,12 @@ public: } else { + CGAL::Color color; if(color_entries == 1){ - int i = entries[first_color_index]; // the index in the color map + color = get_indexed_color(static_cast(entries[first_color_index])); // the index in the color map + r = color.red(); + g = color.green(); + b = color.blue(); } double rd = entries[first_color_index]; double gd = entries[first_color_index + 1]; @@ -1082,19 +616,19 @@ public: if( (floor(rd) == rd) && (floor(gd) == gd) && (floor(bd) == bd)){ // we have to do with integers + r = static_cast(rd); + g = static_cast(gd); + b = static_cast(bd); }else{ // we have to do with floats + r = static_cast(rd*255); + g = static_cast(gd*255); + b = static_cast(bd*255); } if(color_entries == 4){ - double alphad = entries[first_color_index + 3]; + //double alphad = entries[first_color_index + 3]; // it seems that we ignore it. } - - - CGAL::Color color = get_color_from_line(m_in, eol_reached); - r = color.red(); - g = color.green(); - b = color.blue(); } } @@ -1112,11 +646,8 @@ public: I_Binary_read_big_endian_float32(m_in, f); } - if(has_colors()) // @fixme 'has_colors_read' ? + if(has_colors()) { - // It is not well stated in the Geomview manual - // how color is coded following a vertex. It is - // parsed similar to the optional color for facets. boost::int32_t k; I_Binary_read_big_endian_integer32(m_in, k); if(k<0 || k>4) @@ -1200,17 +731,37 @@ public: else { skip_comment(); - if(!(m_in >> size)) - { - m_in.clear(std::ios::badbit); - if(verbose()) - std::cerr<<"error while reading facet. Missing size."<> iformat(d)){ + entries.push_back(d); + } + size = static_cast(entries[0]); + if(has_colors()){ + // Compute how many entries are there for the color + first_color_index = static_cast(size + 1); + + color_entries = static_cast(entries.size()); + color_entries -= static_cast(size + 1); // coordinates + // now color_entries should be 0, 1, 3, or 4 for the color + if(color_entries > 0) + m_has_fcolors = true; } } } void scan_facet_vertex_index(std::size_t& index, + const std::size_t& current_entry, std::size_t current_facet) { if(binary()){ @@ -1220,13 +771,14 @@ public: } else { - if(!(m_in >> index)) + if(entries.size() <= current_entry ) { m_in.clear(std::ios::badbit); if(verbose()) std::cerr<<"error while reading facet. Missing index."<(entries[current_entry]); } if(m_in.fail()) @@ -1294,14 +846,7 @@ public: I_Binary_read_big_endian_float32(m_in, dummy); } } - else - { - m_in >> skip_until_EOL; - } } - - bool eol()const { return eol_reached; } - void set_eol(const bool b) {eol_reached = b; } }; template < class Point> inline diff --git a/Stream_support/include/CGAL/IO/OFF/Scanner_OFF.h b/Stream_support/include/CGAL/IO/OFF/Scanner_OFF.h index b6cd67707bb..56a359fa83b 100644 --- a/Stream_support/include/CGAL/IO/OFF/Scanner_OFF.h +++ b/Stream_support/include/CGAL/IO/OFF/Scanner_OFF.h @@ -167,7 +167,7 @@ private: // A huge value helps to detect a potential // error in the function scan_facet_vertex_index for (std::size_t i = 0; i < no; ++i) { - m_scan->scan_facet_vertex_index( index, m_cnt); + m_scan->scan_facet_vertex_index( index, i+1, m_cnt); m_indices.push_back( index); } m_scan->skip_to_next_facet( m_cnt); diff --git a/Stream_support/include/CGAL/IO/OFF/generic_copy_OFF.h b/Stream_support/include/CGAL/IO/OFF/generic_copy_OFF.h index b43378f80a9..799691de51a 100644 --- a/Stream_support/include/CGAL/IO/OFF/generic_copy_OFF.h +++ b/Stream_support/include/CGAL/IO/OFF/generic_copy_OFF.h @@ -77,7 +77,7 @@ generic_copy_OFF(File_scanner_OFF& scanner, for(std::size_t j=0; jset_vertex(j, vvh[index]); vvh[index]->set_face(fh); }