diff --git a/src/main/java/com/thealgorithms/geometry/BresenhamLine.java b/src/main/java/com/thealgorithms/geometry/BresenhamLine.java deleted file mode 100644 index 51d9930c0250..000000000000 --- a/src/main/java/com/thealgorithms/geometry/BresenhamLine.java +++ /dev/null @@ -1,69 +0,0 @@ -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. - * - *

This algorithm uses integer arithmetic to calculate the points, - * making it suitable for rasterization in computer graphics.

- * - * For more information, please visit {@link https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm} - */ -public final class BresenhamLine { - - private BresenhamLine() { - // Private constructor to prevent instantiation. - } - - /** - * 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} containing all points on the line - */ - public static List findLine(int x0, int y0, int x1, int y1) { - List 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 - final 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 - } -} diff --git a/src/main/java/com/thealgorithms/geometry/BresenhamLineStrategy.java b/src/main/java/com/thealgorithms/geometry/BresenhamLineStrategy.java new file mode 100644 index 000000000000..0a954e23b693 --- /dev/null +++ b/src/main/java/com/thealgorithms/geometry/BresenhamLineStrategy.java @@ -0,0 +1,38 @@ +package com.thealgorithms.geometry; + +import java.awt.Point; +import java.util.ArrayList; +import java.util.List; + +public class BresenhamLineStrategy implements LineDrawingStrategy { + + @Override + public List findLine(int x0, int y0, int x1, int y1) { + List line = new ArrayList<>(); + + int dx = Math.abs(x1 - x0); + int dy = Math.abs(y1 - y0); + int sx = (x0 < x1) ? 1 : -1; + int sy = (y0 < y1) ? 1 : -1; + int err = dx - dy; + + while (true) { + line.add(new Point(x0, y0)); + if (x0 == x1 && y0 == y1) { + break; + } + int e2 = err * 2; + + if (e2 > -dy) { + err -= dy; + x0 += sx; + } + if (e2 < dx) { + err += dx; + y0 += sy; + } + } + + return line; + } +} diff --git a/src/main/java/com/thealgorithms/geometry/LineDrawer.java b/src/main/java/com/thealgorithms/geometry/LineDrawer.java new file mode 100644 index 000000000000..df60002b13c6 --- /dev/null +++ b/src/main/java/com/thealgorithms/geometry/LineDrawer.java @@ -0,0 +1,20 @@ +package com.thealgorithms.geometry; + +import java.awt.Point; +import java.util.List; + +public class LineDrawer { + private LineDrawingStrategy strategy; + + public LineDrawer(LineDrawingStrategy strategy) { + this.strategy = strategy; + } + + public void setStrategy(LineDrawingStrategy strategy) { + this.strategy = strategy; + } + + public List drawLine(int x0, int y0, int x1, int y1) { + return strategy.findLine(x0, y0, x1, y1); + } +} diff --git a/src/main/java/com/thealgorithms/geometry/LineDrawingStrategy.java b/src/main/java/com/thealgorithms/geometry/LineDrawingStrategy.java new file mode 100644 index 000000000000..8c2aa48a2f5b --- /dev/null +++ b/src/main/java/com/thealgorithms/geometry/LineDrawingStrategy.java @@ -0,0 +1,8 @@ +package com.thealgorithms.geometry; + +import java.awt.Point; +import java.util.List; + +public interface LineDrawingStrategy { + List findLine(int x0, int y0, int x1, int y1); +} diff --git a/src/test/java/com/thealgorithms/geometry/BresenhamLineTest.java b/src/test/java/com/thealgorithms/geometry/BresenhamLineTest.java deleted file mode 100644 index 9df308497ddf..000000000000 --- a/src/test/java/com/thealgorithms/geometry/BresenhamLineTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.thealgorithms.geometry; - -import java.awt.Point; -import java.util.Collection; -import java.util.List; -import java.util.stream.Stream; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; - -/** - * The {@code BresenhamLineTest} class contains unit tests for the - * {@code BresenhamLine} class, specifically testing the - * {@code findLine} method. - * - *

This class uses parameterized tests to validate the output of - * Bresenham's line algorithm for various input points.

- */ -class BresenhamLineTest { - - /** - * Provides test cases for the parameterized test. - * - *

Each test case includes starting coordinates, ending coordinates, - * and the expected collection of points that should be generated by the - * {@code findLine} method.

- * - * @return a stream of arguments containing test cases - */ - static Stream linePointsProvider() { - return Stream.of(Arguments.of(0, 0, 5, 5, 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))), Arguments.of(0, 0, 5, 0, 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))), - Arguments.of(0, 0, 0, 5, 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))), Arguments.of(-2, -2, -5, -5, List.of(new Point(-2, -2), new Point(-3, -3), new Point(-4, -4), new Point(-5, -5))), - Arguments.of(-1, -1, 2, 2, List.of(new Point(-1, -1), new Point(0, 0), new Point(1, 1), new Point(2, 2))), Arguments.of(2, -1, -1, -4, List.of(new Point(2, -1), new Point(1, -2), new Point(0, -3), new Point(-1, -4)))); - } - - /** - * Tests the {@code findLine} method of the {@code BresenhamLine} class. - * - *

This parameterized test runs multiple times with different sets of - * starting and ending coordinates to validate that the generated points - * match the expected output.

- * - * @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 - * @param expected a collection of expected points that should form a line - */ - @ParameterizedTest - @MethodSource("linePointsProvider") - void testFindLine(int x0, int y0, int x1, int y1, Collection expected) { - List actual = BresenhamLine.findLine(x0, y0, x1, y1); - Assertions.assertEquals(expected.size(), actual.size(), "The size of the points list should match."); - Assertions.assertTrue(expected.containsAll(actual) && actual.containsAll(expected), "The points generated should match the expected points."); - } -} diff --git a/src/test/java/com/thealgorithms/geometry/LineDrawerTest.java b/src/test/java/com/thealgorithms/geometry/LineDrawerTest.java new file mode 100644 index 000000000000..5e7f304a9790 --- /dev/null +++ b/src/test/java/com/thealgorithms/geometry/LineDrawerTest.java @@ -0,0 +1,57 @@ +package com.thealgorithms.geometry; + +import java.awt.Point; +import java.util.Collection; +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +/** + * Unit tests for the LineDrawer using BresenhamLineStrategy. + */ +class LineDrawerTest { + + /** + * Provides test data for drawing lines using the Bresenham algorithm. + */ + static Stream linePointsProvider() { + return Stream.of(Arguments.of(0, 0, 5, 5, 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))), Arguments.of(0, 0, 5, 0, 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))), + Arguments.of(0, 0, 0, 5, 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))), Arguments.of(-2, -2, -5, -5, List.of(new Point(-2, -2), new Point(-3, -3), new Point(-4, -4), new Point(-5, -5))), + Arguments.of(-1, -1, 2, 2, List.of(new Point(-1, -1), new Point(0, 0), new Point(1, 1), new Point(2, 2))), Arguments.of(2, -1, -1, -4, List.of(new Point(2, -1), new Point(1, -2), new Point(0, -3), new Point(-1, -4)))); + } + + /** + * Tests line drawing using the BresenhamLineStrategy through LineDrawer. + */ + @ParameterizedTest + @MethodSource("linePointsProvider") + void testLineDrawingWithBresenhamStrategy(int x0, int y0, int x1, int y1, Collection expected) { + LineDrawingStrategy strategy = new BresenhamLineStrategy(); + LineDrawer drawer = new LineDrawer(strategy); + + List actual = drawer.drawLine(x0, y0, x1, y1); + + Assertions.assertEquals(expected.size(), actual.size(), "Points count mismatch."); + Assertions.assertTrue(expected.containsAll(actual) && actual.containsAll(expected), "Generated points do not match expected points."); + } + + /** + * Demonstrates dynamic strategy switching. + */ + @ParameterizedTest + @MethodSource("linePointsProvider") + void testSetStrategyDynamicSwitch(int x0, int y0, int x1, int y1, Collection expected) { + LineDrawer drawer = new LineDrawer(new BresenhamLineStrategy()); + + // Simulate switching strategy at runtime (e.g., in future: drawer.setStrategy(new DdaLineStrategy())) + drawer.setStrategy(new BresenhamLineStrategy()); // No-op here but shows extensibility + + List actual = drawer.drawLine(x0, y0, x1, y1); + + Assertions.assertEquals(expected.size(), actual.size(), "Point count mismatch after strategy switch."); + Assertions.assertTrue(expected.containsAll(actual) && actual.containsAll(expected), "Generated points do not match expected points after strategy switch."); + } +}