Python手写Bresenham画线算法(线段+射线)

Bresenham画线算法

在这里插入图片描述

根据两个顶点画线

Bresenham画线算法适用于斜率绝对值小于1的情况,所以要进行翻转,k绝对值小于1的情况下将算法中的x和y换一下即可

#画线算法,参数为(原图像,点1,点2,画线数值)
def draw_line(ori_canvas,x1,y1,x2,y2,color):
    canvas=copy.deepcopy(ori_canvas)
    delta_x=x2-x1
    delta_y=y2-y1
    #判断斜率是否存在
    if(delta_x==0):
        for i in range(min(y1,y2),max(y1,y2)+1):
            canvas[x1][i]=color
        return canvas
    k=1.0*delta_y/delta_x
    # 根据斜率<1分类
    if(abs(k)<1):
        # 固定x增长方向
        if(x1>x2):
            x1,x2=x2,x1
            y1,y2=y2,y1   
        delta_x=x2-x1
        delta_y=y2-y1
        x=x1
        y=y1
        canvas[x][y]=color
        # 判断y增长方向
        if(k<0):
            delta_y=-delta_y
        p=2*delta_y-delta_x
        for i in range(delta_x):
            if(p<0):
                x+=1
                p+=2*delta_y
            else:
                x+=1
                if(k>0):
                    y+=1
                else:
                    y-=1
                p+=2*delta_y-2*delta_x
            canvas[x][y]=color
    else:
        # 固定y增长方向
        if(y1>y2):
            x1,x2=x2,x1
            y1,y2=y2,y1
        delta_x=x2-x1
        delta_y=y2-y1
        x=x1
        y=y1
        canvas[x][y]=color
        # 判断x增长方向
        if(k<0):
            delta_x=-delta_x
        p=2*delta_x-delta_y
        for i in range(delta_y):
            if(p<0):
                y+=1
                p+=2*delta_x
            else:
                if(k>0):
                    x+=1
                else:
                    x-=1
                y+=1
                p+=2*delta_x-2*delta_y
            canvas[x][y]=color
    return canvas
                if(k>0):
                    y+=1
                else:
                    y-=1
                p+=2*delta_y-2*delta_x
            canvas[x][y]=color
    else:
        if(y1>y2):
            x1,x2=x2,x1
            y1,y2=y2,y1
        delta_x=x2-x1
        delta_y=y2-y1
        x=x1
        y=y1
        canvas[x][y]=color
        if(k<0):
            delta_x=-delta_x
        p=2*delta_x-delta_y
        for i in range(delta_y):
            if(p<0):
                y+=1
                p+=2*delta_x
            else:
                if(k>0):
                    x+=1
                else:
                    x-=1
                y+=1
                p+=2*delta_x-2*delta_y
            canvas[x][y]=color
    return canvas
# 圆周采集一系列角度
def get_theta_list(points_number):
    lis=np.arange(0,points_number)
    return 1.0*lis/points_number*2*math.pi
new_canvas=np.zeros([100,100])
theta_list=get_theta_list(12)
point_list=[]
for theta in theta_list:
    x=40*math.cos(theta)+50
    y=40*math.sin(theta)+50
    #print(x,y)
    point_list.append([x,y])
for x,y in point_list:
    new_canvas=draw_line(new_canvas,50,50,int(x),int(y),1)
#new_canvas=draw_line(canvas,23,12,6,12,1)
plt.figure(figsize=(10, 10))
plt.imshow(new_canvas,cmap='gray')

请添加图片描述

根据端点以及角度画线

根据端点以及线段方向,计算出射线的最远点,然后使用画线算法

#根据theta角进行画线
def theta_ray(x1,y1,theta,ori_canvas,color):
    canvas=copy.deepcopy(ori_canvas)
    height=canvas.shape[0]
    width=canvas.shape[1]
    x2,y2=0,0
    #计算沿直线拓展后的边界点
    if(abs(math.tan(theta))<1e-3 or abs(math.tan(theta))>1e3): #垂直方向
        if(abs(theta-0)<1e-3):
            y2=y1
            x2=height-1
        elif(abs(theta-math.pi/2)<1e-3):
            x2=x1
            y2=width-1
        elif(abs(theta-math.pi)<1e-3):
            y2=y1
            x2=0
        elif(abs(theta-3*math.pi/2)<1e-3):
            x2=x1
            y2=0
    else:
        k=math.tan(theta)
        #第一象限方向
        if(theta>=0 and theta<math.pi/2):
            yy=int(y1+k*(height-1-x1))
            if(yy<width):
                x2=height-1
                y2=yy
            else:
                y2=width-1
                x2=int(x1+1/k*(width-1-y1))
        #第二象限方向
        elif(theta>=math.pi/2 and theta<=math.pi):
            yy=int(y1-k*x1)
            if(yy<width):
                x2=0
                y2=yy
            else:
                y2=width-1
                x2=int(x1+1/k*(width-1-y1))
        #第三象限方向
        elif(theta>=math.pi and theta<3*math.pi/2):
            yy=int(y1-k*x1)
            if(yy>=0):
                x2=0
                y2=yy
            else:
                y2=0
                x2=int(x1-1/k*y1)
        #第四象限方向
        elif(theta>=3*math.pi/2 and theta<2*math.pi):
            yy=int(y1+k*(height-1-x1))
            if(yy>=0):
                x2=height-1
                y2=yy
            else:
                y2=0
                x2=int(x1-1/k*y1)
    delta_x=x2-x1
    delta_y=y2-y1
    #判断斜率是否存在
    if(delta_x==0):
        for i in range(min(y1,y2),max(y1,y2)+1):
            canvas[x1][i]=color
        return canvas
    k=1.0*delta_y/delta_x
    # 根据斜率<1分类
    if(abs(k)<1):
        # 固定x增长方向
        if(x1>x2):
            x1,x2=x2,x1
            y1,y2=y2,y1   
        delta_x=x2-x1
        delta_y=y2-y1
        x=x1
        y=y1
        canvas[x][y]=color
        # 判断y增长方向
        if(k<0):
            delta_y=-delta_y
        p=2*delta_y-delta_x
        for i in range(delta_x):
            if(p<0):
                x+=1
                p+=2*delta_y
            else:
                x+=1
                if(k>0):
                    y+=1
                else:
                    y-=1
                p+=2*delta_y-2*delta_x
            canvas[x][y]=color
    else:
        # 固定y增长方向
        if(y1>y2):
            x1,x2=x2,x1
            y1,y2=y2,y1
        delta_x=x2-x1
        delta_y=y2-y1
        x=x1
        y=y1
        canvas[x][y]=color
        # 判断x增长方向
        if(k<0):
            delta_x=-delta_x
        p=2*delta_x-delta_y
        for i in range(delta_y):
            if(p<0):
                y+=1
                p+=2*delta_x
            else:
                if(k>0):
                    x+=1
                else:
                    x-=1
                y+=1
                p+=2*delta_x-2*delta_y
            canvas[x][y]=color
    return canvas
pre_theta_list=get_theta_list(20)
mapp=np.zeros([100,100])
for theta in pre_theta_list:
    mapp=theta_ray(20,30,theta,mapp,3)
    plt.imshow(mapp,cmap='gray')

请添加图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值