在增材打印CAM中,我们需要在切片得到的每层轮廓中规划生成打印路径。传统的三轴3D打印的常见填充方式有:轮廓平行填充和方向平行填充。其中轮廓平行填充主要是通过轮廓偏置实现的。
pyclipper安装使用
Python下安装pyclipper库,命令行输入pip指令:
pip install pyclipper
通过
import pyclipper
导入使用。
pyclipper基础
pyclipper是Python环境下的Clipper库,主要用于平面闭合多边形或非闭合多线段的裁剪(clipping)和偏置(offsetting)。
重要术语:
-
裁剪(Clipping): 指二维平面图形之间的四个布尔操作:交集(intersection)、并(union)、差(difference )和异或(exclusive-or))中的任何一个。
-
路径(Path): 是一个有序的顶点集合,它定义一个单一的几何轮廓(contour),要么是一条线(一个开放的路径),要么是一个多边形(一个闭合的轮廓)。
-
直线(Line): 或者多线段(polyline) 是一个包含两个或多个顶点的开放路径。
-
多边形(Polygon): 通常是指一个二维的区域,其边界是一个外部不相交的闭合轮廓。
-
轮廓(Contour): 同路径(path)。
-
孔(Hole): 是一个多边形中不属于多边形的封闭区域。一个“孔多边形”是一个封闭的路径。
-
多边形填充规则(Polygon Filling Rule): 填充规则,定义了平面封闭区域中的内部区域(即需要填充的区域)和外部的区域(即“孔”,不需要填充的区域)。
需要掌握的Clipper基础:
- Clipper库 | 坐标圆整和精度控制
- Clipper库 | 类型和填充规则
代码实现
import math
import vtk
from pyclipper import *
def numeric_scaling(digits: 'int > 0' = 7, *, pos: list):
def decorate(func):
def scaled(*_args):
__args = list(_args)
f = math.pow(10, digits) # 数值精度,默认为7位小数
for p in pos:
if isinstance(_args[p], int) or isinstance(_args[p], float):
__args[p] *= f
elif isinstance(_args[p], list):
__args[p] = [[tuple(map(lambda x: x * f, pt)) for pt in path] for path in _args[p]]
else:
pass
_result = func(*tuple(__args)) # _result is list of paths
_result = [[tuple(map(lambda x: x / f, pt)) for pt in path] for path in _result]
return _result
return scaled
return decorate
@numeric_scaling(digits = 7, pos = [0, 1])
def offset(polys, delta, jt = JT_SQUARE): # 偏置函数,输人多边形:[[[pt1_x,pt2_y],...,[ptN_x,ptN_y]],[...],...]
pco = PyclipperOffset()
pco.AddPaths(polys, jt, ET_CLOSEDPOLYGON)
sln = pco.Execute(delta) # 偏置距离delta
return sln # 返回偏置曲线
# 轮廓平行路径填充
def genCpPath_clipper(boundaries, interval, shellThk): # 输人:轮廓、偏置距离、填充带宽
offsetPolyses = [] # 偏置曲线列表
delta = interval / 2 # 首次偏置距离
polys = offset(boundaries, -delta, JT_SQUARE)
offsetPolyses.append(polys) # 偏置曲线存放在offsetPolys中
while math.fabs(delta) < shellThk: # 循环直至偏置距离大于填充带宽
delta += interval
polys = offset(boundaries, -delta, JT_SQUARE)
if polys is None or len(polys) == 0:
break # 已到偏置区域中心,则退出
offsetPolyses.append(polys)
return offsetPolyses
按理来讲装饰器定义和调用应该分开来,这里为了方便所以写在一个文件中。
测试结果
偏置轮廓填充结果如下图所示,其中黑色为切片得到的轮廓,红色为偏置填充的路径。
第24层偏置填充结果:
第27层偏置填充结果: