Skip to content

Commit 7cf568c

Browse files
Add midpoint circle algorithm (#5868)
1 parent 9218212 commit 7cf568c

File tree

2 files changed

+140
-0
lines changed

2 files changed

+140
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package com.thealgorithms.geometry;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.List;
6+
7+
/**
8+
* Class to represent the Midpoint Circle Algorithm.
9+
* This algorithm calculates points on the circumference of a circle
10+
* using integer arithmetic for efficient computation.
11+
*/
12+
public final class MidpointCircle {
13+
14+
private MidpointCircle() {
15+
// Private Constructor to prevent instantiation.
16+
}
17+
18+
/**
19+
* Generates points on the circumference of a circle using the midpoint circle algorithm.
20+
*
21+
* @param centerX The x-coordinate of the circle's center.
22+
* @param centerY The y-coordinate of the circle's center.
23+
* @param radius The radius of the circle.
24+
* @return A list of points on the circle, each represented as an int[] with 2 elements [x, y].
25+
*/
26+
public static List<int[]> generateCirclePoints(int centerX, int centerY, int radius) {
27+
List<int[]> points = new ArrayList<>();
28+
29+
// Special case for radius 0, only the center point should be added.
30+
if (radius == 0) {
31+
points.add(new int[] {centerX, centerY});
32+
return points;
33+
}
34+
35+
// Start at (radius, 0)
36+
int x = radius;
37+
int y = 0;
38+
39+
// Decision parameter
40+
int p = 1 - radius;
41+
42+
// Add the initial points in all octants
43+
addSymmetricPoints(points, centerX, centerY, x, y);
44+
45+
// Iterate while x > y
46+
while (x > y) {
47+
y++;
48+
49+
if (p <= 0) {
50+
// Midpoint is inside or on the circle
51+
p = p + 2 * y + 1;
52+
} else {
53+
// Midpoint is outside the circle
54+
x--;
55+
p = p + 2 * y - 2 * x + 1;
56+
}
57+
58+
// Add points for this (x, y)
59+
addSymmetricPoints(points, centerX, centerY, x, y);
60+
}
61+
62+
return points;
63+
}
64+
65+
/**
66+
* Adds the symmetric points in all octants of the circle based on the current x and y values.
67+
*
68+
* @param points The list to which symmetric points will be added.
69+
* @param centerX The x-coordinate of the circle's center.
70+
* @param centerY The y-coordinate of the circle's center.
71+
* @param x The current x-coordinate on the circumference.
72+
* @param y The current y-coordinate on the circumference.
73+
*/
74+
private static void addSymmetricPoints(Collection<int[]> points, int centerX, int centerY, int x, int y) {
75+
// Octant symmetry points
76+
points.add(new int[] {centerX + x, centerY + y});
77+
points.add(new int[] {centerX - x, centerY + y});
78+
points.add(new int[] {centerX + x, centerY - y});
79+
points.add(new int[] {centerX - x, centerY - y});
80+
points.add(new int[] {centerX + y, centerY + x});
81+
points.add(new int[] {centerX - y, centerY + x});
82+
points.add(new int[] {centerX + y, centerY - x});
83+
points.add(new int[] {centerX - y, centerY - x});
84+
}
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.thealgorithms.geometry;
2+
3+
import static org.junit.jupiter.api.Assertions.assertTrue;
4+
5+
import java.util.List;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.params.ParameterizedTest;
8+
import org.junit.jupiter.params.provider.CsvSource;
9+
10+
/**
11+
* Test class for the {@code MidpointCircle} class
12+
*/
13+
class MidpointCircleTest {
14+
15+
/**
16+
* Parameterized test to check the generated points for different circles.
17+
* The points are checked based on the expected center and radius.
18+
*
19+
* @param centerX The x-coordinate of the circle's center.
20+
* @param centerY The y-coordinate of the circle's center.
21+
* @param radius The radius of the circle.
22+
*/
23+
@ParameterizedTest
24+
@CsvSource({
25+
"0, 0, 3", // Circle centered at (0, 0) with radius 3
26+
"10, 10, 2" // Circle centered at (10, 10) with radius 2
27+
})
28+
void
29+
testGenerateCirclePoints(int centerX, int centerY, int radius) {
30+
List<int[]> points = MidpointCircle.generateCirclePoints(centerX, centerY, radius);
31+
32+
// Ensure that all points satisfy the circle equation (x - centerX)^2 + (y - centerY)^2 = radius^2
33+
for (int[] point : points) {
34+
int x = point[0];
35+
int y = point[1];
36+
37+
int dx = x - centerX;
38+
int dy = y - centerY;
39+
int distanceSquared = dx * dx + dy * dy;
40+
41+
assertTrue(Math.abs(distanceSquared - radius * radius) <= 1, "Point (" + x + ", " + y + ") does not satisfy the circle equation.");
42+
}
43+
}
44+
45+
/**
46+
* Test to ensure the algorithm generates points for a zero-radius circle.
47+
*/
48+
@Test
49+
void testZeroRadiusCircle() {
50+
List<int[]> points = MidpointCircle.generateCirclePoints(0, 0, 0);
51+
52+
// A zero-radius circle should only have one point: (0, 0)
53+
assertTrue(points.size() == 1 && points.get(0)[0] == 0 && points.get(0)[1] == 0, "Zero-radius circle did not generate the correct point.");
54+
}
55+
}

0 commit comments

Comments
 (0)