[matlab编程实践].cli文件二进制格式读取【3D打印切片文件】

文章目录

  • 零.cli文件简介
    • 0.0 cli文件说明文档
    • 0.1 下面是我们这使用的3D打印机的流程。
    • 0.2 cli文件格式
    • 0.3 cli文件结构
    • 0.4 几何数据部分详解
  • 一.matlab 程序实现

零.cli文件简介

0.0 cli文件说明文档

cli文件说明文档,网址:https://www.hmilch.net/downloads/cli_format.html

0.1 下面是我们这使用的3D打印机的流程。

CAD软件导出
切片软件
三维模型
STL文件
.cli文件
3D打印机加工软件

.cli文件是切片软件将STL文件完成切片后的切片文件,里面保存了每层的切片轮廓等几何信息。

0.2 cli文件格式

cli文件主要分为两种:
i)ASCII码版本,里面几何数据由ASCII码保存,可以直接用记事本打开查看,占内存大,少见。如下图,里面的信息很容易读。
[matlab编程实践].cli文件二进制格式读取【3D打印切片文件】_第1张图片
ii)二进制码版本,里面的几何数据由二进制码保存,可读性差,短小精悍,多见。如下图,几何数据部分都是乱码。
[matlab编程实践].cli文件二进制格式读取【3D打印切片文件】_第2张图片
本文是二进制文件读取。

0.3 cli文件结构

如上图可见,里面分为两部分:
i)头文件部分:这部分使用ASCII码编写。头文件部分以’‘HEADERSTART’‘开始,每条指令用"$$"开头,中间每条指令结束有一个换行符,以’‘HEADEREND’'结束,后面之间接几何数据部分的二进制码,没有换行符。
ii)几何数据部分:这部分使用二进制码编写,可以在网上下载二进制读取软件查看。
如下图,读出来是这样的,左边是二进制码,中间转成16进制,右边是ASC码。
[matlab编程实践].cli文件二进制格式读取【3D打印切片文件】_第3张图片

0.4 几何数据部分详解

几何部分数据格式:【指令+数据】
其中指令是两个字节十六位二进制数(unsigned integer)表示,数据有的是二字节十六位(unsigned int)有的是四字节三十二位(long int)。详见开头的说明文档。

我这里的几何数据部分主要是两个指令:
(这里面的二进制数据应该都是小字节序,两个字节颠倒顺序的)
(里面没有小数,都是整型,乘以头文件中的单位得到小数的坐标数据)

i)指令128:层高指令 格式【10000000 00000000 ZZZZZZZZ ZZZZZZZZ】
[matlab编程实践].cli文件二进制格式读取【3D打印切片文件】_第4张图片
10000000 00000000代表指令128,后面两字节ZZZZZZZZ ZZZZZZZZ是层高数据。
这个指令应该是换层指令。

ii)指令129:轮廓指令 格式【10000001 00000000 IDIDIDID IDIDIDID didididi didididi nnnnnnnn nnnnnnnn x1x1x1x1 y1y1y1y1 x2x2x2x2 y2y2y2y2 …】
前面10000001 00000000代表指令129 ;后面两字节的ID数据(我也不知道有啥用,一般是1);后面是两字节的方向数据,0:顺时针 1:逆时针 2:开线。再后面是这条轮廓线中的点的个数n,再后面是坐标数据。

iii)除了这两条之外,还另有四条指令,还有填充线的指令,用于规划打印路径,详见开头的说明文档。

一.matlab 程序实现

本人编程水平奇差,下面程序仅作参考。
这个程序会读取cli文件,将其中每层轮廓画图,并保存。
cli文件地址和保存文件地址请自行修改。

3.18更新
上一个版本的代码有些错误导致读取某些文件会画图出错
又重新改了代码
仍然会有错误,请读者包涵。

clear all%清除工作空间
%%
%文件读取部分,打开文件读取到data中
%||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
fid=fopen('长方体5-30-1_5.cli','rb');%打开文件,只读模式,二进制格式||
%||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

%找到头文件中第八行,存到lines中,里面包含层数信息用于后续提取
for i=1:8
    lines=fgets(fid);
end

frewind(fid);%文件指针回到开头
data=fread(fid,'uint16');%读取二进制文件内容,读取格式'uint16'是用小节字序表示的无符号整型二进制数
fclose(fid);%关闭文件

