1引言
STL(Stereo lithographic)文件格式是美国3D SYSTEMS公司提出的三维实体造型系统的一个接口标准,其接口格式规范。采用三角形面片离散地近似表示三维模型,目前已被工业界认为是快速成形(rapid prototypi ng)领域的标准描述文件格式。在逆向工程、有限元分析、医学成像系统、文物保护等方面有广泛的应用。
STL文件的最大特点也是其主要问题是,它是由一系列的三角形面片无序排列组合在一起的,没有反映三角形面片之间的拓扑关系。
2 STL文件格式的结构
STL文件是一种用许多空间小三角形面片逼近三维实体表面的数据模型,STL模型的数据通过给出组成三角形法向量的3个分量(用于确定三角面片的正反方向)及三角形的3个顶点坐标来实现,一个完整的STL文件记载了组成实体模型的所有三角形面片的法向量数据和顶点坐标数据信息。目前的STL文件格式包括二进制文件(BINARY)和文本文件(ASCII)两种。
2.1 STL的二进制格式
二进制STL文件用固定的字节数来给出三角面片的几何信息。文件起始的80个字节是文件头,用于存贮零件名;紧接着用4个字节的整数来描述模型的三角面片个数,后面逐个给出每个三角面片的几何信息。每个三角面片占用固定的50个字节,依次是3个4字节浮点数(角面片的法矢量),3个4字节浮点数(1个顶点的坐标),3个4字节浮点数(2个顶点的坐标),3个4字节浮点数(3个顶点的坐标),最后2个字节用来描述三角面片的属性信息。一个完整二进制STL文件的大小为三角形面片数乘以50再加上84个字节,总共1 34个字节。
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
2.2 TL的ASCII文件格式
ASCII码格式的STL文件逐行给出三角面片的几何信息,每一行以1个或2个关键字开头。在STL文件中的三角面片的信息单元facet是一个带矢量方向的三角面片,STL三维模型就是由一系列这样的三角面片构成。整个STL文件的首行给出了文件路径及文件名。在一个STL文件中,每一个facet由7行数据组成,facetnormal是三角面片指向实体外部的法矢量坐标,outer loop说明随后的3行数据分别是三角面片的3个顶点坐标,3顶点沿指向实体外部的法矢量方向逆时针排列。
ASCII格式的STL文件结构如下:
通过对STL两种文件格式的分析可知,二进制格式文件较小(通常是ASC¨码格式的1/5),节省文件存储空间,而ASCII码格式的文件可读性更强,更容易进行进一步的数据处理。
3三角片法矢量的计算,注意,点为v1 v2 v3逆时针排列
读取STL文件时,只需要读取STL文件中表示向量和三角形顶点的相应数据,不需要读文件中的其它信息。依次按逆时针方向读入各个三角形面片的3顶点坐标值。由于三角面片外法矢量可以通过右手螺旋法则由3顶点坐标值计算出来,因此可不对其进行存储,以节省存储空间。如果后续处理需用到法矢量,
可利用以下的外法矢量计算公式:
下面分别是 维基百科 对stl文件的论述,和我写的stl文件读取vc程序
Filename extension | .stl |
---|---|
Developed by | 3D Systems |
Type of format | Stereolithography |
STL (STereoLithography) is a file format native to the stereolithography CAD software created by 3D Systems. STL is also known as Standard Tessellation Language[1] This file format is supported by many other software packages; it is widely used for rapid prototyping and computer-aided manufacturing. STL files describe only the surface geometry of a three dimensional object without any representation of color, texture or other common CAD model attributes. The STL format specifies bothASCII and binary representations. Binary files are more common, since they are more compact.[2]
An STL file describes a raw unstructured triangulated surface by the unit normal and vertices (ordered by the right-hand rule) of the triangles using a three-dimensional Cartesian coordinate system.
Contents[hide]
|
An ASCII STL file begins with the line:
solid name
where name is an optional string (though if name is omitted there must still be a space after solid). The file continues with any number of triangles, each represented as follows:
facet normal ni nj nk outer loop vertex v1x v1y v1z vertex v2x v2y v2z vertex v3x v3y v3z endloop endfacet
where each n or v is a floating point number in sign-mantissa 'e'-sign-exponent format, e.g., "-2.648000e-002". The file concludes with:
endsolid name
The structure of the format suggests that other possibilities exist (e.g., facets with more than one 'loop', or loops with more than three vertices) but in practice, all facets are simple triangles.
White space (spaces, tabs, newlines) may be used anywhere in the file except within numbers or words. The spaces between 'facet' and 'normal' and between 'outer' and 'loop' are required.[2]
Because ASCII STL files can become very large, a binary version of STL exists. A binary STL file has an 80 character header (which is generally ignored – but which should never begin with 'solid' because that will lead most software to assume that this is an ASCII STL file). Following the header is a 4 byte unsigned integer indicating the number of triangular facets in the file. Following that is data describing each triangle in turn. The file simply ends after the last triangle.
Each triangle is described by twelve 32-bit-floating point numbers: three for the normal and then three for the X/Y/Z coordinate of each vertex – just as with the ASCII version of STL. After the twelve floats there is a two byte unsigned 'short' integer that is the 'attribute byte count' – in the standard format, this should be zero because most software does not understand anything else.[2]
Floating point numbers are represented as IEEE floating point numbers and the endianness is assumed to be little endian although this is not stated in documentation.
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
There are at least two variations on the binary STL format for adding color information:
The red/green/blue ordering within those two bytes is reversed in these two approaches – so while these formats could easily have been compatible the reversal of the order of the colors means that they are not – and worse still, a generic STL file reader cannot automatically distinguish between them. There is also no way to have facets be selectively transparent because there is no per-facet alpha value – although in the context of current rapid prototyping machinery, this is not important.
下面vc程序
class CSTL
{
private:
float *vx;
float *vy;
float *vz;
int *triaV1;
int *triaV2;
int *triaV3;
int m_TriaNum;
public:
CSTL();
~CSTL();
public:
bool SetStlInf(float *px,float *py,float *pz,
int *TriaNum1,int *TriaNum2,int *TriaNum3,int TriaTotalNum);
bool SaveStlBinary(char *pathname,char * filename);
bool SaveStlASCII(char *pathname,char * filename);
};
CSTL::CSTL()
{
}
CSTL::~CSTL()
{
}
bool CSTL::SetStlInf(float *px, float *py, float *pz,
int *TriaNum1, int *TriaNum2, int *TriaNum3, int TriaTotalNum)
{
bool success = false;
vx = px;
vy = py;
vz = pz;
triaV1 = TriaNum1;
triaV2 = TriaNum2;
triaV3 = TriaNum3;
m_TriaNum = TriaTotalNum;
success = true;
return success;
}
bool CSTL::SaveStlASCII(char *pathname,char * filename)
{
bool suc = true;
char *savename = new char[100];
sprintf(savename,"%s%s.ast",pathname,filename);
char *fileInf = new char[200];
sprintf(fileInf,"solid %s.ast %s",filename,"by master");
FILE *fp = fopen(savename,"w");
fprintf(fp,"%s\n",fileInf);
delete []savename;
for(int i=0;i<m_TriaNum;i++)
{
int id= triaV1[i];
float v1x = vx[id];
float v1y = vy[id];
float v1z = vz[id];
id= triaV2[i];
float v2x = vx[id];
float v2y = vy[id];
float v2z = vz[id];
id= triaV3[i];
float v3x = vx[id];
float v3y = vy[id];
float v3z = vz[id];
float nx = (v1y-v3y)*(v2z-v3z)-(v1z-v3z)*(v2y-v3y);
float ny = (v1z-v3z)*(v2x-v3x)-(v2z-v3z)*(v1x-v3x);
float nz = (v1x-v3x)*(v2y-v3y)-(v2x-v3x)*(v1y-v3y);
float nxyz = sqrt(nx*nx+ny*ny+nz*nz);
fprintf(fp,"facet normal %f %f %f\n",nx/nxyz,ny/nxyz,nz/nxyz);
fprintf(fp,"outer loop\n");
fprintf(fp,"vertex %f %f %f\n",v1x,v1y,v1z);
fprintf(fp,"vertex %f %f %f\n",v2x,v2y,v2z);
fprintf(fp,"vertex %f %f %f\n",v3x,v3y,v3z);
fprintf(fp,"endloop\n");
fprintf(fp,"endfacet\n");
}
sprintf(fileInf,"endsolid %s.ast %s",filename,"by master");
fprintf(fp,"%s\n",fileInf);
fclose(fp);
delete []fileInf;
return suc;
}
bool CSTL::SaveStlBinary(char *pathname,char * filename)
{
bool suc = true;
char *savename = new char[100];
sprintf(savename,"%s%s.stl",pathname,filename);
char *fileInf = new char[200];
sprintf(fileInf,"solid %s.stl %s",filename,"by master");
FILE *fp = fopen(savename,"wb");
delete []savename;
float* dat = new float[12];
fwrite(fileInf,sizeof(char),80,fp);
fwrite(&m_TriaNum,sizeof(int),1,fp);
for(int i=0;i<m_TriaNum;i++)
{
int id= triaV1[i];
float v1x = vx[id];
float v1y = vy[id];
float v1z = vz[id];
id= triaV2[i];
float v2x = vx[id];
float v2y = vy[id];
float v2z = vz[id];
id= triaV3[i];
float v3x = vx[id];
float v3y = vy[id];
float v3z = vz[id];
float nx = (v1y-v3y)*(v2z-v3z)-(v1z-v3z)*(v2y-v3y);
float ny = (v1z-v3z)*(v2x-v3x)-(v2z-v3z)*(v1x-v3x);
float nz = (v1x-v3x)*(v2y-v3y)-(v2x-v3x)*(v1y-v3y);
float nxyz = sqrt(nx*nx+ny*ny+nz*nz);
dat[0] = nx/nxyz;
dat[1] = ny/nxyz;
dat[2] = nz/nxyz;
dat[3] = v1x;
dat[4] = v1y;
dat[5] = v1z;
dat[6] = v2x;
dat[7] = v2y;
dat[8] = v2z;
dat[9] = v3x;
dat[10] = v3y;
dat[11] = v3z;
fwrite(dat,sizeof(float),12,fp);
fwrite("wl",sizeof(char),2,fp);
}
fclose(fp);
delete []dat;
delete []fileInf;
return suc;
}