Merge pull request #2657 from afabri/Polyhedron_IO-improve_read_STL-GF

Parse headers of binary STL files starting with the keyword 'solid' correctly as binary STL
This commit is contained in:
Laurent Rineau 2017-12-19 16:29:44 +01:00
commit b045bc343d
9 changed files with 140 additions and 21 deletions

View File

@ -26,6 +26,7 @@
#include <map>
#include <iostream>
#include <string>
#include <cctype>
namespace CGAL{
@ -35,26 +36,97 @@ namespace CGAL{
std::vector< cpp11::array<int,3> >& facets,
bool verbose = false)
{
std::string s, solid("solid");
bool is_binary_file = false;
std::string s, solid("solid"), facet("facet");
std::map<cpp11::array<double,3>, int> pmap;
int index = 0;
cpp11::array<int,3> ijk;
cpp11::array<double,3> p;
char line[80];
for(int i=0;i < 80; i++){
boost::uint8_t c;
input.read(reinterpret_cast<char*>(&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<char*>(&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<char*>(&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<char*>(&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<char*>(&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<char*>(&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<char*>(&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<char*>(&c), sizeof(c));
}
is_binary_file = true;
}
done:
if(is_binary_file){
boost::uint32_t N32;
input.read(reinterpret_cast<char*>(&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){

View File

@ -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

View File

@ -1,3 +1,4 @@
#include <cassert>
#include <CGAL/IO/STL_reader.h>
#include <CGAL/array.h>
@ -5,8 +6,9 @@
#include <iostream>
#include <vector>
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<double,3> > 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;
}