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.激光选区熔化分区扫描策略算法生成及软件系统实现——硕士论文

最新文章

  1. 【67测试20161116】【数论】【DP】【思维】
  2. 转型?还是延伸?开源建站系统近乎推整套SNS社区解决方案
  3. asp.net json 与xml 的基础事例
  4. SQL 查询某个表被哪些存储过程使用到
  5. MMO之禅(三)职业能力
  6. ES6的Class
  7. 《android传感器高级编程》译者序
  8. 手动创建第一个JSP应用
  9. POJ 1547
  10. eclipse gradle 自动打包
  11. 如何进行Monkey Test
  12. about mobile web
  13. 查看Wii的系统版本信息
  14. GDB 多进程调试
  15. C语言声明解析方法
  16. 2. MariaDB激活二进制日志
  17. (摘)linux下yum安装redis以及使用
  18. CSS布局 两列布局之单列定宽,单列自适应布局思路
  19. Java Web 浏览器关闭后Session就会被销毁吗?
  20. 基本排序算法[python实现]

热门文章

  1. ActiveMQ数据接收类型问题
  2. Vue-Router在当前UR不刷新的Debug调试
  3. Redis 最适合的场景?
  4. 判断集合中存在String字符串 或 判断集合中不存在String字符串
  5. Altium Designer 原理图的绘制前导
  6. 关于js中this指向的总结
  7. 小程序输入框闪烁BUG解决方案
  8. ES6-11学习笔记--扩展运算符与rest参数
  9. ztree详解
  10. 《头号玩家》AI电影调研报告(五)