ASCII码形式读取
STL文件格式如下,按照这个使用流读取即可
solid
facet normal -1 0 0
outer loop
vertex -5.0999999046325684 -5.0999999046325684 39.900001525878906
vertex -5.0999999046325684 -5.0999999046325684 49.818454742431641
vertex -5.0999999046325684 -5.0701136589050293 49.815811157226562
endloop
endfacet
// solid: 放在文件开头,表示固体
// facet normal: 三角面片的法向量
// vertex: 三角面片的三个顶点
代码如下, 这里是将法向量和顶点按照1+3的形式一起读入了vector中
#include <vector>
#include <cstdio>
#include <string>
#include <fstream>
struct Point
{
double x, y, z;
Point() : x(0.0), y(0.0), z(0.0) {}
Point(double x_, double y_) : x(x_), y(y_), z(0.0){}
Point(double x_, double y_, double z_) : x(x_), y(y_), z(z_){}
Point(const Point& p) : x(p.x), y(p.y), z(p.z){}
Point& operator=(const Point& p)
{
x = p.x;
y = p.y;
z = p.z;
return *this;
}
};
void readAsciiSTL(const std::string& filepath, std::vector<Point>& points, bool is_print)
{
if (is_print) printf("Reading binary file \" %s \"...\n", filepath.c_str());
std::ifstream input(filepath);
if (!input.is_open())
{
printf("\nError: %s, %d.\n", __FILE__, __LINE__);
printf("Can not open file:\"%s\" .\n", filepath.c_str());
exit(EXIT_FAILURE);
}
std::string s;
while (input >> s)
{
if (s == "vertex" || s == "normal")
{
double x, y, z;
input >> x >> y >> z;
points.push_back(Point(x, y, z));
}
}
}
二进制形式读取
二进制STL文件用固定的字节数来给出三角面片的几何信息。
文件起始的80个字节是文件头,用于存贮文件名;
紧接着用 4 个字节的整数来描述模型的三角面片个数,
后面逐个给出每个三角面片的几何信息。每个三角面片占用固定的50个字节,依次是:
3个4字节浮点数(角面片的法矢量)
3个4字节浮点数(1个顶点的坐标)
3个4字节浮点数(2个顶点的坐标)
3个4字节浮点数(3个顶点的坐标)个
三角面片的最后2个字节用来描述三角面片的属性信息。
一个完整二进制STL文件的大小为三角形面片数乘以 50再加上84个字节。
依照格式,读取函数如下
#include <string>
#include <vector>
#include <fstream>
#include <cstdio>
struct Point
{
double x, y, z;
Point() : x(0.0), y(0.0), z(0.0) {}
Point(double x_, double y_) : x(x_), y(y_), z(0.0){}
Point(double x_, double y_, double z_) : x(x_), y(y_), z(z_){}
Point(const Point& p) : x(p.x), y(p.y), z(p.z){}
Point& operator=(const Point& p)
{
x = p.x;
y = p.y;
z = p.z;
return *this;
}
};
void readBinarySTL(const std::string& filepath, std::vector<Point>& points, bool is_print)
{
if (is_print) printf("Reading %s...\n", filepath.c_str());
std::ifstream input(filepath, std::ios::binary);
if (!input.is_open())
{
printf("\nError: %s, %d\n", __FILE__, __LINE__);
printf("Cannot open file: %s\n", filepath.c_str());
exit(EXIT_FAILURE);
}
// 跳过开头80个二进制码
input.seekg(80);
// 读取三角面片数量 4 字节
uint32_t numTriangles;
input.read(reinterpret_cast<char*>(&numTriangles), sizeof(numTriangles));
// 读取每个三角面片
for (uint32_t i = 0; i < numTriangles; ++i)
{
// 读取法向量 12 字节
float nx, ny, nz;
input.read(reinterpret_cast<char*>(&nx), sizeof(nx));
input.read(reinterpret_cast<char*>(&ny), sizeof(ny));
input.read(reinterpret_cast<char*>(&nz), sizeof(nz));
points.push_back(Point(nx, ny, nz)); // 存入法向量
// 读取顶点 36 字节
for (int j = 0; j < 3; ++j)
{
float x, y, z;
input.read(reinterpret_cast<char*>(&x), sizeof(x));
input.read(reinterpret_cast<char*>(&y), sizeof(y));
input.read(reinterpret_cast<char*>(&z), sizeof(z));
points.push_back(Point(x, y, z));
}
// 跳过属性 2 字节
input.seekg(2, std::ios_base::cur);
}
input.close();
}