Draw circle in console using python
Asked Answered
D

4

6

I want to draw a circle in the console using characters instead of pixels, for this I need to know how many pixels are in each row. The diameter is given as input, you need to output a list with the width in pixels of each line of the picture

For example:

input: 7

output: [3, 5, 7, 7, 7, 5, 3]

enter image description here

input: 12

output: [4, 8, 10, 10, 12, 12, 12, 12, 10, 10, 8, 4]

enter image description here

How can this be implemented?

Delorisdelorme answered 15/1, 2022 at 14:56 Comment(1)
Please read stackoverflow.com/help/how-to-ask . Have you tried anything? Unless you can show what you've tried and explain where you got stuck we cannot possibly start helping you!. Do you know how to print to the console? Do you know how to loop? Do you have python installed? Do you understand the problem? Are you trying to 'draw a circle' as per the question title, or 'output how many characters would be used per line to draw a circle'Dizzy
R
3

This was a good reminder for me to be careful when mixing zero-based and one-based computations. In this case, I had to account for the for loops being zero-based, but the quotient of the diameter divided by 2 being one-based. Otherwise, the plots would have been over or under by 1.

By the way, while I matched your answer for 7, I didn't come up with the same exact plot for 12:

NOTE - Tested using Python 3.9.6

pixels_in_line = 0
pixels_per_line = []

diameter = int(input('Enter the diameter of the circle: '))

# You must account for the loops being zero-based, but the quotient of the diameter / 2 being
# one-based. If you use the exact radius, you will be short one column and one row.
offset_radius = (diameter / 2) - 0.5

for i in range(diameter):
    for j in range(diameter):
        x = i - offset_radius
        y = j - offset_radius
        if x * x + y * y <= offset_radius * offset_radius + 1:
            print('*', end='  ')
            pixels_in_line += 1
        else:
            print(' ', end='  ')
    pixels_per_line.append(pixels_in_line)
    pixels_in_line = 0
    print()

print('The pixels per line are {0}.'.format(pixels_per_line))

Output for 7:

Enter the diameter of the circle: 7
      *  *  *        
   *  *  *  *  *     
*  *  *  *  *  *  *  
*  *  *  *  *  *  *  
*  *  *  *  *  *  *  
   *  *  *  *  *     
      *  *  *        
The pixels per line are [3, 5, 7, 7, 7, 5, 3].

Output for 12:

Enter the diameter of the circle: 12
               *  *                 
         *  *  *  *  *  *           
      *  *  *  *  *  *  *  *        
   *  *  *  *  *  *  *  *  *  *     
   *  *  *  *  *  *  *  *  *  *     
*  *  *  *  *  *  *  *  *  *  *  *  
*  *  *  *  *  *  *  *  *  *  *  *  
   *  *  *  *  *  *  *  *  *  *     
   *  *  *  *  *  *  *  *  *  *     
      *  *  *  *  *  *  *  *        
         *  *  *  *  *  *           
               *  *                 
The pixels per line are [2, 6, 8, 10, 10, 12, 12, 10, 10, 8, 6, 2].
Randeerandel answered 15/1, 2022 at 19:18 Comment(1)
Cool! Congrats. I'd propose instead of if x * x + y * y <= offset_radius * offset_radius + 1: to use: if x ** 2 + y ** 2 <= offset_radius ** 2 + 1:. And by the way, you can put all * in one string (join the lines with '\n') and print the string in one step. Don't need to print every pixel and don't need to count every * inside the loop (they can be counted with list.count('*') method). I think it would be a more clean code, just three steps: (1) make the string, (2) print the string, (3) count the 'pixels' per lines in the string and pint the report.Frederik
F
3

Based on Rob's solution (all credits to Rob!) I've managed to tweak the code for 12x12 pixel grid as well:

diameter = 12

radius = diameter / 2 - .5
r = (radius + .25)**2 + 1

result = ''

for i in range(diameter):
    y = (i - radius)**2
    for j in range(diameter):
        x = (j - radius)**2
        if x + y <= r:
            result = result + '*  '
        else:
            result = result + '   '
    result = result + '\n'

print(result)

result = result.split('\n')[:-1]
pixels_per_line = [x.count('*') for x in result]

print(f'The pixels per line are {pixels_per_line}.')

Output:

            *  *  *  *              
      *  *  *  *  *  *  *  *        
   *  *  *  *  *  *  *  *  *  *     
   *  *  *  *  *  *  *  *  *  *     
*  *  *  *  *  *  *  *  *  *  *  *  
*  *  *  *  *  *  *  *  *  *  *  *  
*  *  *  *  *  *  *  *  *  *  *  *  
*  *  *  *  *  *  *  *  *  *  *  *  
   *  *  *  *  *  *  *  *  *  *     
   *  *  *  *  *  *  *  *  *  *     
      *  *  *  *  *  *  *  *        
            *  *  *  *              

The pixels per line are [4, 8, 10, 10, 12, 12, 12, 12, 10, 10, 8, 4].

If you need the empty area inside the circle it can be done with minimal changes:

diameter = 7

radius = diameter / 2 - .5
r = (radius + .25)**2 + 1
r_min = (radius - 1)**2 + 1 # <-------- here

result = ''

for i in range(diameter):
    y = (i - radius)**2
    for j in range(diameter):
        x = (j - radius)**2
        if r_min <= x + y <= r: # <----- here
            result = result + '*  '
        else:
            result = result + '   '
    result = result + '\n'

