您的当前位置:首页正文

逐点比较法直线和圆弧插补算法及实现

2024-12-01 来源:个人技术集锦

一年前就用逐点比较法做过直线和圆弧的插补,当时没做笔记,现在忘光了,这次好好的整理了一番。:)

如果你看到了这里,相信你已经对逐点比较法有所了解了,缺的是整个插补过程中需要用到的公式而已。

补充一点:

# 当求圆弧的正逆时,可以根据圆弧上的三个点与圆心构成的三个向量的行列式的正负来判断,
# 如果行列式的值大于0,是逆时针,小于零,是顺时针,等于零,则在一条直线上
# 这个a是圆弧的起点和圆心构成的向量, b是圆弧上中点与圆心构成的向量, c是圆弧上终点与圆心构成的向量。
def main():
    c= [0, 3, 1]
    b = [3/math.sqrt(2), 3/math.sqrt(2), 1]
    a = [3,0, 1]
    ns = a[0]*b[1]*c[2] + a[1]*b[2]*c[0] + a[2]*b[0]*c[1] - a[2]*b[1]*c[0] - a[1]*b[0]*c[2] - a[0]*b[2]*c[0]
    if ns > 0:
        print("逆时针")
    elif ns <0:
        print("顺时针")
    elif ns==0:
        print("在一条直线上")
main()

 运行结果:

 

一、公式算法部分

这张图里的真值表是为了在FPGA中实现直线和圆弧插补的,为了验证算法的正确性,我先在python做了一下仿真(因为python简单啊),事实证明算法没问题,文章后面会附上完整的圆弧和直线插补的python代码。

圆弧插补时,象限用圆弧圆心与圆弧起点的向量和圆心与圆弧终点的向量和向量(x, y)来进行判断。在求Fm时,用到的xi, yi是当前点的坐标,这个是有正负的

插补直线时,用直线终点与直线起点构成的向量的(x, y)的正负判断象限,Fm的计算用到的坐标(xe, ye)是直线终点与直线起点构成的向量的x,y坐标,在求Fm时用到的是绝对值

 

二、具体实现部分

2.1直线插补:python代码如下

import turtle

point = []


def judge_quadrant(x0, y0, xe, ye):
    x = xe - x0
    y = ye - y0
    if(x > 0) and (y > 0):  # 第一象限
        quadrant = 1
    elif(x < 0) and (y > 0):  # 第二象限
        quadrant = 2
    elif(x < 0) and (y < 0):  # 第三象限
        quadrant = 3
    elif(x > 0) and (y < 0):  # 第四象限
        quadrant = 4
    elif x > 0 and y == 0:
        quadrant = 5   # X轴正方向
    elif x < 0 and y == 0:
        quadrant = 6   # X轴负方向
    elif x == 0 and y > 0:
        quadrant = 7   # Y轴正方向
    elif x == 0 and y < 0:
        quadrant = 8   # Y轴负方向
    return quadrant


def interpolation(quadrant, x0, y0, xe, ye):
    x = xe - x0
    y = ye - y0
    fm = 0
    x1 = abs(x)
    y1 = abs(y)
    total = x1 + y1
    print("total = ",total)
    cnt = 0
    while cnt < total:
        if quadrant < 5:
            if fm >= 0:
                if quadrant == 1 or quadrant == 4:
                    x0 += 1
                elif quadrant == 2 or quadrant == 3:
                    x0 -= 1
                # point.append(p)
                fm = fm - y1
            elif fm <0:
                if quadrant == 1 or quadrant == 2:
                    y0 += 1
                elif quadrant == 3 or quadrant == 4:
                    y0 -= 1
                # point.append(p)
                fm = fm + x1
        else:
            if quadrant == 5:
                x0 += 1
            elif quadrant ==6:
                x0 -=1
            elif quadrant ==7:
                y0 += 1
            elif quadrant ==8:
                y0 -=1
        p = (x0, y0)
        point.append(p)
        cnt += 1
    print("点的列表为:",point)


def get_points():
    line_path = [(0, 0), (-5, -6)]
    for i in range(0,len(line_path)-1):
        xo= line_path[i][0]
        yo = line_path[i][1]
        print(xo,yo)
        xe = line_path[i+1][0]
        ye = line_path[i+1][1]
        print(xe, ye)
        quadrant = judge_quadrant(xo, yo, xe, ye)
        print(quadrant)
        interpolation(quadrant,xo, yo, xe, ye)


def draw_line():
    print(point)
    turtle.goto(point[0])
    turtle.pendown()
    for item in point:
        turtle.goto(item)


