Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions src/main/java/com/thealgorithms/geometry/BresenhamLine.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.thealgorithms.geometry;

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

/**
* The {@code BresenhamLine} class implements the Bresenham's line algorithm,
* which is an efficient way to determine the points of a straight line
* between two given points in a 2D space.
*
* <p>This algorithm uses integer arithmetic to calculate the points,
* making it suitable for rasterization in computer graphics.</p>
*
* For more information, please visit {@link https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm}
*/
public final class BresenhamLine {

/**
* Finds the list of points that form a straight line between two endpoints.
*
* @param x0 the x-coordinate of the starting point
* @param y0 the y-coordinate of the starting point
* @param x1 the x-coordinate of the ending point
* @param y1 the y-coordinate of the ending point
* @return a {@code List<Point>} containing all points on the line
*/
public List<Point> findLine(int x0, int y0, int x1, int y1) {
List<Point> line = new ArrayList<>();

// Calculate differences and steps for each axis
int dx = Math.abs(x1 - x0); // Change in x
int dy = Math.abs(y1 - y0); // Change in y
int sx = (x0 < x1) ? 1 : -1; // Step in x direction
int sy = (y0 < y1) ? 1 : -1; // Step in y direction
int err = dx - dy; // Initial error term

// Loop until we reach the endpoint
while (true) {
line.add(new Point(x0, y0)); // Add current point to the line

// Check if we've reached the endpoint
if (x0 == x1 && y0 == y1) {
break; // Exit loop if endpoint is reached
}

// Calculate error term doubled for decision making
int e2 = err * 2;

// Adjust x coordinate if necessary
if (e2 > -dy) {
err -= dy; // Update error term
x0 += sx; // Move to next point in x direction
}

// Adjust y coordinate if necessary
if (e2 < dx) {
err += dx; // Update error term
y0 += sy; // Move to next point in y direction
}
}

return line; // Return the list of points forming the line
}
}
87 changes: 87 additions & 0 deletions src/test/java/com/thealgorithms/geometry/BresenhamLineTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package com.thealgorithms.geometry;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.awt.Point;
import java.util.List;
import org.junit.jupiter.api.Test;

/**
* The {@code BresenhamLineTest} class contains unit tests for the {@code BresenhamLine} class.
* It verifies the correctness of the findLine method, which generates a list of points
* representing a straight line between two specified endpoints.
*
* <p>This test class uses JUnit 5 for testing and covers various scenarios including horizontal,
* vertical, and diagonal lines, as well as lines with negative coordinates.</p>
*/
class BresenhamLineTest {

// Instance of BresenhamLine to be tested
private final BresenhamLine bresenhamLine = new BresenhamLine();

/**
* Tests the generation of a horizontal line from (0, 0) to (5, 0).
* Asserts that the generated line matches the expected list of points.
*/
@Test
void testHorizontalLine() {
List<Point> line = bresenhamLine.findLine(0, 0, 5, 0);
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));
assertEquals(expected, line);
}

/**
* Tests the generation of a vertical line from (0, 0) to (0, 5).
* Asserts that the generated line matches the expected list of points.
*/
@Test
void testVerticalLine() {
List<Point> line = bresenhamLine.findLine(0, 0, 0, 5);
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));
assertEquals(expected, line);
}

/**
* Tests the generation of a diagonal line from (0, 0) to (5, 5).
* Asserts that the generated line matches the expected list of points.
*/
@Test
void testDiagonalLine() {
List<Point> line = bresenhamLine.findLine(0, 0, 5, 5);
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));
assertEquals(expected, line);
}

/**
* Tests the generation of a diagonal line with a negative slope from (5, 5) to (0, 0).
* Asserts that the generated line matches the expected list of points.
*/
@Test
void testNegativeSlopeDiagonal() {
List<Point> line = bresenhamLine.findLine(5, 5, 0, 0);
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));
assertEquals(expected, line);
}

/**
* Tests the generation of a steep vertical line from (1, 1) to (1, 4).
* Asserts that the generated line matches the expected list of points.
*/
@Test
void testSteepDiagonal() {
List<Point> line = bresenhamLine.findLine(1, 1, 1, 4);
List<Point> expected = List.of(new Point(1, 1), new Point(1, 2), new Point(1, 3), new Point(1, 4));
assertEquals(expected, line);
}

/**
* Tests the generation of a diagonal line with negative coordinates from (-3,-3) to (-1,-1).
* Asserts that the generated line matches the expected list of points.
*/
@Test
void testMixedCoordinates() {
List<Point> line = bresenhamLine.findLine(-3, -3, -1, -1);
List<Point> expected = List.of(new Point(-3, -3), new Point(-2, -2), new Point(-1, -1));
assertEquals(expected, line);
}
}