Drawing a circle with the correct number of segments

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Drawing a circle with the correct number of segments

Post by kikito »

This is a math problem.

LÖVE's circle drawing function isn't really a circle drawing function. It would be more correctly described as a "regular polygon drawing function" - by default it draws octogons (8 segments).

Code: Select all

love.graphics.circle(x,y,radius,segments) --segments defaults to 8
While this is interesting if you are trying to draw regular polygons (pass a 3 and you get equilateral triangle, 5 a pentagon, etc), it can cause problems if you are trying to draw circles.

Specifically, big circles. Say that you are drawing a "bigger than the screen planet Earth circle" - how many segments do you use for that circle to look "smooth"?

You would set the number of segments to something huge, like 2000 or something. Say that your game now zooms out to see the whole solar system. 8 or 10 segments would probably suffice now - 2000 would be overkill.

I hope you see the problem now - I'm looking for a formula that, given a radius, chooses the minimum amount of segments drawing a smooth circle. I'm also thinking that the formula might had to take into account the screen resolution - not sure about this though.

Right now I'm using radius*2 for segments, based on a very quick and dirty test. Do any of you guys know a better approach?
When I write def I mean function.
Jpfed
Prole
Posts: 4
Joined: Tue Jun 02, 2009 10:54 pm

Re: Drawing a circle with the correct number of segments

Post by Jpfed »

The length of any one segment shouldn't be larger than some threshold (2 or 3 pixels?). So

r*sin(2*pi/segments) <= threshold

which means

segments >= 2*pi/arcsin(threshold/r)

This is approximated well by the following (and the approximation gets better as r increases):

segments >= 2*r*pi/threshold

Your approach is correct for a threshold of pi pixels. :)
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Drawing a circle with the correct number of segments

Post by kikito »

Amazing stuff.

Thanks for helping me with the trigonometric parts; I haven't used stuff like this since highschool.
Your approach is correct for a threshold of pi pixels. :)
Not bad for a quick and dirty estimation, hum? :neko:

I'll use 3*radius from now on, then. It is simple, and if I'm not mistaken, should give me a 2*Pi/3 threshold (~ 2 pixels).

Kudos to you!
When I write def I mean function.
User avatar
tentus
Inner party member
Posts: 1060
Joined: Sun Oct 31, 2010 7:56 pm
Location: Appalachia
Contact:

Re: Drawing a circle with the correct number of segments

Post by tentus »

(This is being discussed on the Issue Tracker, hence the resurrection.)

Try this code to see what happens depending on difference segments:

Code: Select all

function love.draw()
	for i=1, 6 do
		local y = (i * 100) - 48
		for j=1, 22 do
			local x = ((j ^ 2) * 1.5) + 16
			love.graphics.circle("fill", x, y, j, i * j)
		end
		love.graphics.print(i.."r segments", 16, y - 32)
	end
end
In my opinion, 2r is good enough most of the time. 3r does have the advantage of being visible at radius of 1 though.
Kurosuke needs beta testers
User avatar
kikito
Inner party member
Posts: 3153
Joined: Sat Oct 03, 2009 5:22 pm
Location: Madrid, Spain
Contact:

Re: Drawing a circle with the correct number of segments

Post by kikito »

tentus wrote:(This is being discussed on the Issue Tracker, hence the resurrection.)

Try this code to see what happens depending on difference segments:

Code: Select all

function love.draw()
	for i=1, 6 do
		local y = (i * 100) - 48
		for j=1, 22 do
			local x = ((j ^ 2) * 1.5) + 16
			love.graphics.circle("fill", x, y, j, i * j)
		end
		love.graphics.print(i.."r segments", 16, y - 32)
	end
end
In my opinion, 2r is good enough most of the time. 3r does have the advantage of being visible at radius of 1 though.
I don't have any opinion on this regard. If we "must" make the circles visible, no matter what, then the amount of sides must have a lower bound of three; i.e. math.max(2*r, 3) or something.
When I write def I mean function.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 153 guests