def draw_coordinate():
    turtle.penup()
    turtle.goto(0,500)
    turtle.pendown()
    turtle.goto(0,-1000)
    turtle.penup()
    turtle.goto(500,0)
    turtle.pendown()
    turtle.goto(-500, 0)
    turtle.penup()
    turtle.goto(0, 0)


def main():
    draw_coordinate()
    get_points()
    draw_line()
    turtle.exitonclick()


if __name__ == '__main__':
    main()

运行效果图:红箭头是路劲方向

2.2圆弧插补:python代码

import turtle
point = []


def arc_interpolation(quadrant, sn, x1, y1, totalsteps): #sn 0:逆,1:顺
    fm = 0
    point.append((x1,  y1))
    while totalsteps != 0:
        if quadrant == 1:
            if sn == 0:   #1 逆圆
                if fm >= 0:
                    fm = fm -2*x1 +1
                    x1 -= 1
                else:
                    fm = fm +2*y1 +1
                    y1 += 1
            else:   #1 顺圆
                if fm >= 0:
                    fm = fm -2*y1 +1
                    y1 -= 1
                else:
                    fm = fm +2* x1 +1
                    x1 += 1
        elif quadrant == 2:
            if sn == 0:   #1 逆圆
                if fm >= 0:
                    fm = fm -2*y1 +1
                    y1 -= 1
                else:
                    fm = fm -2*x1 +1
                    x1 -= 1
            else:
                if fm >= 0:
                    fm = fm +2*x1 +1
                    x1 += 1
                else:
                    fm = fm +2*y1 +1
                    y1 += 1
        elif quadrant == 3:
            if sn==0:   #1 逆圆
                if fm >= 0:
                    fm = fm +2*x1 +1
                    x1 += 1
                else:
                    fm = fm -2*y1 +1
                    y1 -= 1
            else:
                if fm >= 0:
                    fm = fm +2*y1 +1
                    y1 += 1
                else:
                    fm = fm -2*x1 +1
                    x1 -= 1
        elif quadrant == 4:
            if sn==0:   #1 逆圆
                if fm >= 0:
                    fm = fm +2*y1 +1
                    y1 += 1
                else:
                    fm = fm +2*x1 +1
                    x1 += 1
            else:
                if fm >= 0:
                    fm = fm -2*x1 +1
                    x1 -= 1
                else:
                    fm = fm -2*y1 +1
                    y1 -= 1
        point.append((x1, y1))
        totalsteps -= 1


def judge_quadrant(xo, yo, x1, y1, x2, y2):
    x11 = x1 - xo
    y11 = y1 - yo
    x22 = x2 - xo
    y22 = y2 - yo
    x12 = x11 + x22
    y12 = y11 + y22
    if x12 > 0 and y12 > 0:
        quadrant = 1
    elif x12 < 0 and y12 > 0:
        quadrant = 2
    elif x12 < 0 and y12 < 0:
        quadrant = 3
    elif x12 > 0 and y12 < 0:
        quadrant = 4
    return quadrant


def get_points():
    line_path = [(0, 0), (-30, 0), (0, -30)]    #圆弧路径
    sn = 0
    for i in range(0,len(line_path)-2):
        xo = line_path[i][0]
        yo = line_path[i][1]
        print(xo,yo)
        x1 = line_path[i+1][0]
        y1 = line_path[i+1][1]

        x2 = line_path[i+2][0]
        y2 = line_path[i+2][1]
        print(x1, y1,"  ", x2, y2)
        quadrant = judge_quadrant(xo, yo, x1, y1, x2, y2)
        print(quadrant)
        totalsteps = abs(x2 - x1) + abs(y2 - y1)
        arc_interpolation(quadrant, sn, x1, y1, totalsteps)


def draw_line():
    print(point)
    turtle.goto(point[0])
    turtle.pendown()
    for item in point:
        turtle.goto(item)


def draw_coordinate():
    turtle.penup()
    turtle.goto(0, 500)
    turtle.pendown()
    turtle.goto(0, -1000)
    turtle.penup()
    turtle.goto(500, 0)
    turtle.pendown()
    turtle.goto(-500, 0)
    turtle.penup()
    turtle.goto(0, 0)


def main():
    draw_coordinate()
    get_points()
    draw_line()
    turtle.exitonclick()


if __name__ == '__main__':
    main()

运行结果如下

这里只是画了一个圆弧,有兴趣的话,可以在代码中增加这个里面的坐标值,当然了,这个没有实现跨象限的圆弧插补,所以,每次要画的圆弧起点和终点须在同一象限。

line_path = [(0, 0), (-90, 0), (0, -90)]    #圆弧路径
显示全文