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个字节是存放的三角片的个数。

UINT8[80] – Header
UINT32 – Number of trianglesforeach triangle
REAL32[3] – Normal vector
REAL32[3] – Vertex 1
REAL32[3] – Vertex 2
REAL32[3] – Vertex 3
UINT16 – Attribute byte count
end

读取文件之前需判断文件为哪种格式:

bool isSTLBinary(const char* fileName)
{bool isBinary = false;//return valueFILE *fp = fopen(fileName, "r");//int errorCode = fopen_s(&fp, fileName, "r");// #ifdef __unix// #define fopen_s(pFile,filename, "r") ((*(pFile))=fopen((fileName),  ("r")))==NULL// #endifif (fp)//成功打开文件{printf("%s isSTLBinary open success\n", fileName);//确定文件实际大小fseek(fp, 0, SEEK_END);//将fp移动到文件尾部int fileSize = ftell(fp);//返回文档首部到fp位置大小(bytes)int facetNum;//计算标准stl二进制文件的大小fseek(fp, 80, SEEK_SET);//跳过文档开头的注释size_t t = fread(&facetNum, sizeof(int), 1, fp);//读取facet的数目并保存在facetNum中int standardBinaryFileSize = 80 + sizeof(int) + facetNum * 50;//判断是否是标准stl文件if (fileSize == standardBinaryFileSize){isBinary = true;}//判断是否是非标准stl文件unsigned char tmpbuf[128];//如果文件过短,这里会有Bugt = fread(tmpbuf, sizeof(tmpbuf), 1, fp);//读取128个char大小的数据for (unsigned int i = 0;i<sizeof(tmpbuf);i++){//char类型取值范围是-128~127,如果是ASCII格式,应该全是charif (tmpbuf[i]>127){isBinary = true;break;}}fclose(fp);printf("t=%d\n", (int)t);}else{printf("%s isSTLBinary open file fail\n", fileName);}return isBinary;
}

之后再根据文件格式选择读取方法。

读取二进制文件:

void openBinaryFile(std::string fileName, std::vector<float>& positions, std::vector<float>& normals)
{FILE *fp = fopen(fileName.c_str(), "rb");int numFacet;//int error= fopen_s(&fp,fileName, "rb");float normal[3];float point1[3];if (fp)//成功打开文件{fseek(fp, 80, SEEK_SET);//跳过开头size_t t = fread(&numFacet, sizeof(int), 1, fp);//读取facet的数目for (int facetIndex = 0; facetIndex < numFacet;++facetIndex){unsigned short attr; //用来储存属性,实际上把这个值丢弃了t = fread(normal, sizeof(float), 3, fp);//读取facet的法向量for (int i = 0; i < 3;++i){t = fread(point1, sizeof(float), 3, fp);//读取vertexpositions.push_back(point1[0] / 1000);positions.push_back(point1[1] / 1000);positions.push_back(point1[2] / 1000);normals.push_back(point1[0] / 1000);normals.push_back(point1[1] / 1000);normals.push_back(point1[2] / 1000);//printf ("%f, %f %f", point1[0], point1[1], point1[2]);}t = fread(&attr, sizeof(unsigned short), 1, fp);//读取属性}printf("t=%d\n", (int)t);}else {printf("%s open fail\n", fileName.c_str());}fclose(fp);
}

读取ASCII文件:

void openASCIIFile(std::string fileName, std::vector<float>& positions, std::vector<float>& normals)
{std::ifstream ifs;ifs.open(fileName, std::ifstream::in);if (ifs.is_open()){/*略去第一行*/std::string line;getline(ifs, line);/*读取facet*/int readCounter = 0;//记录每行读取成功的数据项int lineCounter = 0;double x,y,z = 0;double pointX, pointY, pointZ = 0;while (!ifs.eof()){/*读取facet normal ni nj nk*/getline(ifs, line);readCounter = sscanf(line.c_str(), "%*s %*s %lf %lf %lf\n", &x, &y, &z);if (readCounter!=3){// we could be in the case of a multiple solid object, where after a endfaced instead of another facet we have to skip two lines://     endloop//   endfacet//endsolid     <- continue on ret==0 will skip this line//solid ascii  <- and this one.//   facet normal 0.000000e+000 7.700727e-001 -6.379562e-001lineCounter++;continue;}//end ifgetline(ifs, line);//读取outer loop
/*读取三个顶点坐标vertex v1x v1y v1z*/for (int i = 0; i < 3;i++){getline(ifs, line);readCounter=sscanf(line.c_str(),"%*s %lf %lf %lf", &pointX, &pointY, &pointZ);positions.push_back(pointX);positions.push_back(pointY);positions.push_back(pointZ);normals.push_back(pointX);normals.push_back(pointY);normals.push_back(pointZ);}getline(ifs, line);//读取“endloop”getline(ifs, line);//读取"endfacet"lineCounter += 7;}// end while (ifs.eof())}//end if (ifs.is_open())else{return;}ifs.close();
}

STL 类

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()
{}

设置STL信息

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;
}

保存STL ASCLL 格式文件

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;
}

