Xiaolin Wu's line algorithm: Difference between revisions
Content added Content deleted
({{header|Racket}} implementation added) |
(Updated D entry) |
||
Line 181: | Line 181: | ||
/// Plots anti-aliased line by Xiaolin Wu's line algorithm. |
/// Plots anti-aliased line by Xiaolin Wu's line algorithm. |
||
void aaLine(Color)(ref Image!Color img |
void aaLine(Color)(ref Image!Color img, |
||
double x1, double y1, |
|||
double x2, double y2, |
|||
/*pure*/ nothrow { |
in Color color) /*pure*/ nothrow { |
||
// Straight translation of Wikipedia pseudocode. |
// Straight translation of Wikipedia pseudocode. |
||
static double round(in double x) |
static double round(in double x) pure nothrow { |
||
return floor(x + 0.5); |
return floor(x + 0.5); |
||
} |
} |
||
static double fpart(in double x) |
static double fpart(in double x) pure nothrow { |
||
return x - |
return x - x.floor; |
||
} |
} |
||
static double rfpart(in double x) |
static double rfpart(in double x) pure nothrow { |
||
return 1 - fpart(x); |
return 1 - fpart(x); |
||
} |
} |
||
Line 200: | Line 200: | ||
auto dx = x2 - x1; |
auto dx = x2 - x1; |
||
auto dy = y2 - y1; |
auto dy = y2 - y1; |
||
immutable ax = |
immutable ax = dx.abs; |
||
immutable ay = |
immutable ay = dy.abs; |
||
static Color mixColors(in Color c1, in Color c2, in double p) |
static Color mixColors(in Color c1, in Color c2, in double p) |
||
Line 215: | Line 215: | ||
// Plot function set here to handle the two cases of slope. |
// Plot function set here to handle the two cases of slope. |
||
void delegate(in int, in int, in double) |
void delegate(ref Image!Color img, in int, in int, in double) |
||
pure nothrow plot; |
|||
if (ax < ay) { |
if (ax < ay) { |
||
swap(x1, y1); |
swap(x1, y1); |
||
swap(x2, y2); |
swap(x2, y2); |
||
swap(dx, dy); |
swap(dx, dy); |
||
plot = (x, y, p) { |
//plot = (img, x, y, p) { |
||
plot = (ref Image!Color img, x, y, p) { |
|||
assert(p >= 0.0 && p <= 1.0); |
assert(p >= 0.0 && p <= 1.0); |
||
img[y, x] = mixColors(color, img[y, x], p); |
img[y, x] = mixColors(color, img[y, x], p); |
||
}; |
}; |
||
} else { |
} else { |
||
plot = (x, y, p) { |
//plot = (img, x, y, p) { |
||
plot = (ref Image!Color img, x, y, p) { |
|||
assert(p >= 0.0 && p <= 1.0); |
assert(p >= 0.0 && p <= 1.0); |
||
img[x, y] = mixColors(color, img[x, y], p); |
img[x, y] = mixColors(color, img[x, y], p); |
||
Line 238: | Line 242: | ||
// Handle first endpoint. |
// Handle first endpoint. |
||
auto xEnd = |
auto xEnd = x1.round; // Not pure. |
||
auto yEnd = y1 + gradient * (xEnd - x1); |
auto yEnd = y1 + gradient * (xEnd - x1); |
||
auto xGap = rfpart(x1 + 0.5); |
auto xGap = rfpart(x1 + 0.5); |
||
// This will be used in the main loop. |
// This will be used in the main loop. |
||
immutable xpxl1 = cast(int)xEnd; |
immutable xpxl1 = cast(int)xEnd; |
||
immutable ypxl1 = cast(int) |
immutable ypxl1 = cast(int)yEnd.floor; |
||
plot(xpxl1, ypxl1, rfpart(yEnd) * xGap); |
plot(img, xpxl1, ypxl1, rfpart(yEnd) * xGap); |
||
plot(xpxl1, ypxl1 + 1, fpart(yEnd) * xGap); |
plot(img, xpxl1, ypxl1 + 1, fpart(yEnd) * xGap); |
||
// First y-intersection for the main loop. |
// First y-intersection for the main loop. |
||
auto yInter = yEnd + gradient; |
auto yInter = yEnd + gradient; |
||
// Handle second endpoint. |
// Handle second endpoint. |
||
xEnd = |
xEnd = x2.round; |
||
yEnd = y2 + gradient * (xEnd - x2); |
yEnd = y2 + gradient * (xEnd - x2); |
||
xGap = fpart(x2 + 0.5); |
xGap = fpart(x2 + 0.5); |
||
// This will be used in the main loop. |
// This will be used in the main loop. |
||
immutable xpxl2 = cast(int)xEnd; |
immutable xpxl2 = cast(int)xEnd; |
||
immutable ypxl2 = cast(int) |
immutable ypxl2 = cast(int)yEnd.floor; |
||
plot(xpxl2, ypxl2, rfpart(yEnd) * xGap); |
plot(img, xpxl2, ypxl2, rfpart(yEnd) * xGap); |
||
plot(xpxl2, ypxl2 + 1, fpart(yEnd) * xGap); |
plot(img, xpxl2, ypxl2 + 1, fpart(yEnd) * xGap); |
||
// Main loop. |
// Main loop. |
||
foreach (immutable x; xpxl1 + 1 .. xpxl2) { |
foreach (immutable x; xpxl1 + 1 .. xpxl2) { |
||
plot(x, cast(int) |
plot(img, x, cast(int)yInter.floor, rfpart(yInter)); |
||
plot(x, cast(int) |
plot(img, x, cast(int)yInter.floor + 1, fpart(yInter)); |
||
yInter += gradient; |
yInter += gradient; |
||
} |
} |