原理:
这是原理地址
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)
不是所有线段都能完美的给出所有经过的栅格。先记录下。