# STL文件及其读取

1引言

STL(Stereo lithographic)文件格式是美国3D SYSTEMS公司提出的三维实体造型系统的一个接口标准，其接口格式规范。采用三角形面片离散地近似表示三维模型，目前已被工业界认为是快速成形(rapid prototypi ng)领域的标准描述文件格式。在逆向工程、有限元分析、医学成像系统、文物保护等方面有广泛的应用。

STL文件的最大特点也是其主要问题是，它是由一系列的三角形面片无序排列组合在一起的，没有反映三角形面片之间的拓扑关系。

2 STL文件格式的结构

STL文件是一种用许多空间小三角形面片逼近三维实体表面的数据模型，STL模型的数据通过给出组成三角形法向量的3个分量(用于确定三角面片的正反方向)及三角形的3个顶点坐标来实现，一个完整的STL文件记载了组成实体模型的所有三角形面片的法向量数据和顶点坐标数据信息。目前的STL文件格式包括二进制文件(BINARY)和文本文件(ASCII)两种。

2.1 STL的二进制格式

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 STL的ASCII文件格式

ASCII码格式的STL文件逐行给出三角面片的几何信息，每一行以1个或2个关键字开头。在STL文件中的三角面片的信息单元facet是一个带矢量方向的三角面片，STL三维模型就是由一系列这样的三角面片构成。整个STL文件的首行给出了文件路径及文件名。在一个STL文件中，每一个facet由7行数据组成，facetnormal是三角面片指向实体外部的法矢量坐标，outer loop说明随后的3行数据分别是三角面片的3个顶点坐标，3顶点沿指向实体外部的法矢量方向逆时针排列

ASCII格式的STL文件结构如下：

3三角片法矢量的计算，注意，点为v1 v2 v3逆时针排列

# STL (file format)        http://en.wikipedia.org/wiki/STL_file

(Redirected from  STL file)
Filename extension .stl 3D Systems 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 theright-hand rule) of the triangles using a three-dimensional Cartesian coordinate system.

[ hide]

## ASCII STL

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 nkouter loopvertex v1x v1y v1zvertex v2x v2y v2zvertex v3x v3y v3zendloopendfacet

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]

## Binary STL

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 belittle endian although this is not stated in documentation.

UINT8[80] – HeaderUINT32 – Number of trianglesforeach triangleREAL32[3] – Normal vectorREAL32[3] – Vertex 1REAL32[3] – Vertex 2REAL32[3] – Vertex 3UINT16 – Attribute byte countend

## Color in binary STL

There are at least two variations on the binary STL format for adding color information:

• The VisCAM and SolidView software packages use the two 'attribute byte count' bytes at the end of every triangle to store a 15 bitRGB color:
• bit 0 to 4 are the intensity level for blue (0 to 31)
• bits 5 to 9 are the intensity level for green (0 to 31)
• bits 10 to 14 are the intensity level for red (0 to 31)
• bit 15 is 1 if the color is valid
• bit 15 is 0 if the color is not valid (as with normal STL files)
• The Materialise Magics software does things a little differently. It uses the 80 byte header at the top of the file to represent the overall color of the entire part. If color is used, then somewhere in the header should be theASCII string "COLOR=" followed by four bytes representing red, green, blue andalpha channel (transparency) in the range 0–255. This is the color of the entire object unless overridden at each facet. Magics also recognizes a material description; a more detailed surface characteristic. Just after "COLOR=RGBA" specification should be another ASCII string ",MATERIAL=" followed by three colors (3 × 4 bytes): first is a color ofdiffuse reflection, second is a color ofspecular highlight, and third is an ambient light. Material settings are preferred over color. The per-facet color is represented in the two 'attribute byte count' bytes as follows:
• bit 0 to 4 are the intensity level for red (0 to 31)
• bits 5 to 9 are the intensity level for green (0 to 31)
• bits 10 to 14 are the intensity level for blue (0 to 31)
• bit 15 is 0 if this facet has its own unique color
• bit 15 is 1 if the per-object color is to be used

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.

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;

}

10-06

04-28 395
07-19 6166
09-02 111
07-27 1万+
05-25
03-05
09-05
12-15
09-02
10-14
05-18
05-31
12-17
01-11 8万+
05-28
01-29
05-31
07-28