Polina Trotsenko
Polina Trotsenko

Reputation: 107

Print out an ASCII circle and axes

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

Answers (3)

Adonis
Adonis

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

user15402945
user15402945

Reputation:

The general Equation of a circle centred at the origin:

Equation of a circle

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
        * * * * * * * * *         
      * *       *       * *       
    *           *           *     
  *             *             *   
* *             *             * * 
*               *               * 
*               *               * 
*               *               * 
* * * * * * * * * * * * * * * * * 
*               *               * 
*               *               * 
*               *               * 
* *             *             * * 
  *             *             *   
    *           *           *     
      * *       *       * *       
        * * * * * * * * *         

Try it online!

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

alawand
alawand

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

Related Questions