Generate smooth 2d circle for screen
-
I want to draw a circle in 2d. And I want to ensure the circle appears smooth. That means that the longer the radius of the circle, the more steps is needed to make the circle appear smooth.
-
36s gives 10 degree change of direction between each segment
360s gives 1 degree " "
720s gives 0.5 degree " "
Isn't it the steppiness of the segments that is the issue ?
No matter how many or few pixels a segment occupies the angle it makes with its neighbor might cause the appearance to look poor or better... -
A circle of radius 10px needs fewer segments than a 1000px radius circle.
-
But do you know the pixel-size before making it ?
If so, then you can simply have 'a rule' to increase the segment count in proportion to the pixel-size.
It's probably 'inverse' 'Exponential' or perhaps 'Fibonacci' ?
Very small circles will look 'steppy' even if you up the segmentation simply because the graphics are effectively transposed onto a 'grid' of pixels.
As you will know if you have tried to make small icon png image for a toolbar button with its limited choice of pixel positions for each dot representing a point on the circumference - but an 'octagonal' looks almost circular at small sizes as you brain tries to make patterns as it thinks they are, not as they are. -
But if you're drawing a circle that occupies 90% of the screen, then it needs more pixels location computed than a circle that is tiny.
I would guess you start with figuring out how many pixels in height and width your circle is, and then use that somehow to determine how many times you have to re-calculate. If you know the diameter is 800 pixels, figure out the circumference. That tells you how many pixels are on the circle, I think, right? Then maybe determine how many pixels per segment you want....2-3 is what you mentioned first. So the circumference of an 800 diameter circle is pi * diameter (3.14 * 800 = 2513.27). So there should be approximately that many pixels on the circle circunference. Then divide that by 3 to get 838 segments. Then you need 838 points plotted over 360 degrees around the circle. or 1 pixel plotted every 0.42959 degrees. So find an equation that lets you enter the degree and it will return an x,y coordinate for the edge of the circle at that degree. Or instead of dividing it into segments, you could just plot all 2513 pixels this way
Did that make any sense?
Chris
-
@thomthom said:
I want to ensure the circle appears smooth.
I drew a 6" (physical, measured on my screen) radius circle, 100 segments, and it appeared smooth, except at the sides and top/bottom. There you could see individual line segments stepping by single pixels, an unavoidable consequence of the hardware's limitations. More segments wouldn't change this.
At 6" radius, segments begin to disappear around 50s, are entirely gone at 60s. At 1" radius, there are no segments at 30s. At 3.5" radius, 45s is nearly segment-free.
I'd go with s = 6r + 24; s = segments, r = radius in screen inches.
-
And thinking more about it, plus your previous experiments in drawing to the screen, SketchUp automatically uses anti-aliasing on pixel drawing. So if you plotted each pixel (2513 in my previous example) and did not round to an integer, but left it a float - so instead of x,y = 100,29 you would leave it at 100.1232, 29.9843 Then I think that OpenGL would automatically anti-alias those pixels into some gray shades. It might make it a nicer smoother circle, even on small ones.
Chris
-
@chris fullmer said:
If you know the diameter is 800 pixels, figure out the circumference.
Bingo! Using the circumference as guide I can set up a formula to how many points are required to make a smooth circle.
Just to illustrate what I've been talking about.
The circle is of variable size - changes as the user interacts with the tool.Here is the circle in 12 segments in two different radius'.
As the circle increases in size, the more points are required to make it look smooth. I could just set a fixed very high number, but I figured there had to be a way to determine this dynamically.
@chris fullmer said:
So if you plotted each pixel (2513 in my previous example) and did not round to an integer, but left it a float - so instead of x,y = 100,29 you would leave it at 100.1232, 29.9843 Then I think that OpenGL would automatically anti-alias those pixels into some gray shades. It might make it a nicer smoother circle, even on small ones.
If AA is on, and the points are at an angle to XY then they will be AA'ed regardless if they are floats or ints.
It's when you have a straight line and keep it sharp when it matters whether the points are .0 or 0.5. -
Cool, post some pics of it working too, I'd like to see how smooth it works.
The aa thing still confuses me (obvisouly). I thought it might also apply to pixels and that it might aa them differneetly if they are at x=105, x105.5, x-105.21, x=105.93, etc. I guess it does not go to that lengt to AA pixels when drawing them.
Good luck Thom,
Chris
-
First test working good so far. But a linear function adds all too many points for large circles. As TIG mentioned, this probably needs some inverse exponential falloff.
Ok - I'll admit it, might be just as good just to keep it simple to set a fixed value that works ok for all ranges. But this has got me thinking now. I want to solve it as a matter of exercise.
-
Dear Thomas,
Factors other than smoothness can influence the chosen number of segments.
I use Sketchup for concept engineering design before going to other 3D CAD software, and I typically use 48 segments up to diameters of 150 mm, and 96 up to 400 mm. I need numbers divisible by 3, 4, 6, 8, 12 so that I can draw arrays of holes on a pitch circle diameter.
Regards,
Bob -
One of the best appearence of drawing curves on the screen is Moment of Inspiration
The guy (Michael Gibson) has developped his own graphic engineSo you can have that directly on the work's screen
By PaQ (Click for zoom)
Advertisement