STL文件规则

(1)共顶点规则
每一个三角面片必须与其相邻的每一个面片共两个顶点 ,即一个三角面片的顶点不能落在相邻的任何三角面片的边上;
(2)取向规则
单个面片法向量符合右手法(ccw)则且其法向量必须指向实体外面;
(3)充满规则
小三角面片必须布满三维模型的所有表面,不得有任何遗漏;
(4)取值规则
每个顶点的坐标值必须为非负 ,即 STL 文件的实体应该在坐标系的第一象限.

二进制STL文件

二进制STL文件用固定的字节数来给出三角面片的几何信息。
【80】文件起始的80个字节是文件头,用于存贮文件名
【4】紧接着用 4 个字节的整数来描述模型的三角面片个数(小端存储)
【50*n】后面逐个给出每个三角面片的几何信息。每个三角面片占用固定的50个字节(小端存储),依次是:
【12】3个4字节浮点数(角面片的法矢量)
【12】3个4字节浮点数(1个顶点的坐标)
【12】3个4字节浮点数(2个顶点的坐标)
【12】3个4字节浮点数(3个顶点的坐标)个
【2】三角面片的最后2个字节用来描述三角面片的属性信息。

ASCII文件格式

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

solid filename stl //自定义文件头
facet normal x y z //三角面片法向量的3个
outer loop
vertex x y z //三角面片第一个顶点坐标
vertex x y z //三角面片第二个顶点坐标
vertex x y z //三角面片第三个顶点坐标
endloop
endfacet //完成一个三角面片定义
……
endsolid filename stl ∥整个STL文件定义结束

注意

stl文件包含了一些错误信息

判断stl文件并读取

这里学习消化了MeshLab中的代码,MeshLab也使用了别的库,记不清是看的别的库还是MeshLab自己实现的代码了。

判断stl文件是二进制还是ASCII码

bool isSTLBinary(const char *filename)
{bool isBinary = false;//return valueFILE *fp = nullptr;int errorCode = fopen_s(&fp,filename, "r");if (errorCode==0)//成功打开文件{//确定文件实际大小fseek(fp, 0, SEEK_END);//将fp移动到文件尾部int fileSize = ftell(fp);//返回文档首部到fp位置大小(bytes)int facetNum;//计算标准stl二进制文件的大小fseek(fp, STL_LABEL_SIZE, SEEK_SET);//跳过文档开头的注释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];//如果文件过短,这里会有Bugfread(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);}return isBinary;
}

读取二进制stl文件

先定义一个表示stl文件的类。这个类其实可以不要,可以按照自己的实际需求把从stl文件中读取的数据组织起来。比如说可以只读取其中的顶点信息而忽略法向量信息,我这里没有读取属性信息。

