python——找出直线经过的栅格

原理:
这是原理地址
python版代码:

import numpy as np
import math
#from pylab import *
import matplotlib.pyplot as plt

class inline:
    def __init__(self,A,B):
        self.A=A
        self.B=B
        #aaa=self.main()
        
    def line_func(self):
        a=self.B[1]-self.A[1]
        b=self.A[0]-self.B[0]
        c=self.B[0]*self.A[1]-self.A[0]*self.B[1]
        return a,b,c
    #这个就是转置坐标的函数
    def con_ij(self,dot):
        dd=[dot[1],dot[0]]
        return dd
    
    def cha_m(self):
        if self.A[0]>self.B[0] and self.A[1]>self.B[1]:
            return self.B,self.A
        else:
            return self.A,self.B
        
    def d_line(self):
        self.A,self.B=self.con_ij(self.A),self.con_ij(self.B)
        x=np.linspace(self.A[0],self.B[0],50)
        abc=self.line_func()
        y=(abc[0]*x+abc[2])/(-abc[1])
        #每次都以0.5的位置去标点
        i=np.arange(0.5,15.5,0.5)#横着的坐标
        j=np.arange(0.5,15.5,0.5)#竖着的坐标
        plt.xticks(i)
        plt.yticks(j)
        plt.plot(x,y)
    
    #上升的直线
    def upin_line(self):
        open=[]
        
        abc=self.line_func()#ax+by+c,a,b,c三个参数依次在结果中
        self.A,self.B=self.con_ij(self.A),self.con_ij(self.B)
        tan_theta=(self.B[0]-self.A[0])/(self.B[1]-self.A[1])
        if tan_theta < 1:#这是上升曲线
            open.append(self.B)
            #小于就用纵向,点和点之间隔了几个格子,就把几个格子加入open表
            x=[i for i in range(self.A[0],self.B[0]+2)]
            #print(x,len(x))
            y=[(abc[1]*i+abc[2])/(-abc[0]) for i in x]#这个y的公式实际要换成x的公式,因为x,y翻转了
            #print(y,len(y))
            for i in range(1,len(x)):
                if i!=1:
                    num = math.ceil(y[i])-math.floor(y[i-1]-0.001)#只在线是单增的情况适用
                else:
                    num = math.ceil(y[i])-math.floor(y[i-1])
                for j in range(num):
                    open.append([x[i-1],math.ceil(y[i])-j-1])
            #这些if语句以及下面这些if语句肯定是可以改进的,这是在具体实践过程中发现有些点奇奇怪怪的也在路径里面,可以改进成遇到起始点和初始点就停止往open表里添加元素。当然现在也能用。。。
            if [self.B[0],self.B[1]+1] in open:
                open.remove([self.B[0],self.B[1]+1])
            if [self.B[0],self.B[1]+2] in open:
                open.remove([self.B[0],self.B[1]+2])
            if [self.B[0],self.B[1]+3] in open:
                open.remove([self.B[0],self.B[1]+3])
            if [self.B[0],self.B[1]+4] in open:
                open.remove([self.B[0],self.B[1]+4])
        #大于用的是横向,一样的思路.
        elif tan_theta > 1:
            open.append(self.B)
            #x=[i for i in range(self.A[1]-1,self.B[1]+2)]
            x=np.arange(self.A[1]-0.5,self.B[1]+1,1)
            #print(x)
            y=[(abc[0]*i+abc[2])/(-abc[1]) for i in x]
            #print(y)
            for i in range(len(x)):
                if i!=0:
                    num=math.ceil(y[i])-math.floor(y[i-1]-0.001)
                    for j in range(num):
                        open.append([math.floor(y[i]-0.001)-j,math.floor(x[i])])
            #待改进的if语句         
            if [self.A[0]-1,self.A[1]] in open:
                open.remove([self.A[0]-1,self.A[1]])
            if [self.A[0]-2,self.A[1]] in open:
                open.remove([self.A[0]-2,self.A[1]])
            if [self.A[0]-3,self.A[1]] in open:
                open.remove([self.A[0]-3,self.A[1]])
            if [self.A[0]-4,self.A[1]] in open:
                open.remove([self.A[0]-4,self.A[1]])
            if [self.B[0]+1,self.B[1]] in open:
                open.remove([self.B[0]+1,self.B[1]])
            if [self.B[0]+2,self.B[1]] in open:
                open.remove([self.B[0]+2,self.B[1]])
            if [self.B[0]+3,self.B[1]] in open:
                open.remove([self.B[0]+3,self.B[1]])
            if [self.B[0]+4,self.B[1]] in open:
                open.remove([self.B[0]+4,self.B[1]])
        #这个else是当它正好斜对角的时候 
        else :
            open.append(self.A)
            open.append(self.B)
            i=0
            while i<self.B[1]-self.A[1]:
                open.append([self.A[0]+i,self.A[1]+i])
                i+=1
        #print(open)
        return open
    
    #这个就是下降的线条了,按理说应该要是对称的
    def dnin_line(self):
        open=[]
        abc=self.line_func()
        #print((abc[1]*8.5+abc[2])/(-abc[0]))
        tan_theta=(self.B[0]-self.A[0])/(self.A[1]-self.B[1])
        #print(tan_theta)
        #print(self.A,self.B)
        self.A,self.B=self.con_ij(self.A),self.con_ij(self.B)
        #print(self.A,self.B)
        #print(A[0]+1,A[1])
        open.append(self.A)
        open.append(self.B)
        #如果角度是45度,那么就应该是比较竖的直线
        if tan_theta <1:
            #画了图之后,应该是画竖格子
            x=np.arange(self.A[1]-0.5,self.B[1]+1,1)
            #print(x)
            y=[(abc[0]*j+abc[2])/(-abc[1]) for j in x]
            #print(y)
            for i in range(len(x)-1):
                num=(round(y[i])+0.5)-(round(y[i+1])-0.5)
                #print(num)
                #print(round(y[i])+0.5,(round(y[i+1])-0.5))
                for j in range(int(num)):
                    open.append([int(round(y[i]))-j,math.ceil(x[i])])
            #待改进的if语句
            if [self.A[0]+1,self.A[1]] in open:
                open.remove([self.A[0]+1,self.A[1]])
            if [self.B[0]-1,self.B[1]] in open:
                open.remove([self.B[0]-1,self.B[1]])
        elif tan_theta > 1:
            #这里就应该是画横格子
            #print(self.A[0],self.B[0])
            x=np.arange(self.B[0]-0.5,self.A[0]+1+0.5)
            y=[(abc[1]*j+abc[2])/(-abc[0]) for j in x]
            for i in range(len(x)-1):
                num=(round(y[i])+0.5)-(round(y[i+1])-0.5)
                for j in range(int(num)):
                    open.append([math.ceil(x[i]),int(round(y[i]))-j])
            if [self.A[0],self.A[1]-1] in open:
                open.remove([self.A[0],self.A[1]-1])
            if [self.B[0],self.B[1]+1] in open:
                open.remove([self.B[0],self.B[1]+1])
            if [self.B[0],self.B[1]+2] in open:
                open.remove([self.B[0],self.B[1]+2])
            if [self.B[0],self.B[1]+3] in open:
                open.remove([self.B[0],self.B[1]+3])
        return open
    #如果直线是横线
    def hen_line(self):
        open=[]
        #print(self.B[0]-self.A[0])
        for i in range(self.B[0]-self.A[0]):
            open.append([self.B[1],self.A[0]+i])
        open.append([self.B[1],self.B[0]])
        return open
    #这段是如果直线是竖线
    def shu_line(self):
        open=[]
        for i in range(self.B[1]-self.A[1]):
            open.append([self.A[1]+i,self.A[0]])
        open.append([self.B[1],self.B[0]])
        return open
    
    def main(self):
        if self.A[0]<self.B[0] and self.A[1]<self.B[1]:
            #都是小于的就用上升的情况
            open=self.upin_line()
        elif self.A[0] > self.B[0] and self.A[1] > self.B[1]:
            #都大于那就转换一下坐标,然后用上升
            self.A,self.B=self.B,self.A
            open=self.upin_line()
        elif self.A[0] <self.B[0] and self.A[1] >self.B[1]:
            #这里就是用下降了
            open=self.dnin_line()
        elif self.A[0] >self.B[0] and self.A[1] <self.B[1]:
            self.A,self.B=self.B,self.A
            open=self.dnin_line()
        elif self.A[1] ==self.B[1]:
            open=self.hen_line()
        else:
            open=self.shu_line()
            
        return open  

