cgv
stl_reader.h File Reference

Provides functions to read stl files into user provided arrays. More...

#include <algorithm>
#include <exception>
#include <fstream>
#include <sstream>
#include <vector>

Go to the source code of this file.

Classes

class  stl_reader::StlMesh< TNumber, TIndex >
 convenience mesh class which makes accessing the stl data more easy More...
 

Macros

#define STL_READER_THROW(msg)   {std::stringstream ss; ss << msg; throw(std::runtime_error(ss.str()));}
 Throws an std::runtime_error with the given message.
 
#define STL_READER_COND_THROW(cond, msg)   if(cond){std::stringstream ss; ss << msg; throw(std::runtime_error(ss.str()));}
 Throws an std::runtime_error with the given message, if the given condition evaluates to true.
 

Functions

template<class TNumberContainer1 , class TNumberContainer2 , class TIndexContainer1 , class TIndexContainer2 >
bool stl_reader::ReadStlFile (const char *filename, TNumberContainer1 &coordsOut, TNumberContainer2 &normalsOut, TIndexContainer1 &trisOut, TIndexContainer2 &solidRangesOut)
 Reads an ASCII or binary stl file into several arrays. More...
 
template<class TNumberContainer1 , class TNumberContainer2 , class TIndexContainer1 , class TIndexContainer2 >
bool stl_reader::ReadStlFile_ASCII (const char *filename, TNumberContainer1 &coordsOut, TNumberContainer2 &normalsOut, TIndexContainer1 &trisOut, TIndexContainer2 &solidRangesOut)
 Reads an ASCII stl file into several arrays. More...
 
template<class TNumberContainer1 , class TNumberContainer2 , class TIndexContainer1 , class TIndexContainer2 >
bool stl_reader::ReadStlFile_BINARY (const char *filename, TNumberContainer1 &coordsOut, TNumberContainer2 &normalsOut, TIndexContainer1 &trisOut, TIndexContainer2 &solidRangesOut)
 Reads a binary stl file into several arrays. More...
 
bool stl_reader::StlFileHasASCIIFormat (const char *filename)
 Determines whether a stl file has ASCII format. More...
 

Detailed Description

Provides functions to read stl files into user provided arrays.

The central function of this file is ReadStlFile(...). It automatically recognizes whether an ASCII or a Binary file is to be read. It identifies matching corner coordinates of triangles with each other, so that the resulting coordinate array does not contain the same coordinate-triple multiple times.

The function operates on template container types. Those containers should have similar interfaces as std::vector and operate on float or double types (TNumberContainer) or on int or size_t types (TIndexContainer).

A conveniance class StlMesh is also provided, which makes accessing triangle corners and corresponding corner coordinates much more easy. It still provides raw access to the underlying data arrays.

Usage example 1 (using <tt>StlMesh</tt>):

try {
for(size_t itri = 0; itri < mesh.num_tris(); ++itri) {
std::cout << "coordinates of triangle " << itri << ": ";
for(size_t icorner = 0; icorner < 3; ++icorner) {
const float* c = mesh.tri_corner_coords (itri, icorner);
// or alternatively:
// float* c = mesh.vrt_coords (mesh.tri_corner_ind (itri, icorner));
std::cout << "(" << c[0] << ", " << c[1] << ", " << c[2] << ") ";
}
std::cout << std::endl;
float* n = mesh.tri_normal (itri);
std::cout << "normal of triangle " << itri << ": "
<< "(" << n[0] << ", " << n[1] << ", " << n[2] << ")\n";
}
}
catch (std::exception& e) {
std::cout << e.what() << std::endl;
}

Usage example 2 (using <tt>StlMesh</tt> and <em>solids</em>)

try {
for(size_t isolid = 0; isolid < mesh.num_solids(); ++isolid) {
std::cout << "solid " << isolid << std::endl;
for(size_t itri = mesh.solid_tris_begin(isolid);
itri < mesh.solid_tris_end(isolid); ++itri)
{
const float* n = mesh.tri_normal (itri);
std::cout << "normal of triangle " << itri << ": "
<< "(" << n[0] << ", " << n[1] << ", " << n[2] << ")\n";
}
}
}
catch (std::exception& e) {
std::cout << e.what() << std::endl;
}

Usage example 3 (using raw data arrays)