class STLDocument
{
public:class STLPoint{public:double x;double y;double z;explicit STLPoint(){x = y = z = 0;}explicit STLPoint(float *p_Array){x = p_Array[0];y = p_Array[1];z = p_Array[2];}STLPoint& operator=(float *p_Array){x = p_Array[0];y = p_Array[1];z = p_Array[2];return *this;}};class STLFacet{public:STLPoint m_PointList[3];//三个顶点STLPoint m_Normal;//法向量};vector<STLPoint> m_VertexList;vector<STLFacet> m_FacetList;void clear();  //清除数据
};//end class 

读取二进制stl文件,并将数据存在上面定义的类里面。

const int STL_LABEL_SIZE = 80;
bool openBinary(const std::string &p_FileName, STLDocument &p_STLDocument)
{p_STLDocument.clear();FILE *fp;int numFacet;int error= fopen_s(&fp,p_FileName.c_str(), "rb");float normal[3];float point1[3];STLDocument::STLPoint stlPoint;STLDocument::STLFacet stlFacet;if (0==error)//成功打开文件{fseek(fp, STL_LABEL_SIZE, SEEK_SET);//跳过开头fread(&numFacet, sizeof(int), 1, fp);//读取facet的数目for (int facetIndex = 0; facetIndex < numFacet;++facetIndex){unsigned short attr; //用来储存属性,实际上把这个值丢弃了fread(normal, sizeof(float), 3, fp);//读取facet的法向量stlFacet.m_Normal = normal;for (int i = 0; i < 3;++i){fread(point1, sizeof(float), 3, fp);//读取vertexstlFacet.m_PointList[i] = point1;stlPoint = point1;p_STLDocument.m_VertexList.push_back(stlPoint);}fread(&attr, sizeof(unsigned short), 1, fp);//读取属性p_STLDocument.m_FacetList.push_back(stlFacet);}}fclose(fp);return true;
}

读取ASCII码的stl文件

bool openASCII(const std::string &p_FileName, STLDocument &p_STLDocument)
{p_STLDocument.clear();ifstream ifs;ifs.open(p_FileName, ifstream::in);if (ifs.is_open()){/*略去第一行*/string line;getline(ifs, line);/*读取facet*/int readCounter = 0;//记录每行读取成功的数据项int lineCounter = 0;while (!ifs.eof()){STLDocument::STLFacet facet;STLDocument::STLPoint point;/*读取facet normal ni nj nk*/getline(ifs, line);readCounter = sscanf(line.c_str(), "%*s %*s %lf %lf %lf\n", &facet.m_Normal.x, &facet.m_Normal.y, &facet.m_Normal.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", &point.x, &point.y, &point.z);p_STLDocument.m_VertexList.push_back(point);facet.m_PointList[i] = point;           }p_STLDocument.m_FacetList.push_back(facet);getline(ifs, line);//读取“endloop”getline(ifs, line);//读取"endfacet"lineCounter += 7;}// end while (ifs.eof())}//end if (ifs.is_open())else{cout << "Error Opening file!"<<endl;return false;}ifs.close();return true;
}

stl文件介绍及读取相关推荐

  1. 矢量数据shp七个文件介绍_读取矢量数据

    读写矢量数据 前面已经介绍了什么是矢量数据,简单地说就是用点.线.面表示离散的地理要素以及带有明显边界的地理要素,如城市. shapefile数据是一种通用的存储矢量数据的格式.但是shapefile ...

  2. Python如何读取STL文件,生成STL文件预览图(缩略图)

    如果你的项目也遇到了需要在后台将STL文件自动处理并生成预览图(缩略图)的需求,那么看本文就可以实现.如下图,我有一个狗头. 后台处理后生成的效果1: 后台处理后生成的效果2: 后台处理后生成的效果3 ...

  3. 旋转狗头:Python如何读取STL文件,生成STL文件预览图(缩略图)之进化,动态旋转Gif图

    之前的文章<Python如何读取STL文件,生成STL文件预览图(缩略图)>实现了将STL文件读取加载.绘制保存为某个角度下2D的png图片,作为预览图(缩略图).但是3D转2D,预览就丢 ...

  4. matlab读入stl文件,matlab读取stl文件

    设定 Facet Surface Smoothing (三角面片平滑)为 150 -> File (文件) -> Export (输出) -> 选择 .STL Mechanical ...

  5. php 读取 stl 文件,科学网—[转载]【源码】读取ASCII STL文件的STLReader - 刘春静的博文...

    读取包含顶点和面的ASCII STL文件,并将其构造为矩阵"顶点"."颜色"和"面".之后,使用各小模块在Matlab上建立模型. Read ...

  6. 打开stl文件_介绍一种修复、查看以及打印STL三维模型文件的工具

    slic3r是一种3D打印切片软件,这里可以帮助大家用于协助修复STL文件,并能帮助设定3D打印选项的小工具,下载后免安装直接可以用.官方网站点击左下角查看原文.我们也知道3D打印爱好者必不可少的也是 ...

  7. 如何读取STL文件?

    STL文件有两种文件格式,分别是二进制的stl和Ascii格式的stl.下面将针对这文件的两个格式,用C语言分别写出一段简单的示例代码. 一.读取二进制的STL文件 (1)二进制stl文件的结构 文件 ...

  8. MATLAB快速读取STL文件

    MATLAB快速读取STL文件 一.STL文件格式 binary格式 ascii格式stl 二.开源代码 安装方法 使用方法 三.快速读取 binary格式stl ascii格式stl 四.效果对比 ...

  9. Matlab读取并输出stl文件

    *#利用matlab读取stl文件后,将其中三角形片数据×2后,保存到另一个stl文件,利用3D软件打开观察图形是否变为两倍.那么应该怎么做呢? 首先了解一下stl文件 STL(Stereo lith ...

最新文章

  1. 2020年10月linux内核,Linux内核5.9于2020年10月12日发布
  2. URL加随机数的作用
  3. gdb 编译make: *** [all] 错误 2_Dev 日志 | Segmentation Fault 和 GCC 编译问题排查
  4. 【学习笔记】斜率优化
  5. 基于flink+clickhouse构建亿级电商全端用户画像平台训练营
  6. linux怎么创建扩展分区,Linux磁盘创建扩展分区
  7. 直接法光度误差导数推导
  8. 未能加载包studio package_Xrepo:一个现代化的跨平台 C/C++ 包管理器
  9. 《Head First设计模式》第三章笔记 装饰者模式
  10. Spark与MR的区别
  11. 兄弟姐妹们,祝大家圣诞节快乐!
  12. C-Free 5.0注册码
  13. CV+Deep Learning——网络架构Pytorch复现系列——classification(一:LeNet5,VGG,AlexNet,ResNet)
  14. 浙江大学深蓝质感简约答辩PPT模板
  15. angularJs - 弹窗
  16. Spring boot的定时任务调度
  17. Java I/O---概述
  18. ubuntu桌面之路-续三
  19. 用VISP+Opencv做相机到机械臂的标定
  20. (应用程序无法正常启动0xc0000142) 关于win10周年版更新后无法正常使用vc6.0问题的解决方法

热门文章

  1. 【51nod】---1278 相离的圆(二分排序)
  2. 练习:排序数组中查找元素的第一个和最后一个位置
  3. mac系统怎么制作装系统的u盘?苹果电脑u盘启动盘制作教程
  4. html5 制作书架展示 PHP,简单做出HTML5翻页效果文字特效
  5. 【Java8新特性 串行/并行流-Optional容器类-时间格式化线程安全等】
  6. Windows下维基百科中文语料库词向量训练
  7. python引流_Python初学者也可以秒懂的Python For循环思维
  8. 国外免费电子书资源下载
  9. 关于Linux mint更换中文字体后全局楷体修改办法
  10. 大风吹乱了我的头发,就像吹一朵蒲公英