34 #ifndef EGS_TRIANGLE_MESH_STL_PARSER_
35 #define EGS_TRIANGLE_MESH_STL_PARSER_
48 namespace stl_parser {
60 static inline void trim(std::string &s) {
62 s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](
unsigned char ch) {
63 return !std::isspace(ch);
66 s.erase(std::find_if(s.rbegin(), s.rend(), [](
unsigned char ch) {
67 return !std::isspace(ch);
73 const std::string &filename) {
77 std::istringstream line_stream(facet_line);
80 line_stream >> facet >> normal;
81 if (facet !=
"facet" || normal !=
"normal") {
82 throw std::runtime_error(
"failed to parse STL file `" + filename +
"`, expected `facet normal`");
87 line_stream >> n_x >> n_y >> n_z;
88 if (line_stream.fail()) {
89 throw std::runtime_error(
"failed to parse STL file `" + filename +
"`, normal parsing failed");
96 std::getline(input, line);
97 stl_parser::internal::trim(line);
98 if (line !=
"outer loop") {
99 throw std::runtime_error(
"failed to parse STL file `" + filename +
"`, expected `outer loop`");
102 std::getline(input, line);
103 stl_parser::internal::trim(line);
104 std::istringstream line_stream(line);
109 line_stream >> vertex >> x >> y >> z;
110 if (line_stream.fail() || vertex !=
"vertex") {
111 throw std::runtime_error(
"failed to parse STL file `" + filename +
"` vertex data");
115 tri.a = parse_vertex();
116 tri.b = parse_vertex();
117 tri.c = parse_vertex();
119 std::getline(input, line);
120 stl_parser::internal::trim(line);
121 if (line !=
"endloop") {
122 throw std::runtime_error(
"failed to parse STL file `" + filename +
"`, expected `endloop`");
124 std::getline(input, line);
125 stl_parser::internal::trim(line);
126 if (line !=
"endfacet") {
127 throw std::runtime_error(
"failed to parse STL file `" + filename +
"`, expected `endfacet`");
136 const std::string &filename) {
139 std::getline(input, line);
141 std::vector<EGS_TriangleMeshSpec::Triangle> raw_triangles;
143 while (std::getline(input, line)) {
144 stl_parser::internal::trim(line);
145 if (line.rfind(
"endsolid", 0) == 0) {
148 else if (line.rfind(
"facet", 0) == 0) {
149 const auto tri = parse_ascii_stl_triangle(line, input, filename);
150 raw_triangles.push_back(tri);
153 throw std::runtime_error(
"failed to parse STL file `" + filename +
"`, expected `facet` or `endsolid`");
163 const std::string &filename) {
165 std::uint32_t n_tri = 0;
166 input.read(
reinterpret_cast<char *
>(&n_tri), 4);
168 throw std::runtime_error(
"failed to parse the number of triangles");
171 throw std::runtime_error(std::string(
"STL file `") + filename
172 +
"` has 0 triangles");
187 std::vector<EGS_TriangleMeshSpec::Triangle> raw_triangles;
188 raw_triangles.resize(n_tri);
189 for (std::uint32_t i = 0; i < n_tri; i++) {
191 input.read(
reinterpret_cast<char *
>(&xf),
sizeof(float));
192 input.read(
reinterpret_cast<char *
>(&yf),
sizeof(float));
193 input.read(
reinterpret_cast<char *
>(&zf),
sizeof(float));
194 fill_egsvec(raw_triangles[i].n);
197 input.read(
reinterpret_cast<char *
>(&xf),
sizeof(
float));
198 input.read(
reinterpret_cast<char *
>(&yf),
sizeof(
float));
199 input.read(
reinterpret_cast<char *
>(&zf),
sizeof(
float));
200 fill_egsvec(raw_triangles[i].a);
202 input.read(
reinterpret_cast<char *
>(&xf),
sizeof(
float));
203 input.read(
reinterpret_cast<char *
>(&yf),
sizeof(
float));
204 input.read(
reinterpret_cast<char *
>(&zf),
sizeof(
float));
205 fill_egsvec(raw_triangles[i].b);
207 input.read(
reinterpret_cast<char *
>(&xf),
sizeof(
float));
208 input.read(
reinterpret_cast<char *
>(&yf),
sizeof(
float));
209 input.read(
reinterpret_cast<char *
>(&zf),
sizeof(
float));
210 fill_egsvec(raw_triangles[i].c);
213 std::uint16_t attr_bytes = 0;
214 input.read(
reinterpret_cast<char *
>(&attr_bytes), 2);
215 input.ignore(attr_bytes);
218 throw std::runtime_error(
"failed to parse STL file `" + filename +
"`");
230 std::ifstream stl_file(filename, std::ios::binary);
232 throw std::runtime_error(
"STL file `" + filename
233 +
"` does not exist or is not readable");
239 stl_file.read(&header[0], 5);
240 if (stl_file.fail()) {
241 throw std::runtime_error(
"failed to parse STL file `" + filename +
"`");
244 if (header ==
"solid") {
245 return stl_parser::internal::parse_ascii_stl_file(stl_file, filename);
252 return stl_parser::internal::parse_binary_stl_file(stl_file, filename);
A container for raw unstructured triangle surface mesh data.
A class representing 3D vectors.
void(* EGS_InfoFunction)(const char *,...)
Defines a function printf-like prototype for functions to be used to report info, warnings,...
Triangle surface mesh geometry: header.