Very simply, given a point A(x,y) and another point B(m,n), I need a function that can return in any iterable object a list[k,z] of all points in between.
Am only interested in integer points, so no need for floats.
I need the best possible pythonic way because this 'little' function is going to be heavily run and is the key pillar of a larger system.
EDIT:
@roippi, thanks pointing out the gotcha concerning the integers. From my code below, you can see I try to step across the x axis and get corresponding y, then do the same for y. My set of points will not have any non-discrete co-ordinate point, so for the moment I can afford to overlook that small flaw
import itertools
#Vars
origin = {'x':0, 'y':0}
def slope(origin, target):
if target['x'] == origin['x']:
return 0
else:
m = (target['y'] - origin['y']) / (target['x'] - origin['x'])
return m
def line_eqn(origin, target):
x = origin['x']
y = origin['y']
c = -(slope(origin, target)*x - y)
c = y - (slope(origin, target)*x)
#return 'y = ' + str(slope(target)) + 'x + ' + str(c)
m = slope(origin, target)
return {'m':m, 'c':c}
def get_y(x, slope, c):
# y = mx + c
y = (slope*x) + c
return y
def get_x(y, slope, c):
#x = (y-c)/m
if slope == 0:
c = 0 #vertical lines never intersect with y-axis
if slope == 0:
slope = 1 #Do NOT divide by zero
x = (y - c)/slope
return x
def get_points(origin, target):
coord_list = []
#Step along x-axis
for i in range(origin['x'], target['x']+1):
eqn = line_eqn(origin, target)
y = get_y(i, eqn['m'], eqn['c'])
coord_list.append([i, y])
#Step along y-axis
for i in range(origin['y'], target['y']+1):
eqn = line_eqn(origin, target)
x = get_x(i, eqn['m'], eqn['c'])
coord_list.append([x, i])
#return unique list
return list(k for k,_ in itertools.groupby(sorted(coord_list)))
origin = {'x':1, 'y':3}
target = {'x':1, 'y':6}
print get_points(origin, target)
def get_line(x1, y1, x2, y2):
points = []
issteep = abs(y2-y1) > abs(x2-x1)
if issteep:
x1, y1 = y1, x1
x2, y2 = y2, x2
rev = False
if x1 > x2:
x1, x2 = x2, x1
y1, y2 = y2, y1
rev = True
deltax = x2 - x1
deltay = abs(y2-y1)
error = int(deltax / 2)
y = y1
ystep = None
if y1 < y2:
ystep = 1
else:
ystep = -1
for x in range(x1, x2 + 1):
if issteep:
points.append((y, x))
else:
points.append((x, y))
error -= deltay
if error < 0:
y += ystep
error += deltax
# Reverse the list if the coordinates were reversed
if rev:
points.reverse()
return points
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With