%%
%数据定义部分

pre=0.005;%坐标精度

i=0;%操作循环
j=1;%操作循环
z=0;%操作层数
n=0;%操作点的个数
k=0;%操作循环
t=0;%操作循环
%n_numb(z,n) 第z层第n条轮廓线中的点数
%X(z,i)、Y(z,i)代表第z层第i个轮廓点的x、y的坐标
data_num=0;%整个文件的数据数
data_headnum=0;%头文件部分的数据数
%n_sum初始化每层点数
%layers层数,从头文件中读取

%%
%前置处理部分
%寻找数据头的坐标
data_num=size(data);%data_num是整个文件的数据量(两个字节算一个数据)

while i==0%先找到第一个指令128,它代表几何数据部分的开始
    if (data(j)==128)
        i=1;
    end
    
    j=j+1;%j-1代表第一个128指令的字节数
end

data_headnum=j-2;%data_headnum代表头文件的数据量(两个字节算一个数据)

%下面找到头文件中的层数信并转换成数字格式存储到变量layers中
layers_txt=strcat(lines(12),lines(13),lines(14),lines(15));
layers=str2num(layers_txt);

%%
%数据读取部分
n_sum=zeros(1,layers);%初始化每层点数
i=data_headnum+1;

while (i<=data_num(1))%从几何部分第一个数据开始读取
    if data(i)==128%如果是指令128
        z=z+1;%那么层数加一
        k=0;
        
        if n~=0%在每层n_numb最后补一行0,方便后面画图
            n_numb(z-1,n)=0;
        end
        
        n=1;%每层的第几条轮廓线归1
        i=i+1;%补i
        
    else %如果是指令129
        n_numb(z,n)=data(i+3);%那么129指令后第三个数据代表这个轮廓线中含有的点个数
        n_sum(z)=n_sum(z)+n_numb(z,n);%用于统计每层中的点数
        
        for j=k+1:n_sum(z)%读取坐标
            X(z,j)=data(i+4+2*t)*pre;
            Y(z,j)=data(i+5+2*t)*pre;
            t=t+1;
        end
        
        k=n_sum(z);
        
        i=i+2*n_numb(z,n)+3;%补i
        t=0;
        
        n=n+1;%轮廓中点数上升
    end
    i=i+1;
    
end

%下面将坐标矩阵空余部分的0补成inf,防止画图的时候,0值显示在图上
m=max(n_sum);%寻找每层点数的最大值

for i=1:layers
    for j=n_sum(i)+1:m
        X(i,j)=inf;
        Y(i,j)=inf;
    end
end

%%
%画图部分,画每层的图并保存在文件夹pic中

col=1;%暂时不区分轮廓和填充

for z=1:layers
    t=0;
    j=1;
    k=0;
    u=1;
    %——————————————————————————————————————
    %画线
    while n_numb(z,j)~=0%当线段点数矩阵元素不为0时进入以下循环
        
        k=k+n_numb(z,j);%k是折线段结束的点数
        
        hold on;%保持一个图像窗口不关闭,画多条线段
        
        if col==1%如果是轮廓线,用蓝颜色画,如果是填充线,用红颜色画
            for n=u:k-1%通过循环完成一条折线的绘制
                 plot([X(z,n),X(z,n+1)],[Y(z,n),Y(z,n+1)],'b');
            end
        else 
            for n=u:k-1%通过循环完成一条折线的绘制
                 plot([X(z,n),X(z,n+1)],[Y(z,n),Y(z,n+1)],'r');
            end
        end
        hold off;%不保持一个图像窗口不关闭
        
        u=u+n_numb(z,j);%u是折线段开始的点数
        j=j+1;

    end
    axis equal;%坐标轴刻度相等
    %——————————————————————————————————————
    %命名及存储
% 图片地址及文件名,文件名格式:layers+层数
%|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    picname1='C:\Users\Layla\Desktop\read_file\pic\';%图片存储地址|||
%|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
    picname2='layers';%名字
    picname3=num2str(z);
    picname4='.jpg';%格式为jpg
    picname=strcat(picname1,picname2,picname3,picname4);
    
    saveas(gcf,picname);%保存文件,gcf是指当前图像的句柄
    
    fprintf('%d/%d\n',z,layers);%显示层数
    
    close(gcf);%关闭当前图像
end

你可能感兴趣的:(matlab)