有个很别扭的问题是网格坐标和直线坐标不一致

x=[5,45]
y=[13,55]
plt.plot(x,y)
for i in range(len(x)):
    map_grid[x[i],y[i]]=2   
plt.imshow(map_grid, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
plt.grid(True)

在这里插入图片描述
直线坐标轴,下面是x轴,左边是y轴。而栅格的坐标轴左边是x轴,下方是y轴,所以在要注意将点的坐标转置,或是转置坐标轴才可以得到符合的结果。

map_grid=np.full((15,15),int(10),dtype=np.int8)

def m_show(mat,color):
    for item in mat:
        map_grid[item[0],item[1]] =color
    return map_grid
def xxx_y(x,y):
    x1=[]
    y1=[]
    x1.append(x[0]);x1.append(y[0])
    y1.append(x[1]);y1.append(y[1])
    return x1,y1
x=[5,13]
y=[9,2]

aaa=inline(x,y)
open=aaa.main()
m_show(open,5)
#以下这段就可以规定坐标轴的方向
xlim(-1, 15)  # 设置x轴范围
ylim(-1, 15)  # 设置y轴范围
my_x_ticks = np.arange(0, 15, 1)
my_y_ticks = np.arange(0, 15, 1)
plt.xticks(my_x_ticks)
plt.yticks(my_y_ticks)
xy=xxx_y(x,y)
plt.plot(xy[0],xy[1])
plt.imshow(map_grid, cmap=plt.cm.hot, interpolation='nearest', vmin=0, vmax=10)
plt.grid(True)

在这里插入图片描述
在这里插入图片描述不是所有线段都能完美的给出所有经过的栅格。先记录下。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值