From be83329b2d7b6c3395c13bedcf151e0fffd3a958 Mon Sep 17 00:00:00 2001 From: Alexander Buhl <63983202+Buhlean@users.noreply.github.com> Date: Wed, 14 Jul 2021 00:18:35 +0200 Subject: [PATCH] Implemented remaining 7/8 of ImageDrawLine The existing code was correct for one octant, it now works for all 8 Added two internal functions, _ImageDrawLineHorizontal and _ImageDrawLineVertical, whithout which it would've been 4 times as much code. --- src/textures.c | 105 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 93 insertions(+), 12 deletions(-) diff --git a/src/textures.c b/src/textures.c index 9bef90c4c..15b5f6d6f 100644 --- a/src/textures.c +++ b/src/textures.c @@ -2415,21 +2415,102 @@ void ImageDrawPixelV(Image *dst, Vector2 position, Color color) ImageDrawPixel(dst, (int)position.x, (int)position.y, color); } -// Draw line within an image -void ImageDrawLine(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color) -{ - int m = 2*(endPosY - startPosY); - int slopeError = m - (endPosX - startPosX); +void _ImageDrawLineHorizontal(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color){ - for (int x = startPosX, y = startPosY; x <= endPosX; x++) + int changeInX = (endPosX - startPosX); + int abs_changeInX = changeInX < 0 ? -changeInX : changeInX; + int changeInY = (endPosY - startPosY); + int abs_changeInY = changeInY < 0 ? -changeInY : changeInY; + + // we need to go up or down depending (-1 or 1); + int y_directional_unit = changeInY < 0 ? -1 : 1; + + int A = 2* abs_changeInY; + int B = A - 2* abs_changeInX; + int P = A - abs_changeInX; + + ImageDrawPixel(dst, startPosX, startPosY, color); + + for (int x = startPosX+1, y = startPosY; x <= endPosX; x += 1) { - ImageDrawPixel(dst, x, y, color); - slopeError += m; - - if (slopeError >= 0) + if (P >= 0) { - y++; - slopeError -= 2*(endPosX - startPosX); + y += y_directional_unit; + P += B; + } + else + { + P += A; + } + + ImageDrawPixel(dst, x, y, color); + } +} + +void _ImageDrawLineVertical(Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color){ + // same code as *Horizontal but with all x and y flipped + + int changeInX = (endPosX - startPosX); + int abs_changeInX = changeInX < 0 ? -changeInX : changeInX; + int changeInY = (endPosY - startPosY); + int abs_changeInY = changeInY < 0 ? -changeInY : changeInY; + + // we need to go left or right depending (-1 or 1) + int x_directional_unit = changeInX < 0 ? -1 : 1; + + int A = 2* abs_changeInX; + int B = A - 2* abs_changeInY; + int P = A - abs_changeInY; + + ImageDrawPixel(dst, startPosX, startPosY, color); + + for (int y = startPosY+1, x = startPosX; y <= endPosY; y += 1) + { + if (P >= 0) + { + x += x_directional_unit; + P += B; + } + else + { + P += A; + } + + ImageDrawPixel(dst, x, y, color); + } +} + +// Draw line within an image +void ImageDrawLine (Image *dst, int startPosX, int startPosY, int endPosX, int endPosY, Color color){ + // Using Bresenham's algorithm as described in + // Drawing Lines with Pixels - Joshua Scott - March 2012 + // https://classic.csunplugged.org/wp-content/uploads/2014/12/Lines.pdf + + int changeInX = (endPosX - startPosX); + int abs_changeInX = changeInX < 0 ? -changeInX : changeInX; + int changeInY = (endPosY - startPosY); + int abs_changeInY = changeInY < 0 ? -changeInY : changeInY; + + if (abs_changeInY < abs_changeInX) + { + if (changeInX > 0) + { + _ImageDrawLineHorizontal(dst, startPosX, startPosY, endPosX, endPosY, color); + } + else + { + _ImageDrawLineHorizontal(dst, endPosX, endPosY, startPosX, startPosY, color); + } + } + else + { + if (changeInY > 0) + { + _ImageDrawLineVertical(dst, startPosX, startPosY, endPosX, endPosY, color); + } + else + { + _ImageDrawLineVertical(dst, endPosX, endPosY, startPosX, startPosY, color); } } }