"""
@Source http://www.roguebasin.com/index.php?title=Bresenham%27s_Line_Algorithm

Algorithm to get a list of pixels associated with a line from pixel a to pixel b. Not all pixels are returned, but
rather 1 pixel per row for flat lines and 1 pixel per column for steep lines.

For example
_a__   _x__
____ > __x_
__b_   __x_

and
____   ____
a___ > xx__
___b   __xx

"""


def get_line(start, end):
    """
    Bresenham's Line Algorithm

    Produces a list of tuples from start and end
    > points1 = get_line((0, 0), (3, 4))
    > points2 = get_line((3, 4), (0, 0))
    > assert(set(points1) == set(points2))
    > print points1
    [(0, 0), (1, 1), (1, 2), (2, 3), (3, 4)]
    > print points2
    [(3, 4), (2, 3), (1, 2), (1, 1), (0, 0)]
    """

    # Setup initial conditions
    x1, y1 = start
    x2, y2 = end
    dx = x2 - x1
    dy = y2 - y1
 
    # Determine how steep the line is
    is_steep = abs(dy) > abs(dx)
 
    # Rotate line
    if is_steep:
        x1, y1 = y1, x1
        x2, y2 = y2, x2
 
    # Swap start and end points if necessary and store swap state
    swapped = False
    if x1 > x2:
        x1, x2 = x2, x1
        y1, y2 = y2, y1
        swapped = True
 
    # Recalculate differentials
    dx = x2 - x1
    dy = y2 - y1
 
    # Calculate error
    error = int(dx / 2.0)
    ystep = 1 if y1 < y2 else -1
 
    # Iterate over bounding box generating points between start and end
    y = y1
    points = []
    for x in range(x1, x2 + 1):
        coord = (y, x) if is_steep else (x, y)
        points.append(coord)
        error -= abs(dy)
        if error < 0:
            y += ystep
            error += dx
 
    # Reverse the list if the coordinates were swapped
    if swapped:
        points.reverse()
    return points