I have updated my Python code. It no longer uses inner loops to increment the x coordinates, although the setup now requires some integer divisions.
It also handles sides sloped in either direction, so it does not need any particular ordering of the x coordinates.
def fill_triangle(screen, x0, y0, x1, y1, x2):
# Fills a flat-bottomed triangle with apex at (x0, y0) and
# lower vertices at (x1, y1), (x2, y1). Assumes y0 < y1.
xL = xR = x0
y = y0
dy = y1 - y0
dxL, deL = divmod(x1 - x0, dy)
dxR, deR = divmod(x2 - x0, dy)
if dxL < 0:
deL = -deL
if dxR < 0:
deR = -deR
eL = eR = 0
n = dy
while n > 0:
fill_raster_line(screen, xL, xR, y)
xL += dxL
eL += deL
if eL > 0:
if dxL < 0:
xL -= 1
else:
xL += 1
eL -= dy
xR += dxR
eR += deR
if eR > 0:
if dxR < 0:
xR -= 1
else:
xR += 1
eR -= dy
y += 1
n -= 1
def fill_raster_line(screen, x0, x1, y):
x = x0
n = x1 - x0 + 1
while n > 0:
draw_pixel(screen, x, y)
x += 1
n -= 1
def draw_pixel(screen, x, y):
screen[y][x] = '*'
#----------------------- Testing -------------------------
def test(x0, y0, x1, y1, x2):
screen = [[' '] * 79 for y in range(23)]
fill_triangle(screen, x0, y0, x1, y1, x2)
for row in screen:
print(''.join(row))
test(50, 5, 10, 20, 60)
test(50, 5, 10, 20, 40)
test(30, 5, 40, 20, 60)