三维图形数据格式 STL的 读取

在wiki上有对STL图形文件格式的详细描述。

http://en.wikipedia.org/wiki/STL_(file_format)

STL文件格式分为两种:ASCII字符格式,及二进制格式。

ASCII字符格式的格式如下:

开头一行:

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

二进制格式数据:

因为字符格式的STL文件比较大,占空间,因为有了二进制格式,且二进制的存储格式与ASCII的格式不同。二进制有80个字节作为文件头,一般都忽略掉,但开头不能使solid,不然就不能与ASCII格式相区分了。 另外,接下来4个字节是存放的三角片的个数,这个是ASCII格式所没有 的。

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


读取STL文件,首先,程序要区别读取的是那种格式的STL。然后根据格式,来读取数据。

先定义如下数据类型:

template <int D, class T = float>
class Vec {
private:
T v[D];
public:

...

};


typedef Vec<3,float> Vec3f;

用于存放点坐标数据和法向量数据,这里将点坐标和法向量都读到一个数组中。

[cpp]  view plain copy
  1. bool ReadSTLFile(const char *cfilename)  
  2. {  
  3.     if (cfilename == NULL)  
  4.     {  
  5.         return false;  
  6.     }  
  7.   
  8.     ifstream in(cfilename, ios::in);  
  9.     if (!in)  
  10.     {  
  11.         return false;  
  12.     }  
  13.     string headStr;  
  14.     getline(in, headStr, ' ');  
  15.   
  16.     in.close();  
  17.   
  18.   
  19.     if (headStr.empty())  
  20.     {  
  21.         return false;  
  22.     }  
  23.   
  24.     if (headStr[0] == 's')  
  25.     {  
  26.         ReadASCII(cfilename);  
  27.     }  
  28.     else  
  29.     {  
  30.         ReadBinary(cfilename);  
  31.     }  
  32.   
  33.     return true;  
  34. }  
[cpp]  view plain copy
  1. bool ReadASCII(const char *cfilename)  
  2. {  
  3.     int i=0,j=0,cnt=0 ,pCnt=4;  
  4.     char a[100];  
  5.     char str[100];  
  6.     double x=0,y=0,z=0;  
  7.     Vec3f tPoint;  
  8.     Vector<Vec3f> pointList; // todo: 可以预先计算出pointList的大小,节省空间  
  9.   
  10.     ifstream in;  
  11.     in.open(cfilename, ios::in);  
  12.     if (!in)   
  13.     {   
  14.         return false;   
  15.     }   
  16.     do   
  17.     {   
  18.         i=0;   
  19.         cnt=0;   
  20.         in.getline(a,100, '\n');   
  21.         while(a[i]!='\0')   
  22.         {   
  23.             if (!islower((int)a[i]) && !isupper((int)a[i]) && a[i]!=' ')   
  24.               break;   
  25.             cnt++;   
  26.             i++;   
  27.         }   
  28.           
  29.         while(a[cnt]!='\0')           
  30.         {   
  31.             str[j]=a[cnt];   
  32.             cnt++;   
  33.             j++;   
  34.         }   
  35.         str[j]='\0';   
  36.         j=0;   
  37.           
  38.         if (sscanf(str,"%lf%lf%lf",&x,&y,&z)==3)   
  39.         {   
  40.             tPoint.SetParam(x,y,z);  
  41.             pointList.push_back(tPoint);  
  42.         }  
  43.         pCnt++;  
  44.     }while(!in.eof());  
  45.   
  46.     return true;  
  47. }  
  48.   
  49. bool ReadBinary(const char *cfilename)  
  50. {  
  51.     char str[80];  
  52.   
  53.     ifstream in;  
  54.     //三角形数目  
  55.     int unTriangles(0);  
  56.     in.open(cfilename, ios::in);  
  57.   
  58.     if (!in)  
  59.     {  
  60.         return false;  
  61.     }  
  62.   
  63.     in.read(str, 80);  
  64.   
  65.     in >> unTriangles;  
  66.   
  67.     if(unTriangles==0)  
  68.     {     
  69.         return false;  
  70.     }  
  71.   
  72.     Vec3f tPoint;  
  73.     vector<Vec3f> pointList(unTriangles); // 预留足够的空间  
  74.     float x(0.f), y(0.f), z(0.f);  
  75.     char unusedByte;  
  76.     //Binary  
  77.     for(int i=0;i<(int)unTriangles;i++)  
  78.     {  
  79.         for (int pointIdx=0; pointIdx<4; pointIdx++)  
  80.         {  
  81.             in >> x >> y >> z;  
  82.             tPoint.SetParam(x, y, z);  
  83.             pointList.push_back(tPoint);  
  84.         }  
  85.   
  86.         in >> unusedByte >> unusedByte;  
  87.     }  
  88.   
  89.     in.close();  
  90.   
  91.     return true;  
  92. }  
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值