将*.STL转换成顶点索引格式
将*.STL转换成顶点索引格式
*.stl的格式很简单,某一个片断如下:
solid ascii
facet normal 0.000000e+000 0.000000e+000 1.000000e+000
outer loop
vertex 4.104528e+002 6.994522e+002 0.000000e+000
vertex 3.895472e+002 6.994522e+002 0.000000e+000
vertex 4.309017e+002 6.951057e+002 0.000000e+000
endloop
endfacet
facet normal 0.000000e+000 0.000000e+000 1.000000e+000
outer loop
vertex 4.309017e+002 6.951057e+002 0.000000e+000
vertex 3.895472e+002 6.994522e+002 0.000000e+000
vertex 3.690983e+002 6.951057e+002 0.000000e+000
endloop
endfacet
endsolid
可以看出,每个面都是一个三角形,有三个顶点。相邻的面有重复的顶点。若不消除重复的顶点,索引格式实现起来很简单,只需把所有面的顶点取出来,然后分配面的索引即可。若需要消除重复的顶点,那么确定面的顶点索引将十分麻烦。因此,在次将不消除重复的顶点,并忽略面的法向量。。
分析过程分两步:
1)读取顶点数据
2)生成索引式
Point3DList m_PointsList;
POINT3D m_minPoint;
POINT3D m_maxPoint;
POINT3D m_size;
bool ReadSTL(const char* stlFileName)
{
FILE* pSTLFile = fopen(stlFileName, "rt");
if(NULL == pSTLFile)
return false;
m_PointsList.clear();
m_minPoint.x = m_minPoint.y = m_minPoint.z = 10000;
m_maxPoint.x = m_maxPoint.y = m_maxPoint.z = -10000;
char strBuffer[BUF_SIZ];
POINT3D pointTemp;
char strTemp[BUF_SIZ];
int nPtCount = 0;
//---------------------------
// read from stl file
//---------------------------
while(fgets(strBuffer, BUF_SIZ, pSTLFile) != NULL)
{
memset(strTemp, 0, BUF_SIZ);
int rlt = sscanf(strBuffer, "%s %lf %lf %lf",
strTemp, &pointTemp.x, &pointTemp.y, &pointTemp.z);
if(EOF != rlt)
{
if(0 == strcmp(strTemp, "vertex"))
{
// min
if(pointTemp.x < m_minPoint.x)
{
m_minPoint.x = pointTemp.x;
}
if(pointTemp.y < m_minPoint.y)
{
m_minPoint.y = pointTemp.y;
}
if(pointTemp.z < m_minPoint.z)
{
m_minPoint.z = pointTemp.z;
}
// max
if(pointTemp.x > m_maxPoint.x)
{
m_maxPoint.x = pointTemp.x;
}
if(pointTemp.y > m_maxPoint.y)
{
m_maxPoint.y = pointTemp.y;
}
if(pointTemp.z > m_maxPoint.z)
{
m_maxPoint.z = pointTemp.z;
}
nPtCount++;
m_PointsList.push_back(pointTemp);
if(nPtCount % 3 == 0)
m_PointsList.push_back(pointTemp);
}
else
{
continue;
}
}
}
fclose(pSTLFile);
// compute size
m_size.x = m_maxPoint.x - m_minPoint.x;
m_size.y = m_maxPoint.y - m_minPoint.y;
m_size.z = m_maxPoint.z - m_minPoint.z;
if(m_size.x < 1.000000E-10)
m_size.x = 1.000000E-10;
if(m_size.y < 1.000000E-10)
m_size.y = 1.000000E-10;
if(m_size.z < 1.000000E-10)
m_size.z = 1.000000E-10;
return true;
}
bool WritePhonDat(const char* dataFileName)
{
//-----------------------------------
// write phon data file
//-----------------------------------
FILE* pOut = fopen(dataFileName, "wt");
if(pOut == NULL)
return false;
char strTemp[BUF_SIZ];
// position
memset(strTemp, 0, BUF_SIZ);
_snprintf(strTemp, BUF_SIZ, " POSITION, %.6E, %.6E, %.6E/n",
m_minPoint.x, m_minPoint.y, m_minPoint.z);
fputs(strTemp, pOut);
// size
memset(strTemp, 0, BUF_SIZ);
_snprintf(strTemp, BUF_SIZ, "SIZE , %.6E, %.6E, %.6E/n",
m_size.x, m_size.y , m_size.z);
fputs(strTemp, pOut);
// vertex number
int nVerNum = m_PointsList.size();
memset(strTemp, 0, BUF_SIZ);
_snprintf(strTemp, BUF_SIZ, "%6d/n", nVerNum);
fputs(strTemp, pOut);
// vertex
Point3DList::iterator it = m_PointsList.begin();
Point3DList::iterator itEnd = m_PointsList.end();
for(; it != itEnd; ++it)
{
memset(strTemp, 0, BUF_SIZ);
_snprintf(strTemp, BUF_SIZ, "%.6E %.6E %.6E/n",
((*it).x - m_minPoint.x)/m_size.x,
((*it).y - m_minPoint.y)/m_size.y,
((*it).z - m_minPoint.z)/m_size.z);
fputs(strTemp, pOut);
}
// faces number
memset(strTemp, 0, BUF_SIZ);
_snprintf(strTemp, BUF_SIZ, "%6d/n", nVerNum/3);
fputs(strTemp, pOut);
// faces index
for(int i=1; i <= nVerNum; i=i+3)
{;
memset(strTemp, 0, BUF_SIZ);
_snprintf(strTemp, BUF_SIZ, "%6d %6d %6d/n", i, i+1, i+2t);
fputs(strTemp, pOut);
}
// end
fclose(pOut);
return true;
}