DinosaurMoritz
DinosaurMoritz

Reputation: 145

How to calculate how many fields a circle with radius r will take up in a coordinate system

I wrote a function that "draws" a circle into a coordinate system (a 2d array/list):

def drawCircle(x,y,r,steps, draw=True):
        coords = []
        for n in range(steps):
            coords.append(((round(x + r * math.cos(2 * math.pi * (n / steps)))),round(y + r * math.sin(2 * math.pi * (n / steps)))))
        if draw:  
            for n in range(len(coords)):
                self.drawPixel(coords[n][0],coords[n][1])
        return list(set(coords))

It returns how many points are actually visible, because it overdraws some points. My question: (How) can I determine steps from r. That would make the function more efficient.

If I run

print(len(drawCircle(10, 10, r, 200)))

it gives me the answer I'm searching for.

for r in range(5,30):
    print(len(drawCircle(10, 10, r, 200)))
40
40
56
56
72
80
80
88
96
96
112
112
128
136
120
128
152
152
176
152
176
168
160
176
192

I can't see any pattern. The drawPixel(x,y) just does list[y][x] = "#"

Upvotes: 0

Views: 70

Answers (3)

I am new to this, but if I understand correctly, is this what you are looking for

import sympy as sy # a symbolic math module in numpy stack
import sympy.geometry as gm # a geometry module in sympy
import numpy as np # you might know this

unit=3 # the units of your field

#List of circles from 5 to 30
circles=[gm.Circle(gm.Point(10,10),r) for r in range(5,30)] 

# list of circle perimeters
perimeters=[i.circumference for i in circles]

#number of units for each radius step
num_of_units=[i//unit for i in perimeters]

print(num_of_units)

Upvotes: 1

MBo
MBo

Reputation: 80187

Instead of using trigonometry, exploit effective Bresenham circle drawing algorithm.

enter image description here

It produces only distinct points.

Upvotes: 1

Andre
Andre

Reputation: 788

You might be missing that the number of coordinates/pixels you function returns depends on both the r and step variables. If steps is sufficiently large, the number the number of pixels wont increase with even bigger steps.

consider this:

for steps in range(200, 5000, 200):
    print(len(drawCircle(10, 10, 40, steps, draw=False))) 

Out [1]:
200
280
288
304
288
312
320
320
312
320
320
320
312
320
320
320
320
320
320
320
320
320
320
320

So you might want to get the smallest number of steps that gets you the largest possible number of coorditates/pixels.

That is a bit more challenging, and I can't think of a very straightforward way to calculate this. A "bruteforce" solution could be this

def drawCircle(x,y,r, draw=True):
        
        steps = 500
        n_pixels = 0
        n_pixels_prev = -1
        
        while n_pixels_prev < n_pixels:
            coords = []
            for n in range(steps):
                x_pix = round( x + r * math.cos(2 * math.pi * (n / steps)) )
                y_pix = round( y + r * math.sin(2 * math.pi * (n / steps)) )
                coords.append( (x_pix, y_pix)  )
                
            n_pixels_prev = n_pixels
            n_pixels = len(set(coords))
            steps += 1000
            
            
        if draw:  
            for n in range(len(coords)):
                self.drawPixel(coords[n][0],coords[n][1])
        return list(set(coords))   

What it does is choose increasingly bigger values for step until it the number of pixels does not increase any more. The function then returns those coordinates. But this is not ideal as you can imagine.

Upvotes: 1

Related Questions