print(result)

Output:

      *  *  *        
   *  *     *  *     
*  *           *  *  
*                 *  
*  *           *  *  
   *  *     *  *     
      *  *  *        
            *  *  *  *              
      *  *  *        *  *  *        
   *  *                    *  *     
   *                          *     
*  *                          *  *  
*                                *  
*                                *  
*  *                          *  *  
   *                          *     
   *  *                    *  *     
      *  *  *        *  *  *        
            *  *  *  *              
Frederik answered 15/1, 2022 at 21:9 Comment(1)
@Delorisdelorme it would be fair if you accept the Rob's answer instead. He did most of the job.Frederik
S
1

you can do like this. This is based on the circle formula x^2 + y^2 is equal to radius and any point inside is less than radius.

import math
radius = 10
for i in range(-radius,radius+1):
    for j in range(-radius, radius +1):
        if radius-1 <= math.sqrt(i**2 + j**2) <= radius:
            print("*",end = " ")
        else:
            print(" ", end = ' ')
    print()

Output is as follows

                       *                         
                * * * * * * * * *                 
            * *                   * *             
          *                           *           
        *                               *         
      *                                   *       
    *                                       *     
    *                                       *     
  *                                           *   
  *                                           *   
  *                                           *   
  *                                           *   
* *                                           * * 
  *                                           *   
  *                                           *   
  *                                           *   
  *                                           *   
    *                                       *     
    *                                       *     
      *                                   *       
        *                               *         
          *                           *           
            * *                   * *             
                * * * * * * * * *                 
                        * 

if you remove the greater than condition

radius = 12
for i in range(-radius,radius+1):
    for j in range(-radius, radius +1):
        if math.sqrt(i**2 + j**2) <= radius:
            print("*",end = " ")
        else:
            print(" ", end = ' ')
    print()

output

                       *                         
                * * * * * * * * *                 
            * * * * * * * * * * * * *             
          * * * * * * * * * * * * * * *           
        * * * * * * * * * * * * * * * * *         
      * * * * * * * * * * * * * * * * * * *       
    * * * * * * * * * * * * * * * * * * * * *     
    * * * * * * * * * * * * * * * * * * * * *     
  * * * * * * * * * * * * * * * * * * * * * * *   
  * * * * * * * * * * * * * * * * * * * * * * *   
  * * * * * * * * * * * * * * * * * * * * * * *   
  * * * * * * * * * * * * * * * * * * * * * * *   
* * * * * * * * * * * * * * * * * * * * * * * * * 
  * * * * * * * * * * * * * * * * * * * * * * *   
  * * * * * * * * * * * * * * * * * * * * * * *   
  * * * * * * * * * * * * * * * * * * * * * * *   
  * * * * * * * * * * * * * * * * * * * * * * *   
    * * * * * * * * * * * * * * * * * * * * *     
    * * * * * * * * * * * * * * * * * * * * *     
      * * * * * * * * * * * * * * * * * * *       
        * * * * * * * * * * * * * * * * *         
          * * * * * * * * * * * * * * *           
            * * * * * * * * * * * * *             
                * * * * * * * * *                 
                        *     
Suspensive answered 9/9, 2023 at 14:6 Comment(0)
C
1

If you can do some math, you can use only one loop.

def calc_circle(diameter):
    pixels_per_line = []
    parity = diameter % 2
    radius = (diameter / 2.)-0.5
    for i in range(diameter):
        j = abs(i-radius)
        pixels_in_line = int((radius * radius - j*j+3)**(1/2)*2) # '+3' is an arbitrary number
        pixels_per_line.append(pixels_in_line+int((pixels_in_line%2)^parity))
    return pixels_per_line

The output is below:

calc_offset_circle(7)
> [3, 5, 7, 7, 7, 5, 3]

calc_offset_circle(12)
> [4, 8, 10, 10, 12, 12, 12, 12, 10, 10, 8, 4]

The draw function is as follows:

def print_circle(lines):
    wh = len(lines)
    result = ''
    for i in range(wh):
        for j in range(int((wh-lines[i])/2)): result = result + '   '
        for j in range(lines[i]): result = result + '*  '
        for j in range(int((wh-lines[i])/2)): result = result + '   '
        result = result + '\n'
    print(result)

And the result is below:

print_circle(calc_offset_circle(7))
      *  *  *        
   *  *  *  *  *     
*  *  *  *  *  *  *  
*  *  *  *  *  *  *  
*  *  *  *  *  *  *  
   *  *  *  *  *     
      *  *  *
print_circle(calc_offset_circle(12))
            *  *  *  *              
      *  *  *  *  *  *  *  *        
   *  *  *  *  *  *  *  *  *  *     
   *  *  *  *  *  *  *  *  *  *     
*  *  *  *  *  *  *  *  *  *  *  *  
*  *  *  *  *  *  *  *  *  *  *  *  
*  *  *  *  *  *  *  *  *  *  *  *  
*  *  *  *  *  *  *  *  *  *  *  *  
   *  *  *  *  *  *  *  *  *  *     
   *  *  *  *  *  *  *  *  *  *     
      *  *  *  *  *  *  *  *        
            *  *  *  *   
Caneghem answered 4/7, 2024 at 6:13 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.