Browse Source

Fixes #1873 Implemented remaining 7/8 of ImageDrawLine (#1874)

* 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.

* ImageDrawLine: Replaced 3 functions with 1

Removed both freshly added internal functions
Crammed it all into one

* ImageDrawLine shortened significantly using maths

Substituted X and Y, then wrote one abstract loop instead of 4 specific loops.
Lots of comments to explain what I'm doing for future maintainers.

* Now conforms with style conventions

Also reworded a comment to sound more... fomal.
pull/1886/head
Alexander Buhl 3 years ago
committed by GitHub
parent
commit
ff2b8d6db1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 94 additions and 12 deletions
  1. +94
    -12
      src/textures.c

+ 94
- 12
src/textures.c View File

@ -2414,26 +2414,108 @@ 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);
for (int x = startPosX, y = startPosY; x <= endPosX; x++)
// 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;
int startU, startV, endU, V_step; // Substitutions, either U = X, V = Y or vice versa. See loop at end of function
//int endV; // This is not needed, but to aid understanding it is left in the code below.
int A, B, P; // See linked paper above. Explained down in the main loop.
int is_x_y_reversed = (abs_changeInY < abs_changeInX);
if (is_x_y_reversed)
{
ImageDrawPixel(dst, x, y, color);
slopeError += m;
if (slopeError >= 0)
A = 2*abs_changeInY;
B = A - 2*abs_changeInX;
P = A - abs_changeInX;
if (changeInX > 0)
{
startU = startPosX;
startV = startPosY;
endU = endPosX;
//endV = endPosY;
}
else
{
startU = endPosX;
startV = endPosY;
endU = startPosX;
//endV = startPosY;
// since start and end are reversed:
changeInX = -changeInX;
changeInY = -changeInY;
}
V_step = (changeInY < 0)? -1 : 1;
ImageDrawPixel(dst, startU, startV, color); // At this point they are correctly ordered...
}
else // all X and Y are reversed in here:
{
A = 2*abs_changeInX;
B = A - 2*abs_changeInY;
P = A - abs_changeInY;
if (changeInY > 0)
{
startU = startPosY;
startV = startPosX;
endU = endPosY;
//endV = endPosX;
}
else
{
y++;
slopeError -= 2*(endPosX - startPosX);
startU = endPosY;
startV = endPosX;
endU = startPosY;
//endV = startPosX;
// since start and end are reversed:
changeInX = -changeInX;
changeInY = -changeInY;
}
V_step = (changeInX < 0)? -1 : 1;
ImageDrawPixel(dst, startV, startU, color); // ... but need to be reversed here. Repeated in the main loop below.
}
// We already drew the start point. If we started at startU+0, the line would be crooked and too short.
for (int U = startU+1, V = startV; U <= endU; U += 1)
{
if (P >= 0)
{
V += V_step; // Adjusts whenever we stray too far from the direct line. Details in the linked paper above.
P += B; // Remembers that we corrected our path.
}
else
{
P += A; // Remembers how far we are from the direct line.
}
if (is_x_y_reversed) // Substitutions may be in wrong order for drawing:
{
ImageDrawPixel(dst, U, V, color);
}
else
{
ImageDrawPixel(dst, V, U, color);
}
}
}
// Draw line within an image (Vector version)
void ImageDrawLineV(Image *dst, Vector2 start, Vector2 end, Color color)
{

Loading…
Cancel
Save