保存STL 二进制格式文件

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;}

https://blog.csdn.net/lo_ve18/article/details/120566054?

https://blog.csdn.net/junpengxue/article/details/9951057?

读写三维数据.stl文件相关推荐

  1. 读取三维数据.stl文件

    STL文件格式有两种:ASCII字符格式,及二进制格式. ASCII字符格式的格式如下: solid name // 文件名是可选的字符串 facet normal ni nj nk outer lo ...

  2. Python数据分析之Pandas读写外部数据文件

    点击上方"Datawhale",选择"星标"公众号 第一时间获取价值内容 阅读目录 1 引言 2 文本文件(txt.csv) 2.1 读取数据 2.2 写入数据 ...

  3. python json数据的文件读写操作

    python json数据的文件操作 代码 read_write_json.py #!/usr/bin/env python # -*- encoding: utf-8 -*- "" ...

  4. MATLAB中文件的读写和数据的导入导出

    http://blog.163.com/tawney_daylily/blog/static/13614643620111117853933/ 在编写一个程序时,经常需要从外部读入数据,或者将程序运行 ...

  5. 2.1 基于文件读写图像数据

    基于文件读写图像数据,获取图像文件的内容信息 Image Processing Toolbox™ 使您能够读取和写入许多常见文件格式的图像文件,包括 BMP.GIF.JPEG.PNG 和 TIFF.该 ...

  6. C/C++快速读写磁盘数据的方法-块读取/异步/优化分析算法/内存文件映射的原理和使用

    快速读写磁盘数据的方法: 1.块读取:一下子将数据读取到内存的(无论是文本还是二进制),而不是一行行的读取. 2.异步的IO,创建多线程,或者使用重叠IO,IO复用,异步的事件回调通知机制(可以用事件 ...

  7. java流与文件——读写二进制数据(DataOutput + DataInput)

    [0]README 0.1) 本文描述转自 core java volume 2, 旨在理解 java流与文件--读写二进制数据(DataOutput + DataInput)的相关知识: 0.2) ...

  8. C语言之文件读写探究(四):fwrite、fread(一次读写一块数据(二进制操作))

    相关博文:C语言之文件读写探究(一):fopen.fclose(文件的打开和关闭) 相关博文:C语言之文件读写探究(二):fputc.fgetc.feof(一次读写一个字符(文本操作)) 相关博文:C ...

  9. python处理多个excel数据_python 数据分析基础 day8-pandas读写多个excel文件

    今天是读<python数据分析基础>的第8天,今天的读书笔记的内容为利用pandas读写多个excel文件,当中涉及到读写excel文件的多个工作表. 大致原理如下: glob.glob( ...

  10. linux 打开三维stl文件,三维stl文件查看工具下载

    STL Viewer是一款简单实用的三维stl文件查看软件,用户可以STL Viewer更好地读取SketchUp.3ds Max.AutoCAD, SolidWorks导出的文件,软件支持多种三维模 ...

最新文章

  1. spark streaming 消费 kafka入门采坑解决过程
  2. 基于Python的开源人脸识别库:离线识别率高达99.38%
  3. 数学中的向量乘积和矩阵乘积总结
  4. jQuery缓存数据——仿Map
  5. pkill mysql_每天一个linux命令:kill命令
  6. 【转载】IPPROTO_RAW IPPROTO_IP
  7. 基于php校园失物招领,校园失物招领系统设计
  8. 将linux用在开发环境中
  9. OSChina 周三乱弹 —— 万众期待的拉黑功能
  10. exe文件打不开应该怎么办?
  11. 扩散模型 (Diffusion Model) 简要介绍与源码分析
  12. 五边形镶嵌计算机程序,如何看待美国数学家发现可无缝密铺平面的五边形?.doc...
  13. 重装系统(U盘篇+U盘复原)——保姆级教学
  14. 微信小程序设置单个页面自定义头部为背景图
  15. matlab中rand函数
  16. cdh5.9运行mapreduce uber任务报java.lang.RuntimeException: native snappy library not available错误
  17. Hashtable、HashMap 与 HashTable区别、HashMap、Hashtable和TreeMap、 LinkedHashMap
  18. java计算器课程报告_java计算器课程设计报告
  19. 如何搭建一个个人博客,这么写纯粹是为了通过shen he
  20. 计算机控制继电器电源,最疯狂DIY 用数千继电器自制8位电脑!

热门文章

  1. arm-linux-objdump -D -m arm led_elf led.dis 是什么意思?
  2. Win10开机任务栏卡死
  3. Android 9 Audio系统笔记:AudioFlinger音频流处理流程
  4. 免费智能机器人聊天API
  5. matlab 进行时域分析实验报告,控制系统时域分析实验报告.doc
  6. 计算机的硬盘有几个区,电脑固态硬盘需要分区吗 分几个区比较好?
  7. ora-12555解决方案
  8. 通过 ANE(Adobe Native Extension) 启动Andriod服务 推送消息(三)
  9. 缺失值填充的几种方法
  10. 分享一个去广告的浏览器插件