std::vector<float> coords, normals;
std::vector<unsigned int> tris, solids;
try {
stl_reader::ReadStlFile ("geometry.stl", coords, normals, tris, solids);
const size_t numTris = tris.size() / 3;
for(size_t itri = 0; itri < numTris; ++itri) {
std::cout << "coordinates of triangle " << itri << ": ";
for(size_t icorner = 0; icorner < 3; ++icorner) {
float* c = &coords[3 * tris [3 * itri + icorner]];
std::cout << "(" << c[0] << ", " << c[1] << ", " << c[2] << ") ";
}
std::cout << std::endl;
float* n = &normals [3 * itri];
std::cout << "normal of triangle " << itri << ": "
<< "(" << n[0] << ", " << n[1] << ", " << n[2] << ")\n";
}
}
catch (std::exception& e) {
std::cout << e.what() << std::endl;
}

If you do not want to use exceptions, you may define the macro STL_READER_NO_EXCEPTIONS before including 'stl_reader.h'. In that case, functions will return false if an error occurred.

Function Documentation

◆ ReadStlFile()

template<class TNumberContainer1 , class TNumberContainer2 , class TIndexContainer1 , class TIndexContainer2 >
bool stl_reader::ReadStlFile ( const char *  filename,
TNumberContainer1 &  coordsOut,
TNumberContainer2 &  normalsOut,
TIndexContainer1 &  trisOut,
TIndexContainer2 &  solidRangesOut 
)

Reads an ASCII or binary stl file into several arrays.

Reads a stl file and writes its coordinates, normals and triangle-corner-indices to the provided containers. It also fills a container solidRangesOut, which provides the triangle ranges for individual solids.

Double vertex entries are removed on the fly, so that triangle corners with equal coordinates are represented by a single coordinate entry in coordsOut.

Parameters
filename[in] The name of the file which shall be read
coordsOut[out] Coordinates are written to this container. On termination, it has size numVertices * 3. Each triple of entries forms a 3d coordinate. The type TNumberContainer should have the same interface as std::vector<float>.
normalsOut[out] Face normals are written to this container. On termination, it has size numFaces * 3. Each triple of entries forms a 3d normal. The type TNumberContainer should have the same interface as std::vector<float>.
trisOut[out] Triangle corner indices are written to this container. On termination, it has size numFaces * 3. Each triple of entries defines a triangle. The type TIndexContainer should have the same interface as std::vector<size_t>. Multiply corner indices from trisOut by 3 to obtain the index of the first coordinate of that corner in coordsOut.
solidRangesOut[out] On termination, it holds the ranges of triangle indices for each solid. It has the size numSolids + 1. Each entry can be interpreted as a end/begin triangle index for the previous/next solid. E.g., if there are 3 solids, the returned array would look like this:
{sol1Begin, sol1End/sol2Begin, sol2End/sol3Begin, sol3End}.
The type TIndexContainer should have the same interface as std::vector<size_t>.
Returns
true if the file was successfully read into the provided container.

◆ ReadStlFile_ASCII()

template<class TNumberContainer1 , class TNumberContainer2 , class TIndexContainer1 , class TIndexContainer2 >
bool stl_reader::ReadStlFile_ASCII ( const char *  filename,
TNumberContainer1 &  coordsOut,
TNumberContainer2 &  normalsOut,
TIndexContainer1 &  trisOut,
TIndexContainer2 &  solidRangesOut 
)

Reads an ASCII stl file into several arrays.

See also
ReadStlFile, ReadStlFile_ASCII

◆ ReadStlFile_BINARY()

template<class TNumberContainer1 , class TNumberContainer2 , class TIndexContainer1 , class TIndexContainer2 >
bool stl_reader::ReadStlFile_BINARY ( const char *  filename,
TNumberContainer1 &  coordsOut,
TNumberContainer2 &  normalsOut,
TIndexContainer1 &  trisOut,
TIndexContainer2 &  solidRangesOut 
)

Reads a binary stl file into several arrays.

Todo:
support systems with big endianess
See also
ReadStlFile, ReadStlFile_BINARY

◆ StlFileHasASCIIFormat()

bool stl_reader::StlFileHasASCIIFormat ( const char *  filename)
inline

Determines whether a stl file has ASCII format.

The underlying mechanism is simply checks whether the provided file starts with the keyword solid. This should work for many stl files, but may fail, of course.

stl_reader::StlMesh
convenience mesh class which makes accessing the stl data more easy
Definition: stl_reader.h:235
stl_reader::ReadStlFile
bool ReadStlFile(const char *filename, TNumberContainer1 &coordsOut, TNumberContainer2 &normalsOut, TIndexContainer1 &trisOut, TIndexContainer2 &solidRangesOut)
Reads an ASCII or binary stl file into several arrays.
Definition: stl_reader.h:514