diff --git a/skimage/draw/_draw.pyx b/skimage/draw/_draw.pyx index 0ac540df..aa88c2bd 100644 --- a/skimage/draw/_draw.pyx +++ b/skimage/draw/_draw.pyx @@ -37,14 +37,14 @@ def _coords_inside_image(rr, cc, shape, val=None): return rr[mask], cc[mask] -def line(Py_ssize_t y, Py_ssize_t x, Py_ssize_t y2, Py_ssize_t x2): +def line(Py_ssize_t y, Py_ssize_t x, Py_ssize_t y1, Py_ssize_t x1): """Generate line pixel coordinates. Parameters ---------- y, x : int Starting position (row, column). - y2, x2 : int + y1, x1 : int End position (row, column). Returns @@ -79,16 +79,16 @@ def line(Py_ssize_t y, Py_ssize_t x, Py_ssize_t y2, Py_ssize_t x2): """ cdef char steep = 0 - cdef Py_ssize_t dx = abs(x2 - x) - cdef Py_ssize_t dy = abs(y2 - y) + cdef Py_ssize_t dx = abs(x1 - x) + cdef Py_ssize_t dy = abs(y1 - y) cdef Py_ssize_t sx, sy, d, i with nogil: - if (x2 - x) > 0: + if (x1 - x) > 0: sx = 1 else: sx = -1 - if (y2 - y) > 0: + if (y1 - y) > 0: sy = 1 else: sy = -1 @@ -116,20 +116,20 @@ def line(Py_ssize_t y, Py_ssize_t x, Py_ssize_t y2, Py_ssize_t x2): x = x + sx d = d + (2 * dy) - rr[dx] = y2 - cc[dx] = x2 + rr[dx] = y1 + cc[dx] = x1 return np.asarray(rr), np.asarray(cc) -def line_aa(Py_ssize_t y1, Py_ssize_t x1, Py_ssize_t y2, Py_ssize_t x2): +def line_aa(Py_ssize_t y0, Py_ssize_t x0, Py_ssize_t y1, Py_ssize_t x1): """Generate anti-aliased line pixel coordinates. Parameters ---------- - y1, x1 : int + y0, x0 : int Starting position (row, column). - y2, x2 : int + y1, x1 : int End position (row, column). Returns @@ -165,17 +165,22 @@ def line_aa(Py_ssize_t y1, Py_ssize_t x1, Py_ssize_t y2, Py_ssize_t x2): cdef list cc = list() cdef list val = list() - cdef int dx = abs(x1 - x2) - cdef int dy = abs(y1 - y2) - cdef int err = dx - dy - cdef int x, y, e, ed, sign_x, sign_y + cdef int dx = abs(x0 - x1) + cdef int dx_prime - if x1 < x2: + cdef int dy = abs(y0 - y1) + cdef float err = dx - dy + cdef float err_prime + + cdef int x, y, sign_x, sign_y + cdef float ed + + if x0 < x1: sign_x = 1 else: sign_x = -1 - if y1 < y2: + if y0 < y1: sign_y = 1 else: sign_y = -1 @@ -183,30 +188,34 @@ def line_aa(Py_ssize_t y1, Py_ssize_t x1, Py_ssize_t y2, Py_ssize_t x2): if dx + dy == 0: ed = 1 else: - ed = (sqrt(dx*dx + dy*dy)) + ed = sqrt(dx*dx + dy*dy) - x, y = x1, y1 + x, y = x0, y0 while True: cc.append(x) rr.append(y) - val.append(1. * fabs(err - dx + dy) / (ed)) - e = err - if 2 * e >= -dx: - if x == x2: + val.append(fabs(err - dx + dy) / ed) + + err_prime = err + x_prime = x + + if (2 * err_prime) >= -dx: + if x == x1: break - if e + dy < ed: + if (err_prime + dy) < ed: cc.append(x) rr.append(y + sign_y) - val.append(1. * fabs(e + dy) / (ed)) + val.append(fabs(err_prime + dy) / ed) err -= dy x += sign_x - if 2 * e <= dy: - if y == y2: + + if 2 * err_prime <= dy: + if y == y1: break - if dx - e < ed: - cc.append(x) + if (dx - err_prime) < ed: + cc.append(x_prime + sign_x) rr.append(y) - val.append(fabs(dx - e) / (ed)) + val.append(fabs(dx - err_prime) / ed) err += dx y += sign_y diff --git a/skimage/draw/tests/test_draw.py b/skimage/draw/tests/test_draw.py index c3e49664..c1af1a80 100644 --- a/skimage/draw/tests/test_draw.py +++ b/skimage/draw/tests/test_draw.py @@ -104,6 +104,21 @@ def test_line_aa_diagonal(): for x, y in zip(r, c): assert_equal(img[r, c], 1) +def test_line_equal_aliasing_horizontally_vertically(): + img0 = np.zeros((25, 25)) + img1 = np.zeros((25, 25)) + + # Near-horizontal line + rr, cc, val = line_aa(10, 2, 12, 20) + img0[rr, cc] = val + + # Near-vertical (transpose of prior) + rr, cc, val = line_aa(2, 10, 20, 12) + img1[rr, cc] = val + + # Difference - should be zero + assert_array_equal(img0, img1.T) + def test_polygon_rectangle(): img = np.zeros((10, 10), 'uint8')