C++读取STL文件

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();
    
}

### 如何在C++读取STL文件 要实现通过C++代码读取STL文件的功能,可以利用标准库或者第三方库来解析二进制或ASCII格式的STL文件。以下是具体方法以及代码示例。 #### 使用Boost.Iostreams处理二进制数据 对于二进制形式的STL文件,可以通过`std::ifstream`以二进制模式打开并逐字节读取文件头和三角形面片的数据结构[^2]。下面是一个简单的例子: ```cpp #include <iostream> #include <fstream> struct Triangle { float normal[3]; float vertices[9]; // Three points, each with three coordinates. }; void readBinarySTL(const std::string& filename) { std::ifstream ifs(filename, std::ios::binary); if (!ifs.is_open()) { throw std::runtime_error("Could not open file"); } char header[80]; ifs.read(header, 80); // Read the header (not used). uint32_t numTriangles; ifs.read(reinterpret_cast<char*>(&numTriangles), sizeof(numTriangles)); for (uint32_t i = 0; i < numTriangles && ifs.good(); ++i) { Triangle tri; ifs.read(reinterpret_cast<char*>(tri.normal), sizeof(float) * 3); ifs.read(reinterpret_cast<char*>(tri.vertices), sizeof(float) * 9); // Skip attribute byte count (usually two bytes). uint16_t attrByteCount; ifs.read(reinterpret_cast<char*>(&attrByteCount), sizeof(attrByteCount)); // Process triangle data here... } } ``` 上述代码展示了如何从二进制STL文件中提取几何信息[^3]。 #### ASCII STL 文件解析 如果目标是支持ASCII版本,则需按行扫描字符串直到遇到关键字`solid`, `facet`, 和`endloop`. 下列函数提供了一个基础框架用于加载这种类型的模型: ```cpp #include <sstream> #include <vector> using namespace std; // Helper structure representing a single vertex point in space. struct Vertex { double x,y,z; }; // Structure holding one triangular face definition within an .stl object. struct Face { vector<Vertex> verts; // Typically contains exactly three elements per instance. void addVertex(double xx,double yy,double zz){ this->verts.push_back({xx,yy,zz}); } }; bool parseAsciiStlFile(string path,vector<Face>& facesOut){ ifstream fin(path.c_str()); string lineStr; while(getline(fin,lineStr)){ stringstream ss(lineStr); string cmdWord; ss>>cmdWord; if(cmdWord=="vertex"){ double coordX,coordY,coordZ; ss >> coordX >> coordY >> coordZ ; if(facesOut.size()==0 || facesOut.back().verts.size()>=3 ){ Face newFce; newFce.addVertex(coordX,coordY,coordZ); facesOut.emplace_back(newFce); } else{ facesOut.back().addVertex(coordX,coordY,coordZ); } } } return true; } ``` 此段脚本解释了怎样迭代遍历整个文档寻找顶点坐标,并将其存储到适当的数据容器里以便后续操作[^4]. #### 结合外部库简化开发流程 考虑到手动编写复杂的文件解析逻辑可能耗时且容易出错,推荐采用成熟的开源项目如VTK(Visualization Toolkit),它提供了专门针对多种三维图形交换格式的支持功能模块,其中包括对STL文件的操作接口。安装完成后只需几行命令即可完成导入导出任务[^5]: ```cpp #include <vtkSmartPointer.h> #include <vtkPolyDataReader.h> #include <vtkSTLReader.h> #include <vtkRenderer.h> #include <vtkRenderWindowInteractor.h> int main(int argc,char **argv){ vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New(); reader->SetFileName("/path/to/input.stl"); // Continue setting up visualization pipeline as needed... return EXIT_SUCCESS; } ``` 以上介绍了几种常见的途径去达成用C++程序访问STL档案的目标。无论是自己动手还是借助现成工具包都能满足实际需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值