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文件格式的读取的更多相关文章

  1. 3D打印:三维智能数字化创造(全彩)

    3D打印:三维智能数字化创造(全彩)(全球第一本系统阐述3D打印与3D智能数字化的专业著作) 吴怀宇 编   ISBN 978-7-121-22063-0 2014年1月出版 定价:99.00元 42 ...

  2. Three.js 3D打印数据模型文件(.STL)载入中

    3DPrint是现在和未来10年度科技产品的主流之中.广泛的. 对于电子商务类3D打印网站.一个主要功能就是商品3D呈现的方式,那是,3D数据可视化技术. HTML5(WebGL)它可以用于构建3D查 ...

  3. RAMPS1.4 3d打印控制板接线与测试

    “工欲善其事,必先利其器”,在开始工作之前,你应该准备下面所说的工具(包括软件和硬件). 1.需要下载的软件 1.1 固件上传工具——Arduino IDE 这是上传固件的必备工具,有了这个软件让上传 ...

  4. RAMPS1.4 3D打印控制板:软件下载\连接\安装\测试

    RAMPS1.4 3D打印控制板:软件下载\连接\安装\测试 特别说明: 电源接反,电机驱动板接反将有可能烧毁芯片和电路,请再三确认后再进行通电. 如何使用: 1.需要用到的模块或器件: Arduin ...

  5. RAMPS1.4 3d打印控制板接线与测试2

    http://learn.makerlab.me/guides/1/articles/2 mega 2560板子在3d打印机中相当于大脑,控制这所有的3d打印配件来完成复杂的打印工作,但mega256 ...

  6. RAMPS1.4 3d打印控制板接线与测试1

    1.需要下载的软件 1.1 固件上传工具--Arduino IDE 这是上传固件的必备工具,有了这个软件让上传固件变的容易很多,插上USB,就可以轻松上传. 下载地址:windows版本:http:/ ...

  7. 《3D打印:三维智能数字化创造(全彩)》

    <3D打印:三维智能数字化创造(全彩)> 基本信息 作者: 吴怀宇 出版社:电子工业出版社 ISBN:9787121220630 上架时间:2014-1-13 出版日期:2014 年1月 ...

  8. 3D打印如何重组制造格局?

    ​全球化的竞争正变得毫无底线,国与国之间只有利益,没有同情,也就是说美国品牌想把自己的工厂移回本土,是不会考虑中国工人的生存现状的,更不会顾及这里的GDP和环境问题,甚至还会依靠经济能力去奴役其他国家 ...

  9. 《3D打印与工业制造》个人总结 —— 周吉瑞

    <3D打印与工业制造>个人总结 ---- 周吉瑞 JERRY_Z. ~ 2020 / 10 / 24 转载请注明出处!️ 目录 <3D打印与工业制造>个人总结 ---- 周吉瑞 ...

随机推荐

  1. Myql 中的事务回滚机制概述 ?

    事务是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个 不可分割的工作单位,事务回滚是指将该事务已经完成的对数据库的更新操作撤 销. 要同时修改数据库中两个不同表时,如果它们不是一个事 ...

  2. 三、MyCat主要配置介绍

    一.配置文件 1.server.xml Mycat的配置文件,设置账号.参数等2.schema.xml Mycat对应的物理数据库和数据库表的配置3.rule.xml Mycat分片(分库分表)规则 ...

  3. ACL 权限控制机制?

    UGO(User/Group/Others) 目前在 Linux/Unix 文件系统中使用,也是使用最广泛的权限控制方式.是一种粗 粒度的文件系统权限控制模式. ACL(Access Control ...

  4. mybatis-02-mapper生成器插件使用

    sb_mybatis <?xml version="1.0" encoding="UTF-8"?> <project xmlns=" ...

  5. 7. Github Pages 搭建网站

    7. Github Pages 搭建网站 个人站点 访问 https://用户名.github.io 搭建步骤 1) 创建个人站点   ->  新建仓库(注:仓库名必须是[用户名.github. ...

  6. vuex基础详解

    vuex入门 安装 vuex为我们提供了两种使用方法 直接引入 vuex下载地址:https://unpkg.com/vuex@2.0.0 下载之后用< script >标签包裹引入即可 ...

  7. 第二次课堂练习-连接hbase数据库-页面展示

    图片来源:中国知网 页面来源:中国科学院文献情报中心-科技查新平台 如有侵权,请评论留言

  8. Java JDK 动态代理实现和代码分析

    JDK 动态代理 内容 一.动态代理解析 1. 代理模式 2. 为什么要使用动态代理 3. JDK 动态代理简单结构图 4. JDK 动态代理实现步骤 5. JDK 动态代理 API 5.1 java ...

  9. 使用Socket实现HttpServer(二)

    使用Socket实现HttpServer(二) 前面我们使用 Socket 实现了一个简易的 HttpServer,接下来我们将对我们的服务器进行优化: 面向对象的封装 优化线程模型(引入多线程) R ...

  10. HTTP长连接和短连接及应用情景

    HTTP短连接 HTTP/1.0中默认使用短连接, 客户端和服务器进行一次HTTP操作, 就需要建立一次连接, 任务结束连接也关闭. 当客户端浏览器访问的web网页中包含其他的web资源时, 每遇到一 ...