From 54a5d8466378b501b3876bbaeb47a31ca7304de9 Mon Sep 17 00:00:00 2001 From: Vasheel Date: Wed, 5 Jun 2024 14:08:52 +0400 Subject: [PATCH 01/10] implementation of Bresenham circle algorithm and tests --- .../creme332/algorithms/CircleAlgorithm.java | 49 ++++++++++++++++ .../tests/algorithms/CircleAlgorithmTest.java | 58 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java create mode 100644 src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java diff --git a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java new file mode 100644 index 00000000..d2267975 --- /dev/null +++ b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java @@ -0,0 +1,49 @@ +package com.github.creme332.algorithms; + +public class CircleAlgorithm { + + public static int[][] drawCircle(int centerX, int centerY, int radius) { + if (radius < 0) { + throw new IllegalArgumentException("Radius cannot be negative"); + } + + int diameter = 2 * radius + 1; + int[][] pixels = new int[diameter][diameter]; + + int x = radius; + int y = 0; + int decisionParameter = 1 - radius; + + while (x >= y) { + plotCirclePoints(pixels, centerX, centerY, x, y); + y++; + + if (decisionParameter <= 0) { + decisionParameter += 2 * y + 1; + } else { + x--; + decisionParameter += 2 * (y - x) + 1; + } + } + + return pixels; + } + + private static void plotCirclePoints(int[][] pixels, int centerX, int centerY, int x, int y) { + int diameter = pixels.length; + plotPoint(pixels, centerX + x, centerY + y, diameter); + plotPoint(pixels, centerX - x, centerY + y, diameter); + plotPoint(pixels, centerX + x, centerY - y, diameter); + plotPoint(pixels, centerX - x, centerY - y, diameter); + plotPoint(pixels, centerX + y, centerY + x, diameter); + plotPoint(pixels, centerX - y, centerY + x, diameter); + plotPoint(pixels, centerX + y, centerY - x, diameter); + plotPoint(pixels, centerX - y, centerY - x, diameter); + } + + private static void plotPoint(int[][] pixels, int x, int y, int diameter) { + if (x >= 0 && x < diameter && y >= 0 && y < diameter) { + pixels[x][y] = 1; + } + } +} diff --git a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java new file mode 100644 index 00000000..cb75fb04 --- /dev/null +++ b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java @@ -0,0 +1,58 @@ +package com.github.creme332.tests.algorithms; + +import org.junit.Test; + +import static org.junit.Assert.*; +import com.github.creme332.algorithms.CircleAlgorithm; + +public class CircleAlgorithmTest { + + @Test + public void testDrawCircle_positiveRadius() { + int centerX = 5; + int centerY = 5; + int radius = 5; + int[][] pixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); + + assertEquals(2 * radius + 1, pixels.length); // Check array size + assertEquals(2 * radius + 1, pixels[0].length); + + int[][] expectedPixels = new int[][] { + {0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1}, + {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1}, + {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1}, + {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, + {0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0} + }; + + for (int i = 0; i < pixels.length; i++) { + assertArrayEquals(expectedPixels[i], pixels[i]); + } + } + + @Test + public void testDrawCircle_zeroRadius() { + int centerX = 0; + int centerY = 0; + int radius = 0; + int[][] pixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); + + assertEquals(1, pixels.length); // Single pixel for radius 0 + assertEquals(1, pixels[0].length); + assertTrue(pixels[0][0] == 1); // Check center pixel + } + + @Test(expected = IllegalArgumentException.class) + public void testDrawCircle_negativeRadius() { + int centerX = 0; + int centerY = 0; + int radius = -5; + CircleAlgorithm.drawCircle(centerX, centerY, radius); + } +} From 803faf867a50736b5c57fe9f6a36e4659aeffca7 Mon Sep 17 00:00:00 2001 From: Vasheel Date: Fri, 7 Jun 2024 10:11:40 +0400 Subject: [PATCH 02/10] for CircleAlgorithm, return an array of pixel coordinates and try to debug "testDrawCircle_positiveRadius" but fails --- .../creme332/algorithms/CircleAlgorithm.java | 35 ++++++------- .../tests/algorithms/CircleAlgorithmTest.java | 50 +++++++++++-------- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java index d2267975..c77eadcd 100644 --- a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java +++ b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java @@ -1,5 +1,8 @@ package com.github.creme332.algorithms; +import java.util.ArrayList; +import java.util.List; + public class CircleAlgorithm { public static int[][] drawCircle(int centerX, int centerY, int radius) { @@ -7,15 +10,14 @@ public static int[][] drawCircle(int centerX, int centerY, int radius) { throw new IllegalArgumentException("Radius cannot be negative"); } - int diameter = 2 * radius + 1; - int[][] pixels = new int[diameter][diameter]; + List pixelList = new ArrayList<>(); int x = radius; int y = 0; int decisionParameter = 1 - radius; while (x >= y) { - plotCirclePoints(pixels, centerX, centerY, x, y); + plotCirclePoints(pixelList, centerX, centerY, x, y); y++; if (decisionParameter <= 0) { @@ -26,24 +28,17 @@ public static int[][] drawCircle(int centerX, int centerY, int radius) { } } - return pixels; - } - - private static void plotCirclePoints(int[][] pixels, int centerX, int centerY, int x, int y) { - int diameter = pixels.length; - plotPoint(pixels, centerX + x, centerY + y, diameter); - plotPoint(pixels, centerX - x, centerY + y, diameter); - plotPoint(pixels, centerX + x, centerY - y, diameter); - plotPoint(pixels, centerX - x, centerY - y, diameter); - plotPoint(pixels, centerX + y, centerY + x, diameter); - plotPoint(pixels, centerX - y, centerY + x, diameter); - plotPoint(pixels, centerX + y, centerY - x, diameter); - plotPoint(pixels, centerX - y, centerY - x, diameter); + return pixelList.toArray(new int[pixelList.size()][]); } - private static void plotPoint(int[][] pixels, int x, int y, int diameter) { - if (x >= 0 && x < diameter && y >= 0 && y < diameter) { - pixels[x][y] = 1; - } + private static void plotCirclePoints(List pixelList, int centerX, int centerY, int x, int y) { + pixelList.add(new int[]{centerX + x, centerY + y}); + pixelList.add(new int[]{centerX - x, centerY + y}); + pixelList.add(new int[]{centerX + x, centerY - y}); + pixelList.add(new int[]{centerX - x, centerY - y}); + pixelList.add(new int[]{centerX + y, centerY + x}); + pixelList.add(new int[]{centerX - y, centerY + x}); + pixelList.add(new int[]{centerX + y, centerY - x}); + pixelList.add(new int[]{centerX - y, centerY - x}); } } diff --git a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java index cb75fb04..6264edb2 100644 --- a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java +++ b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java @@ -1,6 +1,9 @@ package com.github.creme332.tests.algorithms; import org.junit.Test; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; import static org.junit.Assert.*; import com.github.creme332.algorithms.CircleAlgorithm; @@ -14,26 +17,32 @@ public void testDrawCircle_positiveRadius() { int radius = 5; int[][] pixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); - assertEquals(2 * radius + 1, pixels.length); // Check array size - assertEquals(2 * radius + 1, pixels[0].length); - - int[][] expectedPixels = new int[][] { - {0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0}, - {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0}, - {0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1}, - {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, - {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1}, - {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1}, - {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1}, - {1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1}, - {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1}, - {0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0}, - {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0} - }; - - for (int i = 0; i < pixels.length; i++) { - assertArrayEquals(expectedPixels[i], pixels[i]); + Set expectedPixels = new HashSet<>(Arrays.asList( + "[10, 5]", "[5, 10]", "[0, 5]", "[5, 0]", + "[9, 6]", "[6, 9]", "[1, 6]", "[6, 1]", + "[8, 7]", "[7, 8]", "[2, 7]", "[7, 2]", + "[8, 3]", "[7, 4]", "[2, 3]", "[7, 6]", + "[8, 1]", "[7, 0]", "[2, 1]", "[7, 10]", + "[9, 4]", "[6, 5]", "[1, 4]", "[6, 10]", + "[10, 6]", "[5, 9]", "[0, 6]", "[5, 1]", + "[10, 4]", "[5, 7]", "[0, 4]", "[5, 3]" + )); + + Set actualPixels = new HashSet<>(); + for (int[] pixel : pixels) { + actualPixels.add(Arrays.toString(pixel)); + } + + // Debugging output for easier comparison + if (!expectedPixels.equals(actualPixels)) { + System.out.println("Expected Pixels: " + expectedPixels); + System.out.println("Actual Pixels: " + actualPixels); + for (int[] pixel : pixels) { + System.out.println(Arrays.toString(pixel)); + } } + + assertEquals(expectedPixels, actualPixels); } @Test @@ -44,8 +53,7 @@ public void testDrawCircle_zeroRadius() { int[][] pixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); assertEquals(1, pixels.length); // Single pixel for radius 0 - assertEquals(1, pixels[0].length); - assertTrue(pixels[0][0] == 1); // Check center pixel + assertArrayEquals(new int[]{0, 0}, pixels[0]); // Check center pixel } @Test(expected = IllegalArgumentException.class) From b9273378cccdb1d13e2244075ef5bd698ae01a0f Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Fri, 7 Jun 2024 19:40:59 +0400 Subject: [PATCH 03/10] rewrite testDrawCircle_positiveRadius with a valid expectedPixels --- .../tests/algorithms/CircleAlgorithmTest.java | 66 +++++++++---------- 1 file changed, 32 insertions(+), 34 deletions(-) diff --git a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java index 6264edb2..bb5d27ca 100644 --- a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java +++ b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java @@ -1,9 +1,6 @@ package com.github.creme332.tests.algorithms; import org.junit.Test; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; import static org.junit.Assert.*; import com.github.creme332.algorithms.CircleAlgorithm; @@ -12,37 +9,38 @@ public class CircleAlgorithmTest { @Test public void testDrawCircle_positiveRadius() { - int centerX = 5; - int centerY = 5; - int radius = 5; - int[][] pixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); + int centerX = 0; + int centerY = 0; + int radius = 10; + int[][] actualPixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); + + int[][] expectedPixels = { + // Octant 1: (x, y) + { 0, 10 }, { 1, 10 }, { 2, 10 }, { 3, 10 }, { 4, 9 }, { 5, 9 }, { 6, 8 }, { 7, 7 }, + + // Octant 2: (y, x) + { 10, 0 }, { 10, 1 }, { 10, 2 }, { 10, 3 }, { 9, 4 }, { 9, 5 }, { 8, 6 }, + + // Octant 3: (y, -x) + { 10, -1 }, { 10, -2 }, { 10, -3 }, { 9, -4 }, { 9, -5 }, { 8, -6 }, { 7, -7 }, + + // Octant 4: (x, -y) + { 0, -10 }, { 1, -10 }, { 2, -10 }, { 3, -10 }, { 4, -9 }, { 5, -9 }, { 6, -8 }, + + // Octant 5: (-x, -y) + { -1, -10 }, { -2, -10 }, { -3, -10 }, { -4, -9 }, { -5, -9 }, { -6, -8 }, { -7, -7 }, + + // Octant 6: (-y, -x) + { -10, 0 }, { -10, -1 }, { -10, -2 }, { -10, -3 }, { -9, -4 }, { -9, -5 }, { -8, -6 }, + + // Octant 7: (-y, x) + { -10, 1 }, { -10, 2 }, { -10, 3 }, { -9, 4 }, { -9, 5 }, { -8, 6 }, { -7, 7 }, + + // Octant 8: (-x, y) + { -1, 10 }, { -2, 10 }, { -3, 10 }, { -4, 9 }, { -5, 9 }, { -6, 8 }, + }; - Set expectedPixels = new HashSet<>(Arrays.asList( - "[10, 5]", "[5, 10]", "[0, 5]", "[5, 0]", - "[9, 6]", "[6, 9]", "[1, 6]", "[6, 1]", - "[8, 7]", "[7, 8]", "[2, 7]", "[7, 2]", - "[8, 3]", "[7, 4]", "[2, 3]", "[7, 6]", - "[8, 1]", "[7, 0]", "[2, 1]", "[7, 10]", - "[9, 4]", "[6, 5]", "[1, 4]", "[6, 10]", - "[10, 6]", "[5, 9]", "[0, 6]", "[5, 1]", - "[10, 4]", "[5, 7]", "[0, 4]", "[5, 3]" - )); - - Set actualPixels = new HashSet<>(); - for (int[] pixel : pixels) { - actualPixels.add(Arrays.toString(pixel)); - } - - // Debugging output for easier comparison - if (!expectedPixels.equals(actualPixels)) { - System.out.println("Expected Pixels: " + expectedPixels); - System.out.println("Actual Pixels: " + actualPixels); - for (int[] pixel : pixels) { - System.out.println(Arrays.toString(pixel)); - } - } - - assertEquals(expectedPixels, actualPixels); + assertArrayEquals(expectedPixels, actualPixels); } @Test @@ -53,7 +51,7 @@ public void testDrawCircle_zeroRadius() { int[][] pixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); assertEquals(1, pixels.length); // Single pixel for radius 0 - assertArrayEquals(new int[]{0, 0}, pixels[0]); // Check center pixel + assertArrayEquals(new int[] { 0, 0 }, pixels[0]); // Check center pixel } @Test(expected = IllegalArgumentException.class) From 3669036d6a336eaf33841a49ef664ed464397f56 Mon Sep 17 00:00:00 2001 From: Vasheel Date: Mon, 10 Jun 2024 12:43:22 +0400 Subject: [PATCH 04/10] remove duplicates & use the new method TestHelper.assert2DArrayEquals --- .../creme332/algorithms/CircleAlgorithm.java | 57 ++++++++++++------- .../tests/algorithms/CircleAlgorithmTest.java | 16 +++--- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java index c77eadcd..f03fdb56 100644 --- a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java +++ b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java @@ -12,19 +12,23 @@ public static int[][] drawCircle(int centerX, int centerY, int radius) { List pixelList = new ArrayList<>(); - int x = radius; - int y = 0; - int decisionParameter = 1 - radius; - - while (x >= y) { - plotCirclePoints(pixelList, centerX, centerY, x, y); - y++; - - if (decisionParameter <= 0) { - decisionParameter += 2 * y + 1; - } else { - x--; - decisionParameter += 2 * (y - x) + 1; + if (radius == 0) { + pixelList.add(new int[] { centerX, centerY }); + } else { + int x = radius; + int y = 0; + int decisionParameter = 1 - radius; + + while (x >= y) { + plotCirclePoints(pixelList, centerX, centerY, x, y); + y++; + + if (decisionParameter <= 0) { + decisionParameter += 2 * y + 1; + } else { + x--; + decisionParameter += 2 * (y - x) + 1; + } } } @@ -32,13 +36,22 @@ public static int[][] drawCircle(int centerX, int centerY, int radius) { } private static void plotCirclePoints(List pixelList, int centerX, int centerY, int x, int y) { - pixelList.add(new int[]{centerX + x, centerY + y}); - pixelList.add(new int[]{centerX - x, centerY + y}); - pixelList.add(new int[]{centerX + x, centerY - y}); - pixelList.add(new int[]{centerX - x, centerY - y}); - pixelList.add(new int[]{centerX + y, centerY + x}); - pixelList.add(new int[]{centerX - y, centerY + x}); - pixelList.add(new int[]{centerX + y, centerY - x}); - pixelList.add(new int[]{centerX - y, centerY - x}); + addUniquePixel(pixelList, centerX + x, centerY + y); + addUniquePixel(pixelList, centerX - x, centerY + y); + addUniquePixel(pixelList, centerX + x, centerY - y); + addUniquePixel(pixelList, centerX - x, centerY - y); + addUniquePixel(pixelList, centerX + y, centerY + x); + addUniquePixel(pixelList, centerX - y, centerY + x); + addUniquePixel(pixelList, centerX + y, centerY - x); + addUniquePixel(pixelList, centerX - y, centerY - x); } -} + + private static void addUniquePixel(List pixelList, int x, int y) { + for (int[] pixel : pixelList) { + if (pixel[0] == x && pixel[1] == y) { + return; // Pixel already exists, don't add it again + } + } + pixelList.add(new int[] { x, y }); + } +} \ No newline at end of file diff --git a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java index bb5d27ca..39468b6b 100644 --- a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java +++ b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java @@ -1,9 +1,10 @@ package com.github.creme332.tests.algorithms; import org.junit.Test; +import com.github.creme332.algorithms.CircleAlgorithm; +import com.github.creme332.tests.utils.TestHelper; import static org.junit.Assert.*; -import com.github.creme332.algorithms.CircleAlgorithm; public class CircleAlgorithmTest { @@ -17,30 +18,27 @@ public void testDrawCircle_positiveRadius() { int[][] expectedPixels = { // Octant 1: (x, y) { 0, 10 }, { 1, 10 }, { 2, 10 }, { 3, 10 }, { 4, 9 }, { 5, 9 }, { 6, 8 }, { 7, 7 }, - // Octant 2: (y, x) { 10, 0 }, { 10, 1 }, { 10, 2 }, { 10, 3 }, { 9, 4 }, { 9, 5 }, { 8, 6 }, - // Octant 3: (y, -x) { 10, -1 }, { 10, -2 }, { 10, -3 }, { 9, -4 }, { 9, -5 }, { 8, -6 }, { 7, -7 }, - // Octant 4: (x, -y) { 0, -10 }, { 1, -10 }, { 2, -10 }, { 3, -10 }, { 4, -9 }, { 5, -9 }, { 6, -8 }, - // Octant 5: (-x, -y) { -1, -10 }, { -2, -10 }, { -3, -10 }, { -4, -9 }, { -5, -9 }, { -6, -8 }, { -7, -7 }, - // Octant 6: (-y, -x) { -10, 0 }, { -10, -1 }, { -10, -2 }, { -10, -3 }, { -9, -4 }, { -9, -5 }, { -8, -6 }, - // Octant 7: (-y, x) { -10, 1 }, { -10, 2 }, { -10, 3 }, { -9, 4 }, { -9, 5 }, { -8, 6 }, { -7, 7 }, - // Octant 8: (-x, y) { -1, 10 }, { -2, 10 }, { -3, 10 }, { -4, 9 }, { -5, 9 }, { -6, 8 }, }; - assertArrayEquals(expectedPixels, actualPixels); + // Debugging with detailed output + TestHelper.compare2DArraysDebug(expectedPixels, actualPixels); + + // Using the helper method for assertion + TestHelper.assert2DArrayEquals(expectedPixels, actualPixels); } @Test From 43f40981b81861d78747ecefdaf1152011c259a8 Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:48:34 +0400 Subject: [PATCH 05/10] fix issues - remove loop in addUniquePixel - swap x and y variables - add private constructor - throw exception for zero radius --- .../creme332/algorithms/CircleAlgorithm.java | 68 +++++++++++-------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java index f03fdb56..927c47e7 100644 --- a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java +++ b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java @@ -5,30 +5,30 @@ public class CircleAlgorithm { + private CircleAlgorithm() { + + } + public static int[][] drawCircle(int centerX, int centerY, int radius) { - if (radius < 0) { - throw new IllegalArgumentException("Radius cannot be negative"); + if (radius <= 0) { + throw new IllegalArgumentException("Radius must be positive"); } List pixelList = new ArrayList<>(); - if (radius == 0) { - pixelList.add(new int[] { centerX, centerY }); - } else { - int x = radius; - int y = 0; - int decisionParameter = 1 - radius; - - while (x >= y) { - plotCirclePoints(pixelList, centerX, centerY, x, y); - y++; - - if (decisionParameter <= 0) { - decisionParameter += 2 * y + 1; - } else { - x--; - decisionParameter += 2 * (y - x) + 1; - } + int x = 0; + int y = radius; + int decisionParameter = 1 - radius; + + while (y >= x) { + plotCirclePoints(pixelList, centerX, centerY, x, y); + x++; + + if (decisionParameter <= 0) { + decisionParameter += 2 * x + 1; + } else { + y--; + decisionParameter += 2 * (x - y) + 1; } } @@ -36,22 +36,34 @@ public static int[][] drawCircle(int centerX, int centerY, int radius) { } private static void plotCirclePoints(List pixelList, int centerX, int centerY, int x, int y) { - addUniquePixel(pixelList, centerX + x, centerY + y); - addUniquePixel(pixelList, centerX - x, centerY + y); - addUniquePixel(pixelList, centerX + x, centerY - y); - addUniquePixel(pixelList, centerX - x, centerY - y); + if (y == 0) { + addUniquePixel(pixelList, centerX + y, centerY + x); + addUniquePixel(pixelList, centerX + x, centerY + y); + addUniquePixel(pixelList, centerX + y, centerY - x); + addUniquePixel(pixelList, centerX - x, centerY + y); + return; + } + + if (y == x) { + addUniquePixel(pixelList, centerX + y, centerY + x); + addUniquePixel(pixelList, centerX - y, centerY + x); + addUniquePixel(pixelList, centerX + y, centerY - x); + addUniquePixel(pixelList, centerX - y, centerY - x); + return; + } + addUniquePixel(pixelList, centerX + y, centerY + x); addUniquePixel(pixelList, centerX - y, centerY + x); addUniquePixel(pixelList, centerX + y, centerY - x); addUniquePixel(pixelList, centerX - y, centerY - x); + + addUniquePixel(pixelList, centerX + x, centerY + y); + addUniquePixel(pixelList, centerX - x, centerY + y); + addUniquePixel(pixelList, centerX + x, centerY - y); + addUniquePixel(pixelList, centerX - x, centerY - y); } private static void addUniquePixel(List pixelList, int x, int y) { - for (int[] pixel : pixelList) { - if (pixel[0] == x && pixel[1] == y) { - return; // Pixel already exists, don't add it again - } - } pixelList.add(new int[] { x, y }); } } \ No newline at end of file From f0119ce7a62a2c01d4287fc4aabe3ba146f940e8 Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:49:55 +0400 Subject: [PATCH 06/10] rename tests, assert exception message is correct where appropriate --- .../tests/algorithms/CircleAlgorithmTest.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java index 39468b6b..02cf1718 100644 --- a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java +++ b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java @@ -9,7 +9,7 @@ public class CircleAlgorithmTest { @Test - public void testDrawCircle_positiveRadius() { + public void testValidCircleCenteredOrigin() { int centerX = 0; int centerY = 0; int radius = 10; @@ -34,29 +34,34 @@ public void testDrawCircle_positiveRadius() { { -1, 10 }, { -2, 10 }, { -3, 10 }, { -4, 9 }, { -5, 9 }, { -6, 8 }, }; - // Debugging with detailed output - TestHelper.compare2DArraysDebug(expectedPixels, actualPixels); - // Using the helper method for assertion TestHelper.assert2DArrayEquals(expectedPixels, actualPixels); } @Test - public void testDrawCircle_zeroRadius() { + public void testZeroRadiusCenteredOrigin() { int centerX = 0; int centerY = 0; int radius = 0; - int[][] pixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); - assertEquals(1, pixels.length); // Single pixel for radius 0 - assertArrayEquals(new int[] { 0, 0 }, pixels[0]); // Check center pixel + try { + CircleAlgorithm.drawCircle(centerX, centerY, radius); + fail("Expected IllegalArgumentException for zero radii"); + } catch (IllegalArgumentException e) { + assertEquals("Radius must be positive", e.getMessage()); + } } - @Test(expected = IllegalArgumentException.class) - public void testDrawCircle_negativeRadius() { + @Test + public void testNegativeRadiusCenteredOrigin() { int centerX = 0; int centerY = 0; int radius = -5; - CircleAlgorithm.drawCircle(centerX, centerY, radius); + try { + CircleAlgorithm.drawCircle(centerX, centerY, radius); + fail("Expected IllegalArgumentException for negative radii"); + } catch (IllegalArgumentException e) { + assertEquals("Radius must be positive", e.getMessage()); + } } } From 7e728395cf1985ba861a59a1dea967ffa086a348 Mon Sep 17 00:00:00 2001 From: Vasheel Date: Mon, 10 Jun 2024 15:55:49 +0400 Subject: [PATCH 07/10] add test testCircleCenteredOriginRadiusOne and testCircleNotCenteredOriginRadiusOne but it fails --- .../algorithms/EllipseAlgorithmTest.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/test/java/com/github/creme332/tests/algorithms/EllipseAlgorithmTest.java b/src/test/java/com/github/creme332/tests/algorithms/EllipseAlgorithmTest.java index 9cceb404..c5710a1d 100644 --- a/src/test/java/com/github/creme332/tests/algorithms/EllipseAlgorithmTest.java +++ b/src/test/java/com/github/creme332/tests/algorithms/EllipseAlgorithmTest.java @@ -2,6 +2,8 @@ import org.junit.Test; import static org.junit.Assert.*; + +import com.github.creme332.algorithms.CircleAlgorithm; import com.github.creme332.algorithms.EllipseAlgorithm; import com.github.creme332.tests.utils.TestHelper; @@ -112,4 +114,32 @@ public void testVerticalEllipseAtOrigin() { TestHelper.assert2DArrayEquals(expectedArray, pixels.toArray(new int[pixels.size()][])); } + @Test + public void testCircleCenteredOriginRadiusOne() { + int centerX = 0; + int centerY = 0; + int radius = 1; + int[][] actualPixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); + + int[][] expectedPixels = { + { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, + { 1, 1 }, { -1, 1 }, { 1, -1 }, { -1, -1 } + }; + + TestHelper.assert2DArrayEquals(expectedPixels, actualPixels); + } + + @Test + public void testCircleNotCenteredOriginRadiusOne() { + int centerX = 5; + int centerY = 5; + int radius = 1; + int[][] actualPixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); + + int[][] expectedPixels = { + { 6, 5 }, { 5, 4 }, { 5, 6 }, { 4, 5 } + }; + + TestHelper.assert2DArrayEquals(expectedPixels, actualPixels); + } } From 3c76f4a62d135e9fa6391d2847e78f2f5176ff58 Mon Sep 17 00:00:00 2001 From: Vasheel Date: Tue, 11 Jun 2024 08:52:31 +0400 Subject: [PATCH 08/10] write tests for circle algorithm in the test file CircleAlgorithmTest.java --- .../tests/algorithms/CircleAlgorithmTest.java | 28 +++++++++++++++++ .../algorithms/EllipseAlgorithmTest.java | 30 ------------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java index 02cf1718..39e4b4d2 100644 --- a/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java +++ b/src/test/java/com/github/creme332/tests/algorithms/CircleAlgorithmTest.java @@ -64,4 +64,32 @@ public void testNegativeRadiusCenteredOrigin() { assertEquals("Radius must be positive", e.getMessage()); } } + + @Test + public void testCircleCenteredOriginRadiusOne() { + int centerX = 0; + int centerY = 0; + int radius = 1; + int[][] actualPixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); + + int[][] expectedPixels = { + { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 } + }; + + TestHelper.assert2DArrayEquals(expectedPixels, actualPixels); + } + + @Test + public void testCircleNotCenteredOriginRadiusOne() { + int centerX = 5; + int centerY = 5; + int radius = 1; + int[][] actualPixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); + + int[][] expectedPixels = { + { 6, 5 }, { 4, 5 }, { 5, 6 }, { 5, 4 } + }; + + TestHelper.assert2DArrayEquals(expectedPixels, actualPixels); + } } diff --git a/src/test/java/com/github/creme332/tests/algorithms/EllipseAlgorithmTest.java b/src/test/java/com/github/creme332/tests/algorithms/EllipseAlgorithmTest.java index c5710a1d..89b81f75 100644 --- a/src/test/java/com/github/creme332/tests/algorithms/EllipseAlgorithmTest.java +++ b/src/test/java/com/github/creme332/tests/algorithms/EllipseAlgorithmTest.java @@ -3,7 +3,6 @@ import org.junit.Test; import static org.junit.Assert.*; -import com.github.creme332.algorithms.CircleAlgorithm; import com.github.creme332.algorithms.EllipseAlgorithm; import com.github.creme332.tests.utils.TestHelper; @@ -113,33 +112,4 @@ public void testVerticalEllipseAtOrigin() { TestHelper.assert2DArrayEquals(expectedArray, pixels.toArray(new int[pixels.size()][])); } - - @Test - public void testCircleCenteredOriginRadiusOne() { - int centerX = 0; - int centerY = 0; - int radius = 1; - int[][] actualPixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); - - int[][] expectedPixels = { - { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, - { 1, 1 }, { -1, 1 }, { 1, -1 }, { -1, -1 } - }; - - TestHelper.assert2DArrayEquals(expectedPixels, actualPixels); - } - - @Test - public void testCircleNotCenteredOriginRadiusOne() { - int centerX = 5; - int centerY = 5; - int radius = 1; - int[][] actualPixels = CircleAlgorithm.drawCircle(centerX, centerY, radius); - - int[][] expectedPixels = { - { 6, 5 }, { 5, 4 }, { 5, 6 }, { 4, 5 } - }; - - TestHelper.assert2DArrayEquals(expectedPixels, actualPixels); - } } From 42763998727c373dda63d8b7653f57a153a191be Mon Sep 17 00:00:00 2001 From: Vasheel Date: Tue, 11 Jun 2024 08:59:05 +0400 Subject: [PATCH 09/10] try to solve error of 8 points instead of 4 points but fails --- .../creme332/algorithms/CircleAlgorithm.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java index 927c47e7..b1428a57 100644 --- a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java +++ b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java @@ -6,7 +6,6 @@ public class CircleAlgorithm { private CircleAlgorithm() { - } public static int[][] drawCircle(int centerX, int centerY, int radius) { @@ -36,19 +35,17 @@ public static int[][] drawCircle(int centerX, int centerY, int radius) { } private static void plotCirclePoints(List pixelList, int centerX, int centerY, int x, int y) { - if (y == 0) { - addUniquePixel(pixelList, centerX + y, centerY + x); - addUniquePixel(pixelList, centerX + x, centerY + y); - addUniquePixel(pixelList, centerX + y, centerY - x); - addUniquePixel(pixelList, centerX - x, centerY + y); - return; - } - - if (y == x) { + // For radius 1, only plot the points exactly at distance 1 from the center + if (x == 0 && y == 1) { addUniquePixel(pixelList, centerX + y, centerY + x); addUniquePixel(pixelList, centerX - y, centerY + x); addUniquePixel(pixelList, centerX + y, centerY - x); addUniquePixel(pixelList, centerX - y, centerY - x); + + addUniquePixel(pixelList, centerX + x, centerY + y); + addUniquePixel(pixelList, centerX - x, centerY + y); + addUniquePixel(pixelList, centerX + x, centerY - y); + addUniquePixel(pixelList, centerX - x, centerY - y); return; } From e43227d5dfd87e5527483fa2ba2adbdbc7ea489e Mon Sep 17 00:00:00 2001 From: creme332 <65414576+creme332@users.noreply.github.com> Date: Tue, 11 Jun 2024 13:20:00 +0400 Subject: [PATCH 10/10] fix bug in drawCircle, rewrite plotCirclePoints with correct naming of variables --- .../creme332/algorithms/CircleAlgorithm.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java index b1428a57..b277fcc0 100644 --- a/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java +++ b/src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java @@ -6,6 +6,7 @@ public class CircleAlgorithm { private CircleAlgorithm() { + } public static int[][] drawCircle(int centerX, int centerY, int radius) { @@ -19,11 +20,11 @@ public static int[][] drawCircle(int centerX, int centerY, int radius) { int y = radius; int decisionParameter = 1 - radius; - while (y >= x) { + while (x <= y) { plotCirclePoints(pixelList, centerX, centerY, x, y); x++; - if (decisionParameter <= 0) { + if (decisionParameter < 0) { decisionParameter += 2 * x + 1; } else { y--; @@ -35,13 +36,15 @@ public static int[][] drawCircle(int centerX, int centerY, int radius) { } private static void plotCirclePoints(List pixelList, int centerX, int centerY, int x, int y) { - // For radius 1, only plot the points exactly at distance 1 from the center - if (x == 0 && y == 1) { + if (x == 0) { + addUniquePixel(pixelList, centerX + x, centerY + y); addUniquePixel(pixelList, centerX + y, centerY + x); + addUniquePixel(pixelList, centerX + x, centerY - y); addUniquePixel(pixelList, centerX - y, centerY + x); - addUniquePixel(pixelList, centerX + y, centerY - x); - addUniquePixel(pixelList, centerX - y, centerY - x); + return; + } + if (x == y) { addUniquePixel(pixelList, centerX + x, centerY + y); addUniquePixel(pixelList, centerX - x, centerY + y); addUniquePixel(pixelList, centerX + x, centerY - y); @@ -49,15 +52,15 @@ private static void plotCirclePoints(List pixelList, int centerX, int cen return; } - addUniquePixel(pixelList, centerX + y, centerY + x); - addUniquePixel(pixelList, centerX - y, centerY + x); - addUniquePixel(pixelList, centerX + y, centerY - x); - addUniquePixel(pixelList, centerX - y, centerY - x); - addUniquePixel(pixelList, centerX + x, centerY + y); addUniquePixel(pixelList, centerX - x, centerY + y); addUniquePixel(pixelList, centerX + x, centerY - y); addUniquePixel(pixelList, centerX - x, centerY - y); + + addUniquePixel(pixelList, centerX + y, centerY + x); + addUniquePixel(pixelList, centerX - y, centerY + x); + addUniquePixel(pixelList, centerX + y, centerY - x); + addUniquePixel(pixelList, centerX - y, centerY - x); } private static void addUniquePixel(List pixelList, int x, int y) {