讀取STL文件模型


STL是CAD軟件中出來的一種3D模型文件格式,wiki已經解釋的很清楚了。

STL文件兩種格式,ASCII STLBinary STL

ASCII STL,每一個facet由7行數據組成,outer loop后面三個頂點的順序沿法線矢量逆時針排序,格式如下:

solid name // 文件名及文件路徑

facet normal ni nj nk          // 三角形法向量的三個分量
    outer loop
        vertex v1x v1y v1z     // 第一個頂點坐標
        vertex v2x v2y v2z     // 第二個頂點坐標
        vertex v3x v3y v3z     // 第三個頂點坐標
    endloop
endfacet                       // 完成一個三角形的定義

endsolid name                  // 整個文件結束

Binary STL,起始有80個字節文件頭用於存儲文件名,緊接4個字節表示三角形數量,而每個三角面片占用固定的50個字節,3個4字節浮點數(法線矢量),3個4字節浮點數(第一個頂點坐標),3個4字節浮點數(第二個頂點坐標),3個4字節浮點數(第三個頂點坐標),接着2個字節描述三角形基本屬性,那么一個完整的二進制STL文件的字節大小就是三角形面數乘50再加上84字節,格式如下:

UINT8[80] – Header             // 文件頭
UINT32 – Number of triangles   // 三角形數量

foreach triangle
REAL32[3] – Normal vector      // 法線矢量
REAL32[3] – Vertex 1           // 第一個頂點坐標
REAL32[3] – Vertex 2           // 第二個頂點坐標
REAL32[3] – Vertex 3           // 第三個頂點坐標
UINT16 – Attribute byte count  // 文件屬性
end

下面為代碼,

#include <fstream>
#include <string>
#include <vector>
bool ReadSTLFile(const char *cfilename)
{
    if (cfilename == NULL)
        return false;

    std::ifstream in(cfilename, std::ifstream::in);

    if (!in)
        return false;

    std::string headStr;
    getline(in, headStr, ' ');
    in.close();

    if (headStr.empty())
        return false;

    if (headStr[0] == 's')
    {
        ReadASCII(cfilename);
    }
    else
    {
        ReadBinary(cfilename);
    }
    return true;
}

bool ReadASCII(const char *cfilename)
{
    std::vector<float> coorX;
    std::vector<float> coorY;
    std::vector<float> coorZ;

    int i = 0, j = 0, cnt = 0, pCnt = 4;
    char a[100];
    char str[100];
    double x = 0, y = 0, z = 0;

    std::ifstream in(cfilename, std::ifstream::in);

    if (!in)
        return false;
    do
    {
        i = 0;
        cnt = 0;
        in.getline(a, 100, '\n');
        while (a[i] != '\0')
        {
            if (!islower((int)a[i]) && !isupper((int)a[i]) && a[i] != ' ')
                break;
            cnt++;
            i++;
        }

        while (a[cnt] != '\0')
        {
            str[j] = a[cnt];
            cnt++;
            j++;
        }
        str[j] = '\0';
        j = 0;

        if (sscanf(str, "%lf%lf%lf", &x, &y, &z) == 3)
        {
            coorX.push_back(x);
            coorY.push_back(y);
            coorZ.push_back(z);
        }
        pCnt++;
    } while (!in.eof());

    return true;
}

bool ReadBinary(const char *cfilename)
{
    std::vector<float> coorX;
    std::vector<float> coorY;
    std::vector<float> coorZ;

    char str[80];
    std::ifstream in(cfilename, std::ifstream::in | std::ifstream::binary);

    if (!in)
        return false;

    in.read(str, 80);

    //number of triangles  
    int triangles;
    in.read((char*)&triangles, sizeof(int));

    if (triangles == 0)
        return false;

    for (int i = 0; i < triangles; i++)
    {
        float coorXYZ[12];
        in.read((char*)coorXYZ, 12 * sizeof(float));

        for (int j = 1; j < 4; j++)
        {
            coorX.push_back(coorXYZ[j * 3]);
            coorY.push_back(coorXYZ[j * 3 + 1]);
            coorZ.push_back(coorXYZ[j * 3 + 2]);
        }

        in.read((char*)coorXYZ, 2);
    }

    in.close();

    return true;
}
ReadSTLFile

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM