刻字机尖角补偿

本文详细介绍了刻字机在处理直角切割时的尖角补偿原理,通过圆弧过渡解决切割不直和闭合曲线问题,并给出了Python代码实现,包括直线段的插补计算和不同转角情况下的圆弧处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 刻字机尖角补偿原理

刀具切割直线段过渡方法在文章旋转偏心裁切刀切向跟踪及半径补偿 已经有过说明。刻字机由于刀具半径的影响,切割直角时会不直会比较圆滑,而且在闭合曲线的下刀点会容易不闭合。使用尖角补偿可以克服这些问题。

如上图所示,切割俩条相邻线段AB和BC时,刀心需要走的轨迹是从A' --> B' --> B'' -->C'。由于刻字机使用的刻刀刀尖半径都比较小,而且刀具也是固定没有转动轴控制转动,所以从B'过渡到B''时使用圆弧进行过渡。这里B2和B1都是圆弧上的过渡点。示意图中从B'B''采用小线段B'B2、B2B1、B1B''进行圆弧拟合过渡。

AB的矢量角α,则A'点坐标为(Xa+r*cosα,Ya+r*sinα)。BC的矢量角为β,则B''的坐标为(Xb+r*cosβ,Yb+r*sinβ)。C'的坐标为(Xc+r*cosβ,Yc+r*sinβ)。AB的转角为β-α。

2 尖角补偿python程序实现

import numpy
import cv2
import math

const_ratio = 10
WIDTH = 100
HEIGHT = 60
KNIFE_CIR = 40 #plt中40个单位=1mm
ANGLE_STEP = 30 #圆弧过渡时插补间隔30度

def show_img(window,img):
    cv2.namedWindow(window,0)
    cv2.resizeWindow(window,int(img.shape[1]),int(img.shape[0]))
    cv2.imshow(window,img)

def proc_line(line):
    i = 0
    signZ = 1
    if len(line) == 0:
        return None
    while line[i]<'0' or line[i]>'9':
        if line[i] == 'U':
            signZ = 0
        if line[i] == '-':
            break
        i = i+1
        if i == len(line):
            return None
        
    line = line[i:]
    if len(line) == 0:
        return None
    strs = line.split(',')
    if len(strs) != 2:
        return None
    axis_y = int(strs[0])
    axis_x = int(strs[1])
    
    if (axis_x is None) or (axis_y is None):
        return None
    return {'x':axis_x,'y':axis_y,'z':signZ}

def plot_plt(cv_img,data,print_width,print_height):
    height_total = print_height
    width_total = print_width
    line = ""
    comma = 0
    points = []
    for i in range(len(data)):
        try:
            ch = chr(data[i])
        except:
            ch = data[i]
        if ch == ';':
            point = proc_line(line)
            if point is not None:
                points.append(point)
            line = ""
            comma = 0
        else:
            line = line+ch
            if ch==',' or ch==' ':
                comma = comma+1
            if comma == 2:
                point = proc_line(line)
                if point is not None:
                    points.append(point)
                line = ""
                comma = 0
    max_x = points[0]['x']
    max_y = points[0]['y']
    min_x = points[0]['x']
    min_y = points[0]['y']
   
    for point in points:
        if point['x']>max_x:
            max_x = point['x']
        if point['y']>max_y:
            max_y = point['y']
        if point['x']<min_x:
            min_x = point['x']
        if point['y']<min_y:
            min_y = point['y']
    print(max_x,max_y,min_x,min_y)

    pre_point = points[0]
    black = (0,255,0)
    
    offset_x = 10*const_ratio
    offset_y = 10*const_ratio

    for point in points:
        x = int((point['x'])*const_ratio/40+offset_x)
        y = int((point['y'])*const_ratio/40+offset_y)
        if point['z'] == 1:
            cv2.line(cv_img,(pre_point['x'],pre_point['y']),(width_total*const_ratio-x,height_total*const_ratio-y),black,lineType=cv2.LINE_AA)
        pre_point = {'x':width_total*const_ratio-x,'y':height_total*const_ratio-y}

def plot_file(img,filepath):
    with open(filepath) as f:
        data = f.read()
        plot_plt(img,data,WIDTH,HEIGHT)

def plot_plt_comp(cv_img,data,print_width,print_height):
    height_total = print_height
    width_total = print_width
    line = ""
    comma = 0
    points = []
    for i in range(len(data)):
        try:
            ch = chr(data[i])
        except:
            ch = data[i]
        if ch == ';':
            point = proc_line(line)
            if point is not None:
                points.append(point)
            line = ""
            comma = 0
        else:
            line = line+ch
            if ch==',' or ch==' ':
                comma = comma+1
            if comma == 2:
                point = proc_line(line)
                if point is not None:
                    points.append(point)
                line = ""
                comma = 0
    max_x = points[0]['x']
    max_y = points[0]['y']
    min_x = points[0]['x']
    min_y = points[0]['y']
   
    for point in points:
        if point['x']>max_x:
            max_x = point['x']
        if point['y']>max_y:
            max_y = point['y']
        if point['x']<min_x:
            min_x = point['x']
        if point['y']<min_y:
            min_y = point['y']
    print(max_x,max_y,min_x,min_y)

    #这里开始执行尖角补偿插补计算
    angleArr = []
    pointNum = len(points)
    pre_point = {'x':0,'y':0,'z':0}
    pre_angle = 0
    downPoint = None
    downAngle = 0
    off_x = 0
    off_y = 0
    pointsInterpArr = []
    for i in range(pointNum):
        point = points[i]
        angle = math.atan2(point['y']-pre_point['y'],point['x']-pre_point['x'])
        length = math.sqrt((point['y']-pre_point['y'])*(point['y']-pre_point['y'])+(point['x']-pre_point['x'])*(point['x']-pre_point['x']))
        angleArr.append(angle)
        angle_delta = (angle-pre_angle)*180/math.pi
        if angle_delta >= 180:
            angle_delta = angle_delta-360
        elif angle_delta <= -180:
            angle_delta = angle_delta+360
        if angle_delta>0:
            angle_step = ANGLE_STEP
        else:
            angle_step = -ANGLE_STEP
        print(angle_delta,length)
        if length == 0:
            continue
        elif point['z'] == 0: #抬刀时不处理
            pointsInterpArr.append(point)
        elif pre_point['z'] == 0:#由抬刀变为下刀保存下刀点坐标和角度,并进行起点和终点偏移
            downPoint = pre_point
            downAngle = angle
            x1=pre_point['x']+KNIFE_CIR*math.cos(angle)
            y1=pre_point['y']+KNIFE_CIR*math.sin(angle)
            pointsInterpArr.append({'x':int(x1),'y':int(y1),'z':0})
            x2 = point['x']+KNIFE_CIR*math.cos(angle)
            y2 = point['y']+KNIFE_CIR*math.sin(angle)
            pointsInterpArr.append({'x':int(x2),'y':int(y2),'z':1})
            off_x = KNIFE_CIR*math.cos(angle)
            off_y = KNIFE_CIR*math.sin(angle)
        elif abs(angle_delta)>30:#下刀切割时线段转角大于30度时进行圆弧过渡
            count = math.floor(angle_delta/angle_step)
            remain = angle_delta-count*angle_step
            for j in range(0,count):
                x = pre_point['x']+KNIFE_CIR*math.cos(pre_angle+angle_step*(j+1)*math.pi/180)
                y = pre_point['y']+KNIFE_CIR*math.sin(pre_angle+angle_step*(j+1)*math.pi/180)
                pointsInterpArr.append({'x':int(x),'y':int(y),'z':1})
            if abs(remain) > 0.1:
                x = pre_point['x']+KNIFE_CIR*math.cos(angle)
                y = pre_point['y']+KNIFE_CIR*math.sin(angle)
                pointsInterpArr.append({'x':int(x),'y':int(y),'z':1})
            
            delta_x = KNIFE_CIR*math.cos(angle)
            delta_y = KNIFE_CIR*math.sin(angle)
            pointsInterpArr.append({'x':int(point['x']+delta_x),'y':int(point['y']+delta_y),'z':point['z']})  

            off_x = KNIFE_CIR*math.cos(angle)
            off_y = KNIFE_CIR*math.sin(angle)
        else:#转角小于30度直接过渡
            delta_x = KNIFE_CIR*math.cos(angle)
            delta_y = KNIFE_CIR*math.sin(angle)
            pointsInterpArr.append({'x':int(point['x']+delta_x),'y':int(point['y']+delta_y),'z':point['z']}) 

        #发现是下刀点坐标时代表曲线段闭合,进行闭合圆弧过渡
        if downPoint != None and length > 0 and point['x'] == downPoint['x'] and point['y'] == downPoint['y']:
            angle_delta = (downAngle-angle)*180/math.pi
            if angle_delta >= 180:
                angle_delta = angle_delta-360
            elif angle_delta <= -180:
                angle_delta = angle_delta+360
            if angle_delta>0:
                angle_step = ANGLE_STEP
            else:
                angle_step = -ANGLE_STEP
            count = math.floor(angle_delta/angle_step)
            remain = angle_delta-count*angle_step
            for j in range(0,count):
                x = point['x']+KNIFE_CIR*math.cos(angle+angle_step*(j+1)*math.pi/180)
                y = point['y']+KNIFE_CIR*math.sin(angle+angle_step*(j+1)*math.pi/180)
                pointsInterpArr.append({'x':int(x),'y':int(y),'z':1})
            if abs(remain) > 0.1:
                x = point['x']+KNIFE_CIR*math.cos(downAngle)
                y = point['y']+KNIFE_CIR*math.sin(downAngle)
                pointsInterpArr.append({'x':int(x),'y':int(y),'z':1})
        pre_point = point
        pre_angle = angle

    pre_point = pointsInterpArr[0]
    black = (0,255,0)
    
    offset_x = 10*const_ratio
    offset_y = 10*const_ratio

    max_x = pointsInterpArr[0]['x']
    max_y = pointsInterpArr[0]['y']
    min_x = pointsInterpArr[0]['x']
    min_y = pointsInterpArr[0]['y']
    for point in pointsInterpArr:
        if point['x']>max_x:
            max_x = point['x']
        if point['y']>max_y:
            max_y = point['y']
        if point['x']<min_x:
            min_x = point['x']
        if point['y']<min_y:
            min_y = point['y']
    print(max_x,max_y,min_x,min_y)

    for point in pointsInterpArr:
        x = int((point['x'])*const_ratio/40+offset_x)
        y = int((point['y'])*const_ratio/40+offset_y)
        if point['z'] == 1:
            cv2.line(cv_img,(pre_point['x'],pre_point['y']),(width_total*const_ratio-x,height_total*const_ratio-y),black,lineType=cv2.LINE_AA)
        pre_point = {'x':width_total*const_ratio-x,'y':height_total*const_ratio-y}

def plot_file_comp(img,filepath):
    with open(filepath) as f:
        data = f.read()
        plot_plt_comp(img,data,WIDTH,HEIGHT)

cv_img = numpy.ones((HEIGHT*const_ratio,WIDTH*const_ratio),dtype=numpy.uint8)
cv_img = cv2.bitwise_not(cv_img)
cv2.rectangle(cv_img,(0,0),(WIDTH*const_ratio-1,HEIGHT*const_ratio-1),(0,0,0))

file = 'C:/Users/liuzj/Desktop/plt/rec.plt'
plot_file(cv_img,file)
show_img('img1',cv_img)


cv_img2 = numpy.ones((HEIGHT*const_ratio,WIDTH*const_ratio),dtype=numpy.uint8)
cv_img2 = cv2.bitwise_not(cv_img2)
cv2.rectangle(cv_img2,(0,0),(WIDTH*const_ratio-1,HEIGHT*const_ratio-1),(0,0,0))

plot_file_comp(cv_img2,file)
show_img('img2',cv_img2)



cv2.waitKey(0)

正方形尖角补偿轨迹:

三角形尖角补偿轨迹:

方圆尖角补偿轨迹:

不要加密狗开启 文泰刻绘2002 精减破解版 一、操作界面。容易上手。Word风格操作界面,只要您有使用Windows操作系统Word的基本知识,使用本软件就会有亲切感。同时,本软件还吸收了FreeHand、PageMaker、CorelDraw等优秀西文软件的优点,增加了键盘功能、全自动(傻瓜型)操作,使用时直接、简单、方便。 二、图形库。丰富多彩、量大面广。除随本软件系统光碟配置的原文泰新图库、文泰实用图库(著名商标、中国民俗图库)、文泰国际图库、国家标准图库(公共标志、提示标志、交通标志等13种)等共有图形近万种外,又增加了千年图库光碟,极大地增加了用户选择应用的可能范围方便灵活性,节省时间、提高效益。这些图库共同组成了本行业目前最新、最全、最实用的图形库。 三、中英文字库。多而全: 1、汉字库:字型字体是目前最多的。字型用三次曲线精心制作,是真正的轮廓汉字,笔划经过处理后更加粗厚,可任意放大而不变形。字体有近百种,均按简体、繁体区分,支持GBK大字符集。 2、中英文匹配:为您的汉字库配套了相近的英文字体标点,并配置了相应的英文基线调整,使用更方便。 3、可挂接Windows底层中英文TTF (Windows True Type Font) 字库。通过特有的去交叉算法处理,您不必担心输出Windows底层交叉笔划的汉字时会将笔划刻断。 4、新增6款单线字,其中文泰单线简体4种、文泰单线繁体2种。 四、速度设备利用率:采用32位编程,软件运行速度大大提高。独特的后台输出功能:不管刻字机内存大小如何,只要刻字机一开始工作,就可以把计算机解放出来,使您能在刻字机刻字的过程中充分利用计算机进行其它的工作。 五、与其它软件的兼容性:可与其它软件的EPS与PLT、DXF文件交换,可以读入TIF图与BMP图及文泰刻绘5.X版本的文件。 六、图形输入编辑 1、直接支持图形扫描:可在本软件内直接挂接扫描仪。 2、彩色、灰度图像条块化,使输出更形象、更逼真。 3、简单实用的节点编辑:增加了批量处理节点的功能对线段直接操作功能,效率更高。 4、弧排、沿线排版功能强大:提供多种方式弧形画法。弧形排版功能,去除了多余的参数设置,使用更简单,方便。 5、图形扫描曲线化描边:对扫描的彩色图像可以直接处理成用曲线描述的轮廓图,以供刻字机或雕刻机输出。 6、新增调色板功能:用户可以在调色板中任意调配颜色,并可对所需内容全色或分色输出。 7、图形的任意组合:特有的交、并、叉算法方便的节点编辑,使您的图形制作更简单快捷。 8、最新优化的图象矢量化,速度快、效果好,可以处理大幅面图象。 9、整图自动光顺功能,无需进行节点编辑,轻松到只需轻轻按一下键,就能输出更加光顺圆滑的大幅面图形,有效地避免锯齿现象,而且保证尖角分明。 七、文字录入编辑: 1、支持汉字大批量录入的即打即排方式录入,可插入以.txt 为后缀的文本文件,并可使用Windows其它软件直接链接到本程序。 2、汉字曲线勾边加粗功能:用户可以将您需要的汉字任意加粗,并可刻出扩边效果,完全不用担心会产生笔划交叉。 3、对任意文字增加曲线的内外轮廓,来改变文字的粗细程度。 4、汉字的变形及特技效果:可以将汉字做任意形状的变形,可以制作球形、圆柱形等各种特技效果。 5、多国、多民族语言支持。在Windows 2000 下,安装相应的True Type 字库(用户自行安装),即可在同一版面上同时输入中文、俄文、阿拉伯文、韩文等语言文字。 八、整体排版 1、随意的缩放功能:输出版面任意缩放,不需要重新制作版面。 2、人性化的刻绘输出:输出前可以将区域及内容预显在屏幕上,页面可以任意移动及任意定义原点。 3、多页排版,分页输出功能。 九、输出功能 99d软件站提供高速下载分流 更多好软件,请来99d.com 1、随意裁切功能:用小幅面刻字机完成大幅面输出。用户可以随意使用裁切功能,将大字,图形从任何位置,以任何方式裁切输出,并提供裁切区域重复功能,真正做到方便迅速,无缝连接。 2、省纸方式输出:最大限度节省您的纸张,为您节省每一分钱。 3、批量复制输出:同一内容可以批量复制后一次输出。 4、支持任意Windows下的打印设备,任意大小输出、实心彩色输出。 5、支持喷绘机巨幅打印输出。 6、通过特有的排序算法,使输出速度更快,质量更好。 7、支持国产刻字机补偿输出:刻绘输出时,本软件独有的曲线补偿功能使国产的刻字机刻绘输出效果完全等同于进口的刻字机。 8、可以单独设置输出页面的纵横比,确保最终产品的尺寸误差最小。 9、海报制作及彩色打印输出功能:支持Windows底层彩色黑白打印机直接输出排版结果,组合后批量复制不再有内存限制,并支持图像打印。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值