3D打印CLI文件格式的读取
CLI
英文全称:COMMON LAYER INTERFACE
中文名称:通用层接口。
推荐从官方网址看一下其完整的内容:
(https://www.hmilch.net/downloads/cli_format.html)
简介
通用层接口 (CLI) 是一种通用格式,用于将几何数据输入到基于层制造技术 (LMT) 的制造系统模型。适用于树脂的逐层光固化、粉末的烧结或粘合、片材的切割、熔融材料的固化以及任何其他逐层构建模型的系统。
目的
做有关3D打印相关的项目,想从基础的切偏数据(cli文件)入手,但是电脑上没有软件能打开cli文件(打开之后数据部分会乱码)。所以搜集一些资源,希望从cli文件中获取切边的数据信息。便于后面的学习。(新手学习,前后用了三天,涉及到某些知识比如文件读取等一些问题都是现学现用,可能存在一些问题或者更简单办法,希望各位大佬能及时指出,共同进步。)
内容
1.格式的解读,主要是二进制文件的解读
2.python源码
3.Java源码
格式
有二进制数据格式与ASCII数据格式,本文主要是介绍二进制格式,ASCII格式给出官网的例子。两种格式的异如下:
相同点:二者头文件是相同的。
不同点:ASCII格式有几何信息开始标志,二进制没有开始标志,头信息结束之后直接就是数据。
1.ASCII数据格式
下面是官网给的例子
$$HEADERSTART
// This is a example for the use of the Layer Format //
$$ASCII
$$UNITS/1 // all coordinates are given in mm //
// $$UNITS/0.01 all coordinates are given in units 0.01 mm //
$$DATE/070493 // 7. April 1993 //
$$LAYERS/100 // 100 layers //
$$HEADEREND
$$GEOMETRYSTART // start of GEOMETRY-section//
$$LAYER/5.5 // Layer at height z = 5.5 mm//
$$POLYLINE/0,0,5,1.00,2.02,3.30,3.42,5.23,5.01,1.57,5.6,1.00,2.02
$$HATCHES/0,2,10.2,10.4,12.34,12.5,8.8,9.3,15.7,13.2
$$POLYLINE/0,1,10,1.2,4.01,...........
..
..
$$LAYER/5.6
$$POLYLINE/0,0,200,10.23,12.34,..........................
..........
..
..
$$LAYER/15.5
$$POLYLINE/0,0,200,13.23,12.34,..........................
..........
..
..
$$GEOMETRYEND
2.二进制数据格式
给一个我已经读出来的例子,例子中是一个简单的立方体,编号0.01.cli
其中的换行是我人为换的,并不是开始就是这样。
代码
python
此代码是我从该网站得来的,非常感谢宝哥的开源。python源码
但是由于他的代码是一行显示的,后面我经过排版,修复其中几个小问题才能跑起来,不过也存在一个问题。直接运行报错,代码为:
byt_int, = struct.unpack("h", byts)
报错原因是
struct.error: unpack requires a buffer of 2 bytes
但是在报错地方打上断点,程序就能运行了,并且能准确读出信息,由于我对python代码不是很熟悉,简单搜一下没有解决这个问题,就暂时先搁置了,如果有大佬知道还望不吝赐教。下面给出具体代码。
import struct
class Que: # 定义一个队列的类
def __init__(self):
self.L = []
def creat_que(self, num): # 创建队列
for i in range(0, num):
self.L.append(str(b'x')) #
return self.L
def push(self, item): # 在末尾增加一个,开头删除一个,实现栈操作
self.L.append(item)
if self.L.__len__() > 11:
self.L.pop(0)
return self.L
def str_head(self):
st = [item.replace("b'", '') # 从链表L中将b'删去
for item in self.L]
st = [item.replace("'", '') # 从链表L中将'删去
for item in st]
st = ''.join(st) # 连接字符串
return st # 返回一个字符串
def b2int(self): # 将读取到的二进制字节转化为 unsign int (2个字节)
un_int, = struct.unpack("h", self.L[0]) # h在python中是整型
return un_int
que_headerend = Que() # 实例化一个对象来处理$$HEADEREND
que_headerend.creat_que(11) # 创建一个包含11个元素的队列,用于判断是不是头部信息结束
que_layer = Que() # 实例化一个对象来
que_layer.creat_que(2) # 队列,用于寻找128/129
class Structure:
def __init__(self, f_dir, f_w): # CI,id,dir,n,p1x,p1y,... pnx,pny
self.UNIT = 0 # 单位
self.LAYERS = 0 # 多少层
self.f = f_dir # 二进制文件???
self.f_ascii = f_w # 输出文件???
self.head = {}
self.CI_start = 0 # 128/129???
self.layer_thick = 0 # 层厚
self.CI_layer = 0 # 128/129???
self.id = 0 # 标识
self.dir = 0 # 顺时针还是逆时针???
self.n = 0 # 点的个数
self.pn = [] # 坐标
def rep(self, byts): # 格式替换
s = str(byts).replace("b", '')
s = s.replace("'", '')
return s
def get_head(self): # 获取文件头,返回一个字典
f = self.f
byts = ' '
d_Ls = []
L = []
while byts: # 开始循环读取二进制数据
byts = f.read(1) #头文件一次读一个字节
que_headerend.push(str(byts)) # 末尾增加一个刚读到的字符,删去一个前面的字符
s = que_headerend.str_head() # 记住s里中最多有11个数据
byt = self.rep(byts) # 转换成无符号整型
L.append(byt) # L中添加这个数据
if s == "$$HEADEREND": # 如果发现了头结束,说明头结束了,去得到一些信息(如层厚等)
# print("$$HEADEREND FOUND!")
sL = ''.join(L) #
sL = sL.replace("\\n", '') # 去掉换行符号,得到下面的字符串
'''sL = $$HEADERSTART$$BINARY$$UNITS/00000000.010000$$VERSION/200$$LABEL/1,part1$$DATE/200620$$DIMENSION
/00000072.796799,00000032.592602,00000019.950001,00000132.546799,00000092.342598,00000025.799999
$$LAYERS/000040$$HEADEREND '''
Ls = sL.split("$$") # 用$$分割成单独的
''' Ls = ['', 'HEADERSTART', 'BINARY', 'UNITS/00000000.010000', 'VERSION/200', 'LABEL/1,part1', 'DATE/200620',
'DIMENSION/00000072.796799,00000032.592602,00000019.950001,00000132.546799,00000092.342598,00000025.799999',
'LAYERS/000040', 'HEADEREND'] '''
Ls = [s for s in Ls if '/' in s] # 如果有/就保存,没有就删去
''' Ls = ['UNITS/00000000.010000', 'VERSION/200', 'LABEL/1,part1', 'DATE/200620', 'DIMENSION/00000072.796799,00000032.592602,
00000019.950001,00000132.546799,00000092.342598,00000025.799999', 'LAYERS/000040'] '''
Ls = [item.split('/') for item in Ls] # 用/分割成小数组
''' Ls = [['UNITS', '00000000.010000'], ['VERSION', '200'], ['LABEL', '1,part1'], ['DATE', '200620'],
['DIMENSION', '00000072.796799,00000032.592602,00000019.950001,00000132.546799,00000092.342598,00000025.799999'],
['LAYERS', '000040']] '''
d_Ls = dict(Ls) # 转化成字典
''' d_Ls = {'UNITS': '00000000.010000', 'VERSION': '200', 'LABEL': '1,part1', 'DATE': '200620', 'DIMENSION':
'00000072.796799,00000032.592602,00000019.950001,00000132.546799,00000092.342598,00000025.799999', 'LAYERS': '000040'} '''
self.UNIT = float(d_Ls['UNITS']) # 得到单位
self.LAYERS = int(d_Ls['LAYERS']) # 得到层数
return d_Ls
break
def get_layer(self):
f1 = self.f_ascii
byts = ' '
byt = 0
L = []
n = 1
while byts:
byts = self.f.read(2) # 因为数据是我无符号整型,所以要一次读两个字节
byt_int, = struct.unpack("h", byts) # 进行格式转换成无符号整型
if byt_int == 128: # 如果是128
f1.write(str(byt_int)) # 写入128
f1.write('\n') # 换行
byts = self.f.read(2) # 读两个
byt_int, = struct.unpack("h", byts) # 转换格式
f1.write(str(byt_int * self.UNIT)) # 写入层厚
f1.write('\n')
elif byt_int == 129: # 写入129
f1.write(str(byt_int))
f1.write('\n') # 写入层厚mm
byts = self.f.read(2)
byt_int, = struct.unpack("h", byts)
f1.write(str(byt_int * self.UNIT))
f1.write('\n') # 写入内/外轮廓(0:内轮廓;1:外轮廓)
byts = self.f.read(2)
byt_int, = struct.unpack("h", byts)
f1.write(str(byt_int))
f1.write('\n') # 写入顶点的个数
byts = self.f.read(2)
byt_int, = struct.unpack("h", byts)
f1.write(str(byt_int))
f1.write('\n')
m = 2 * byt_int
while m > 0:
byts = self.f.read(2)
byt_int, = struct.unpack("h", byts)
cod = byt_int * self.UNIT
cod = round(cod, 2)
f1.write(str(cod))
f1.write(',')
m -= 1
f1.write('\n')
return 1
#下面要替换成自己的文件路径
f = open('D:/py_dir/CLI/tt.cli', 'rb')
f_ascii = open('D:/py_dir/CLI/tt1.cli', 'w')
structure = Structure(f, f_ascii)
d = structure.get_head()
n = structure.get_layer()
layers = structure.LAYERSf.close()
f.closed() #一定要记得关闭数据
f_ascii.close() #一定要记得关闭数据
java
源码在放在我写的blog里面了[http://www.welcomefsjblog.top/archives/3d打印cli格式文件的读取]
用了差不多一天才写出来,果然是个小垃圾。期间遇到很多问题,查了一些书或者有些从别人博客上看的,因为好多所以有些网址都忘了,非常不好意思白嫖了那么多大佬的解决办法。
代码还是有很多可以优化的地方,因为我的目的也不是得到这个输出的文件,而是直接在程序中对数据进行加工处理,在这只是给出代码给后面想读取cli文件的朋友提供直接的方法,避免走弯路而已。(自己确实走了很多弯路,相关资料不是很多)。
还是推荐各位去看官网的详细说明,本篇只是用到了无符号整型,以及没有任何的填充信息,所以代码跑起来不一定能够成功,只是提供一种思路而已,不至于无从下手。
参考网址
1.cli入门
2.python源码
3.激光选区熔化分区扫描策略算法生成及软件系统实现——硕士论文
3D打印CLI文件格式的读取的更多相关文章
- 3D打印:三维智能数字化创造(全彩)
3D打印:三维智能数字化创造(全彩)(全球第一本系统阐述3D打印与3D智能数字化的专业著作) 吴怀宇 编 ISBN 978-7-121-22063-0 2014年1月出版 定价:99.00元 42 ...
- Three.js 3D打印数据模型文件(.STL)载入中
3DPrint是现在和未来10年度科技产品的主流之中.广泛的. 对于电子商务类3D打印网站.一个主要功能就是商品3D呈现的方式,那是,3D数据可视化技术. HTML5(WebGL)它可以用于构建3D查 ...
- RAMPS1.4 3d打印控制板接线与测试
“工欲善其事,必先利其器”,在开始工作之前,你应该准备下面所说的工具(包括软件和硬件). 1.需要下载的软件 1.1 固件上传工具——Arduino IDE 这是上传固件的必备工具,有了这个软件让上传 ...
- RAMPS1.4 3D打印控制板:软件下载\连接\安装\测试
RAMPS1.4 3D打印控制板:软件下载\连接\安装\测试 特别说明: 电源接反,电机驱动板接反将有可能烧毁芯片和电路,请再三确认后再进行通电. 如何使用: 1.需要用到的模块或器件: Arduin ...
- RAMPS1.4 3d打印控制板接线与测试2
http://learn.makerlab.me/guides/1/articles/2 mega 2560板子在3d打印机中相当于大脑,控制这所有的3d打印配件来完成复杂的打印工作,但mega256 ...
- RAMPS1.4 3d打印控制板接线与测试1
1.需要下载的软件 1.1 固件上传工具--Arduino IDE 这是上传固件的必备工具,有了这个软件让上传固件变的容易很多,插上USB,就可以轻松上传. 下载地址:windows版本:http:/ ...
- 《3D打印:三维智能数字化创造(全彩)》
<3D打印:三维智能数字化创造(全彩)> 基本信息 作者: 吴怀宇 出版社:电子工业出版社 ISBN:9787121220630 上架时间:2014-1-13 出版日期:2014 年1月 ...
- 3D打印如何重组制造格局?
全球化的竞争正变得毫无底线,国与国之间只有利益,没有同情,也就是说美国品牌想把自己的工厂移回本土,是不会考虑中国工人的生存现状的,更不会顾及这里的GDP和环境问题,甚至还会依靠经济能力去奴役其他国家 ...
- 《3D打印与工业制造》个人总结 —— 周吉瑞
<3D打印与工业制造>个人总结 ---- 周吉瑞 JERRY_Z. ~ 2020 / 10 / 24 转载请注明出处!️ 目录 <3D打印与工业制造>个人总结 ---- 周吉瑞 ...
随机推荐
- JS字符串格式化
//字符串格式化String.prototype.format = function () { var values = arguments; return this.replace(/\{(\d+) ...
- Spring Cloud 解决了哪些问题?
在使用 Spring Boot 开发分布式微服务时,我们面临的问题很少由 Spring Cloud解决.与分布式系统相关的复杂性 – 包括网络问题,延迟开销,带宽问题,安 全问题.处理服务发现的能力 ...
- SVG是什么?
SVG表示(scalable vector graphics)可缩放矢量图形.这是一个基于文本的图形语言,它可以绘制使用文本.线.点等的图形,因此可以轻巧又快速地渲染.
- Flask-Script使用教程
Flask使用第三方脚本 一个干净的项目准备: 一个干净的Flask项目连接地址: https://pan.baidu.com/s/123TyVXOFvh5P7V8MbyMfDg 话不多说,上菜: 1 ...
- 学习Kvm(六)
五,管理虚拟存储 5.1 虚拟磁盘概述 5.1.1 虚拟化项目中存储的注意事项 [x] 存储的性能几乎总是虚拟化的瓶颈 [x] 通过多个硬盘驱动以分布磁盘I/O来实现存储解决方案 [x] 考虑部署集中 ...
- SDS-redis动态字符串
与C语言类似,redis自己创建了简单动态字符串SDS(Simple Dynamic String)即简单动态字符串,创建字符串类型的键值对,SDS表示字符串值,键值对的值为字符串对象 SDS用途可以 ...
- 遇到的问题之"项目启动加载不出页面"
已找到解决方案1 需要启动这两个微服务(注意:这个属于个人,你们也可以看看是否关联到相关微服务未启动)
- HTML5+CSS3兼容收藏夹
CSS3选择器兼容IE6~8: Selectivizr 使用方法: <!--[if (gte IE 6)&(lte IE 8)]> <script src="htt ...
- 前端基础问题整理-HTML相关
DOCTYPE的作用以及常见的DOCTYPE类型 <!DOCTYPE>声明位于文档中的最前面的位置,处于 <html> 标签之前,用来告知浏览器页面目前的文件是用哪种版本的HT ...
- CCF201812-1小明上学
题目背景 小明是汉东省政法大学附属中学的一名学生,他每天都要骑自行车往返于家和学校.为了能尽可能充足地睡眠,他希望能够预计自己上学所需要的时间.他上学需要经过数段道路,相邻两段道路之间设有至多一盏红绿 ...