Reputation: 107
This program prints a circle in a Cartesian plane.
The inputs are: radius, coordinates of the center of the circle (cx,cy), and the character with which we want to print the circle.
If the points of the circle overlap with the axes, the points have priority. I wrote a condition for the printing of the axes in method drawCircle
, but the image is distorted...
Something is eluding me... can someone help me to find my mistake?
Here is my entire program (the method that has issues is the last one, drawCircle
):
public class Circle {
public static void main(String[] args) {
System.out.println(onCircle(1, 2, 3, 4, 5));
drawCircle(1, 3, 3, '*');
drawCircle(3, 3, 3, '*');
drawCircle(5, 10, 12, '*');
}
//Question 1A
public static boolean onCircle(int radius, int cx, int cy, int x, int y) {
//default answer is false, but if the
//inequality holds then it is set to true
boolean isDrawn = false;
if (Math.pow(radius,2)<=(Math.pow((x-cx),2)+Math.pow((y-cy),2))
&& (Math.pow((x-cx),2)+Math.pow((y-cy),2))<=(Math.pow(radius,2)+1)) {
isDrawn = true;
}
return isDrawn;
}
//Question 1B
public static void verifyInput(int radius, int cx, int cy) {
//if radius is negative, display error message
if (radius <= 0) {
throw new IllegalArgumentException(
"The radius of the circle must be a positive number.");
}
//if the center of the circle with radius 'radius' causes the circle
//to 'overflow' into other quadrants, display error message
if ((cx - radius) < 0 || (cy - radius) < 0) {
throw new IllegalArgumentException(
"the circle with requested parameters does not fit " +
"in the quadrant. Consider moving the center of the " +
"circle further from the axes.");
}
}
//Question 1C
public static void drawCircle(int radius, int cx, int cy, char symbol) {
verifyInput(radius, cx, cy);
//set the values for extension of the axes (aka how long are they)
int xMax = cx + radius + 1;
int yMax = cy + radius + 1;
for (int j = yMax; j >= 0; j--) {
for (int i = 0; i <= xMax; i++) {
//set of if-block to print the axes
if (i == 0 && j == 0) {
System.out.print('+');
} else if (i == 0) {
if (j == yMax) {
System.out.print('^');
}
if (j != yMax && onCircle(radius, cx, cy, i, j) == false) {
System.out.print('|');
}
} else if (j == 0) {
if (i == xMax) {
System.out.print('>');
}
if (i != xMax && onCircle(radius, cx, cy, i, j) == false) {
System.out.print('-');
}
}
//if block to print the circle
//verify for each coordinate (i,j)
//in the quadrant if they are on circle
//if =true print symbol, if =false print empty character
if (onCircle(radius, cx, cy, i, j) == true) {
System.out.print(symbol);
} else {
System.out.print(' ');
}
}
System.out.println();
}
}
}
Here is what I am getting:
false
^
| ***
| * *
| ***
|
+ - - - - >
^
| ***
|
* *
* *
* *
|
+ - ***- - >
^
| ***
| * *
| * *
|
| * *
| * *
| * *
|
| * *
| * *
| ***
|
|
|
|
|
|
+ - - - - - - - - - - - - - - - >
As you can see, the 1st and 3rd circles are fine, but the one that overlaps with the axes is distorted.
Upvotes: 3
Views: 2559
Reputation: 4818
Actually when debugging, your onCircle methods gets for x=0
and y=4
, cx=3
, cy=3
:
You have:
Math.pow(radius=3, 2) = 9
Math.pow((x - cx), 2) = 9
Math.pow((y - cy), 2) = 1
Hence
Math.pow(radius, 2) <= Math.pow((x - cx), 2) + Math.pow((y - cy), 2)
returns true
Then:
(Math.pow((x-cx),2) = 9
Math.pow((y-cy),2)) = 1
(Math.pow(radius,2)+1)) = 10
Thus
(Math.pow((x-cx),2)+Math.pow((y-cy),2)) <= (Math.pow(radius,2)+1))
returns also true
Thus onCircle(radius,cx,cy,i,j)
returns true for this coordinate.
And that's why you get your symbol drawn. You need to improve your algorithm!
Upvotes: 0
Reputation:
The general Equation of a circle centred at the origin:
In Java it can be implemented like this:
i*i + j*j == r*r
But in the case of an integer coordinate system, you have to round this equation somehow so that all the points of the circle are reflected in this coordinate system:
(int) Math.sqrt(i*i + j*j) == r
If r=8
, then the circle and axes look like this:
r=8
* * * * * * * * *
* * * * *
* * *
* * *
* * * * *
* * *
* * *
* * *
* * * * * * * * * * * * * * * * *
* * *
* * *
* * *
* * * * *
* * *
* * *
* * * * *
* * * * * * * * *
int r = 8;
System.out.println("r=" + r);
IntStream.rangeClosed(-r, r)
.peek(i -> IntStream.rangeClosed(-r, r)
.mapToObj(j -> i == 0 || j == 0 ||
(int) Math.sqrt(i*i + j*j) == r ?
"* " : " ")
.forEach(System.out::print))
.forEach(i -> System.out.println());
See also: Print out an ASCII star in java
Upvotes: 1
Reputation: 46
You're missing 3 continue statements.
Check out this revised version of your drawCircle
method:
public static void drawCircle(int radius, int cx, int cy, char symbol) {
verifyInput(radius, cx, cy);
//set the values for extension of the axes (aka how long are they)
int xMax = cx + radius + 1;
int yMax = cy + radius + 1;
for (int j = yMax; j >= 0; j--) {
for (int i = 0; i <= xMax; i++) {
//set of if-block to print the axes
if (i == 0 && j == 0) {
System.out.print('+');
continue;
} else if (i == 0) {
if (j == yMax) {
System.out.print('^');
}
if (j != yMax && onCircle(radius, cx, cy, i, j) == false) {
System.out.print('|');
continue;
}
} else if (j == 0) {
if (i == xMax) {
System.out.print('>');
}
if (i != xMax && onCircle(radius, cx, cy, i, j) == false) {
System.out.print('-');
continue;
}
}
//if block to print the circle
//verify for each coordinate (i,j)
//in the quadrant if they are on circle
//if =true print symbol, if =false print empty character
if (onCircle(radius, cx, cy, i, j) == true) {
System.out.print(symbol);
} else {
System.out.print(' ');
}
}
System.out.println();
}
}
Upvotes: 0