Skip to content

Commit 11d7cc8

Browse files
committed
feat: add bresenham's line drawing algorithm
1 parent 9b52ac9 commit 11d7cc8

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.thealgorithms.geometry;
2+
3+
import java.awt.Point;
4+
import java.util.ArrayList;
5+
import java.util.List;
6+
7+
/**
8+
* The {@code BresenhamLine} class implements the Bresenham's line algorithm,
9+
* which is an efficient way to determine the points of a straight line
10+
* between two given points in a 2D space.
11+
*
12+
* <p>This algorithm uses integer arithmetic to calculate the points,
13+
* making it suitable for rasterization in computer graphics.</p>
14+
*
15+
* For more information, please visit {@link https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm}
16+
*/
17+
public final class BresenhamLine {
18+
19+
/**
20+
* Finds the list of points that form a straight line between two endpoints.
21+
*
22+
* @param x0 the x-coordinate of the starting point
23+
* @param y0 the y-coordinate of the starting point
24+
* @param x1 the x-coordinate of the ending point
25+
* @param y1 the y-coordinate of the ending point
26+
* @return a {@code List<Point>} containing all points on the line
27+
*/
28+
public List<Point> findLine(int x0, int y0, int x1, int y1) {
29+
List<Point> line = new ArrayList<>();
30+
31+
// Calculate differences and steps for each axis
32+
int dx = Math.abs(x1 - x0); // Change in x
33+
int dy = Math.abs(y1 - y0); // Change in y
34+
int sx = (x0 < x1) ? 1 : -1; // Step in x direction
35+
int sy = (y0 < y1) ? 1 : -1; // Step in y direction
36+
int err = dx - dy; // Initial error term
37+
38+
// Loop until we reach the endpoint
39+
while (true) {
40+
line.add(new Point(x0, y0)); // Add current point to the line
41+
42+
// Check if we've reached the endpoint
43+
if (x0 == x1 && y0 == y1) {
44+
break; // Exit loop if endpoint is reached
45+
}
46+
47+
// Calculate error term doubled for decision making
48+
int e2 = err * 2;
49+
50+
// Adjust x coordinate if necessary
51+
if (e2 > -dy) {
52+
err -= dy; // Update error term
53+
x0 += sx; // Move to next point in x direction
54+
}
55+
56+
// Adjust y coordinate if necessary
57+
if (e2 < dx) {
58+
err += dx; // Update error term
59+
y0 += sy; // Move to next point in y direction
60+
}
61+
}
62+
63+
return line; // Return the list of points forming the line
64+
}
65+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package com.thealgorithms.geometry;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import java.awt.Point;
6+
import java.util.List;
7+
import org.junit.jupiter.api.Test;
8+
9+
/**
10+
* The {@code BresenhamLineTest} class contains unit tests for the {@code BresenhamLine} class.
11+
* It verifies the correctness of the findLine method, which generates a list of points
12+
* representing a straight line between two specified endpoints.
13+
*
14+
* <p>This test class uses JUnit 5 for testing and covers various scenarios including horizontal,
15+
* vertical, and diagonal lines, as well as lines with negative coordinates.</p>
16+
*/
17+
class BresenhamLineTest {
18+
19+
// Instance of BresenhamLine to be tested
20+
private final BresenhamLine bresenhamLine = new BresenhamLine();
21+
22+
/**
23+
* Tests the generation of a horizontal line from (0, 0) to (5, 0).
24+
* Asserts that the generated line matches the expected list of points.
25+
*/
26+
@Test
27+
void testHorizontalLine() {
28+
List<Point> line = bresenhamLine.findLine(0, 0, 5, 0);
29+
List<Point> expected = List.of(new Point(0, 0), new Point(1, 0), new Point(2, 0), new Point(3, 0), new Point(4, 0), new Point(5, 0));
30+
assertEquals(expected, line);
31+
}
32+
33+
/**
34+
* Tests the generation of a vertical line from (0, 0) to (0, 5).
35+
* Asserts that the generated line matches the expected list of points.
36+
*/
37+
@Test
38+
void testVerticalLine() {
39+
List<Point> line = bresenhamLine.findLine(0, 0, 0, 5);
40+
List<Point> expected = List.of(new Point(0, 0), new Point(0, 1), new Point(0, 2), new Point(0, 3), new Point(0, 4), new Point(0, 5));
41+
assertEquals(expected, line);
42+
}
43+
44+
/**
45+
* Tests the generation of a diagonal line from (0, 0) to (5, 5).
46+
* Asserts that the generated line matches the expected list of points.
47+
*/
48+
@Test
49+
void testDiagonalLine() {
50+
List<Point> line = bresenhamLine.findLine(0, 0, 5, 5);
51+
List<Point> expected = List.of(new Point(0, 0), new Point(1, 1), new Point(2, 2), new Point(3, 3), new Point(4, 4), new Point(5, 5));
52+
assertEquals(expected, line);
53+
}
54+
55+
/**
56+
* Tests the generation of a diagonal line with a negative slope from (5, 5) to (0, 0).
57+
* Asserts that the generated line matches the expected list of points.
58+
*/
59+
@Test
60+
void testNegativeSlopeDiagonal() {
61+
List<Point> line = bresenhamLine.findLine(5, 5, 0, 0);
62+
List<Point> expected = List.of(new Point(5, 5), new Point(4, 4), new Point(3, 3), new Point(2, 2), new Point(1, 1), new Point(0, 0));
63+
assertEquals(expected, line);
64+
}
65+
66+
/**
67+
* Tests the generation of a steep vertical line from (1, 1) to (1, 4).
68+
* Asserts that the generated line matches the expected list of points.
69+
*/
70+
@Test
71+
void testSteepDiagonal() {
72+
List<Point> line = bresenhamLine.findLine(1, 1, 1, 4);
73+
List<Point> expected = List.of(new Point(1, 1), new Point(1, 2), new Point(1, 3), new Point(1, 4));
74+
assertEquals(expected, line);
75+
}
76+
77+
/**
78+
* Tests the generation of a diagonal line with negative coordinates from (-3,-3) to (-1,-1).
79+
* Asserts that the generated line matches the expected list of points.
80+
*/
81+
@Test
82+
void testMixedCoordinates() {
83+
List<Point> line = bresenhamLine.findLine(-3, -3, -1, -1);
84+
List<Point> expected = List.of(new Point(-3, -3), new Point(-2, -2), new Point(-1, -1));
85+
assertEquals(expected, line);
86+
}
87+
}

0 commit comments

Comments
 (0)