diff --git a/Polyhedron_IO/include/CGAL/IO/STL_reader.h b/Polyhedron_IO/include/CGAL/IO/STL_reader.h index 50bc2691f76..490e8ca3b08 100644 --- a/Polyhedron_IO/include/CGAL/IO/STL_reader.h +++ b/Polyhedron_IO/include/CGAL/IO/STL_reader.h @@ -26,6 +26,7 @@ #include #include #include +#include namespace CGAL{ @@ -35,26 +36,97 @@ namespace CGAL{ std::vector< cpp11::array >& facets, bool verbose = false) { - std::string s, solid("solid"); + bool is_binary_file = false; + + std::string s, solid("solid"), facet("facet"); std::map, int> pmap; int index = 0; cpp11::array ijk; cpp11::array p; char line[80]; - for(int i=0;i < 80; i++){ - boost::uint8_t c; - input.read(reinterpret_cast(&c), sizeof(c)); - line[i]=c; - if(i==5){ - s = std::string(line,5); - if(s == solid){ - break; - } - } - } + int i = 0, ni = 0; - if(s!= solid){ + boost::uint8_t c; + for(; i < 5; i++){ + input.read(reinterpret_cast(&c), sizeof(c)); + line[i]=c; + } + + s = std::string(line,5); + if(s == solid){ + // we found the keyword "solid" which is supposed to indicate the file is Ascii + // But it might still be binary, so we have to find out if it is followed + // by an (optional) name and then the keyword "facet" + // When we find "facet" we conclude that it is really Ascii + do { + input.read(reinterpret_cast(&c), sizeof(c)); + line[i++]=c; + }while(isspace(c) && ( i < 80)); + if(i==80){ + is_binary_file = true; + goto done; + } + // now c is not whitespace + ni = i-1; // here starts either the name or the keyword "facet" + do { + input.read(reinterpret_cast(&c), sizeof(c)); + line[i++]=c; + }while(! isspace(c) && ( i < 80)); + s = std::string(line+ni, (i-1) - ni); +# ifdef CGAL_DEBUG_BINARY_HEADER + std::cout << "|" << s << "|" << std::endl; +# endif + if(s == facet){ + goto done; + } else if(i == 80){ + // the entire header is a name + is_binary_file = true; + goto done; + } + + // we continue to read what comes after the name + + // now c is whitespace + do { + input.read(reinterpret_cast(&c), sizeof(c)); + line[i++]=c; + }while(isspace(c) && ( i < 80)); + if(i==80){ + is_binary_file = true; + goto done; + } + + // now c is not whitespace + ni = i-1; // here starts either "facet", or it is really binary + do { + input.read(reinterpret_cast(&c), sizeof(c)); + line[i++]=c; + }while(! isspace(c) && ( i < 80)); +# ifdef CGAL_DEBUG_BINARY_HEADER + s = std::string(line+ni, (i-1) - ni); + std::cout << "|" << s << "|" << std::endl; +# endif + if(s == facet){ + goto done; + } else { + for(; i < 80; i++){ + input.read(reinterpret_cast(&c), sizeof(c)); + } + is_binary_file = true; + goto done; + } + }else{ + // we read the other 75 characters of the header + for(; i < 80; i++){ + input.read(reinterpret_cast(&c), sizeof(c)); + } + is_binary_file = true; + } + + done: + + if(is_binary_file){ boost::uint32_t N32; input.read(reinterpret_cast(&N32), sizeof(N32)); unsigned int N = N32; @@ -96,14 +168,17 @@ namespace CGAL{ } return true; } else { - std::string facet("facet"), - outer("outer"), + + // It is an Ascii file but the first occurence of "facet" has already be parsed + bool first_facet = true; + std::string outer("outer"), loop("loop"), vertex("vertex"), endloop("endloop"), endsolid("endsolid"); - - while(input >> s){ + s = facet; + while(first_facet || (input >> s)){ + first_facet = false; if(s == endsolid){ //std::cerr << "found endsolid" << std::endl; } else if(s == facet){ diff --git a/Polyhedron_IO/test/Polyhedron_IO/data/ascii-tetrahedron.stl b/Polyhedron_IO/test/Polyhedron_IO/data/ascii-tetrahedron.stl new file mode 100644 index 00000000000..ef48cbaea36 --- /dev/null +++ b/Polyhedron_IO/test/Polyhedron_IO/data/ascii-tetrahedron.stl @@ -0,0 +1,31 @@ +solid cube_corner + facet normal 0.0 -1.0 0.0 + outer loop + vertex 0.0 0.0 0.0 + vertex 1.0 0.0 0.0 + vertex 0.0 0.0 1.0 + endloop + endfacet + facet normal 0.0 0.0 -1.0 + outer loop + vertex 0.0 0.0 0.0 + vertex 0.0 1.0 0.0 + vertex 1.0 0.0 0.0 + endloop + endfacet + facet normal -1.0 0.0 0.0 + outer loop + vertex 0.0 0.0 0.0 + vertex 0.0 0.0 1.0 + vertex 0.0 1.0 0.0 + endloop + endfacet + facet normal 0.577 0.577 0.577 + outer loop + vertex 1.0 0.0 0.0 + vertex 0.0 1.0 0.0 + vertex 0.0 0.0 1.0 + endloop + endfacet + endsolid + \ No newline at end of file diff --git a/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-nice-header.stl b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-nice-header.stl new file mode 100644 index 00000000000..6298d8d89b6 Binary files /dev/null and b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-nice-header.stl differ diff --git a/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-1.stl b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-1.stl new file mode 100644 index 00000000000..3ef58ac3e48 Binary files /dev/null and b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-1.stl differ diff --git a/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-2.stl b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-2.stl new file mode 100644 index 00000000000..2f2b3eb59ca Binary files /dev/null and b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-2.stl differ diff --git a/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-3.stl b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-3.stl new file mode 100644 index 00000000000..733843ff7c7 Binary files /dev/null and b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-3.stl differ diff --git a/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-4.stl b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-4.stl new file mode 100644 index 00000000000..49428f664e8 Binary files /dev/null and b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-4.stl differ diff --git a/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-5.stl b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-5.stl new file mode 100644 index 00000000000..d1dd7ed0bf4 Binary files /dev/null and b/Polyhedron_IO/test/Polyhedron_IO/data/binary-tetrahedron-non-standard-header-5.stl differ diff --git a/Polyhedron_IO/test/Polyhedron_IO/stl2off.cpp b/Polyhedron_IO/test/Polyhedron_IO/stl2off.cpp index 2c2c3dae2de..91a4cc1a51f 100644 --- a/Polyhedron_IO/test/Polyhedron_IO/stl2off.cpp +++ b/Polyhedron_IO/test/Polyhedron_IO/stl2off.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -5,8 +6,9 @@ #include #include -void read(const char* fname) +void read(const char* fname, std::size_t v, std::size_t f) { + std::cout << "Reading "<< fname << std::endl; std::ifstream input(fname, std::ios::in | std::ios::binary); std::vector< CGAL::cpp11::array > points; @@ -16,7 +18,10 @@ void read(const char* fname) points, faces, true); - + + assert(points.size() == v); + assert(faces.size() == f); + std::cout << "OFF version of file " << fname << std::endl; std::cout.precision(17); @@ -35,7 +40,15 @@ void read(const char* fname) int main() { - read("data/cube.stl"); - read("data/triangle.stl"); + read("data/cube.stl", 8, 12); + read("data/triangle.stl", 3, 1); + + + read("data/binary-tetrahedron-nice-header.stl", 4, 4); + read("data/binary-tetrahedron-non-standard-header-1.stl", 4, 4); + read("data/binary-tetrahedron-non-standard-header-2.stl", 4, 4); + read("data/binary-tetrahedron-non-standard-header-3.stl", 4, 4); + read("data/binary-tetrahedron-non-standard-header-4.stl", 4, 4); + read("data/binary-tetrahedron-non-standard-header-5.stl", 4, 4); return 0; }