Skip to content

Commit

Permalink
Merge pull request #43 from Vasheel/Bresenham
Browse files Browse the repository at this point in the history
implementation of  Bresenham circle algorithm and tests
  • Loading branch information
creme332 authored Jun 11, 2024
2 parents b8d4f30 + e43227d commit 9eb493b
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 1 deletion.
69 changes: 69 additions & 0 deletions src/main/java/com/github/creme332/algorithms/CircleAlgorithm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.github.creme332.algorithms;

import java.util.ArrayList;
import java.util.List;

public class CircleAlgorithm {

private CircleAlgorithm() {

}

public static int[][] drawCircle(int centerX, int centerY, int radius) {
if (radius <= 0) {
throw new IllegalArgumentException("Radius must be positive");
}

List<int[]> pixelList = new ArrayList<>();

int x = 0;
int y = radius;
int decisionParameter = 1 - radius;

while (x <= y) {
plotCirclePoints(pixelList, centerX, centerY, x, y);
x++;

if (decisionParameter < 0) {
decisionParameter += 2 * x + 1;
} else {
y--;
decisionParameter += 2 * (x - y) + 1;
}
}

return pixelList.toArray(new int[pixelList.size()][]);
}

private static void plotCirclePoints(List<int[]> pixelList, int centerX, int centerY, int x, int y) {
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);
return;
}

if (x == 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);
return;
}

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<int[]> pixelList, int x, int y) {
pixelList.add(new int[] { x, y });
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
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.*;

public class CircleAlgorithmTest {

@Test
public void testValidCircleCenteredOrigin() {
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 },
};

// Using the helper method for assertion
TestHelper.assert2DArrayEquals(expectedPixels, actualPixels);
}

@Test
public void testZeroRadiusCenteredOrigin() {
int centerX = 0;
int centerY = 0;
int radius = 0;

try {
CircleAlgorithm.drawCircle(centerX, centerY, radius);
fail("Expected IllegalArgumentException for zero radii");
} catch (IllegalArgumentException e) {
assertEquals("Radius must be positive", e.getMessage());
}
}

@Test
public void testNegativeRadiusCenteredOrigin() {
int centerX = 0;
int centerY = 0;
int radius = -5;
try {
CircleAlgorithm.drawCircle(centerX, centerY, radius);
fail("Expected IllegalArgumentException for negative radii");
} catch (IllegalArgumentException e) {
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import org.junit.Test;
import static org.junit.Assert.*;

import com.github.creme332.algorithms.EllipseAlgorithm;
import com.github.creme332.tests.utils.TestHelper;

Expand Down Expand Up @@ -111,5 +112,4 @@ public void testVerticalEllipseAtOrigin() {

TestHelper.assert2DArrayEquals(expectedArray, pixels.toArray(new int[pixels.size()][]));
}

}

0 comments on commit 9eb493b

Please sign in to comment.