Drawing Empty Circles
Monkey Forums/Monkey Programming/Drawing Empty Circles
| ||
In Monkey DrawCirle, DrawEllipse or DrawOval functions fill the shapes. I need to draw empty circles and I did the following code: The only problem it is the performance. Is there another way to draw empty circles in Monkey? Method Circle:Void(x:Float, y:Float, w:Float, h:Float) For Local phi:Float = 0.0 Until 360.0 DrawPoint(x + Cos(phi) * w, y - Sin(phi) * h) Next End |
| ||
Maybe something like:Method Circle:Void(x:Float, y:Float, w:Float, h:Float) For Local phi:Float = 0.0 Until 360.0 Step 10 DrawLine(x + Cos(phi-10) * w, y - Sin(phi-10) * h, x + Cos(phi) * w, y - Sin(phi) * h ) Next EndUntested, but you're basically drawing 36 short lines, instead of 360 points. |
| ||
http://en.wikipedia.org/wiki/Midpoint_circle_algorithm |
| ||
Guys thank you , It improved the performance |
| ||
The simplest thing is to make a Polygon function that draws a polygon of N points, starting at a certain angle. Then for a circle, you just use lots of points. Of course if the background is unimportant, you can DrawCircle twice in different colours, with the second one having a smaller radius. |
| ||
Translated my old PureBasic code for Bresenham circle and ellipse:Strict Import mojo Function Circle:Void(x:Int, y:Int, radius:Int) Local temp_x:Int = 0 Local d:Int = 3 - 2 * radius While temp_x <= radius DrawPoint(x+temp_x, y+radius) ' part 1 DrawPoint(x-temp_x, y+radius) DrawPoint(x+radius, y+temp_x) ' part 2 DrawPoint(x-radius, y+temp_x) DrawPoint(x+radius, y-temp_x) ' part 3 DrawPoint(x-radius, y-temp_x) DrawPoint(x-temp_x, y-radius) ' part 4 DrawPoint(x+temp_x, y-radius) If d < 0 d += 4 * temp_x + 6 Else d += 4 * (temp_x - radius) + 10 radius -= 1 Endif temp_x += 1 Wend End Function Ellipse:Void(x:Int, y:Int, radius_x:Int, radius_y:Int) Local temp_x:Int = 0 Local temp_y:Int = radius_y Local temp_radius_x1:Int = radius_x * radius_x Local temp_radius_y1:Int = radius_y * radius_y Local temp_radius_x2:Int = temp_radius_x1 * 2 Local temp_radius_y2:Int = temp_radius_y1 * 2 Local temp_fx:Int = 0 Local temp_fy:Int = temp_radius_x2 * radius_y Local p:Int = temp_radius_y1 - temp_radius_x1*radius_y + Int(0.25 * temp_radius_x1) If radius_x = radius_y Circle(x,y,radius_x) Return Endif While temp_fx <= temp_fy DrawPoint(x+temp_x, y+temp_y) DrawPoint(x-temp_x, y+temp_y) DrawPoint(x-temp_x, y-temp_y) DrawPoint(x+temp_x, y-temp_y) temp_x += 1 temp_fx += temp_radius_y2 If p < 0 p += temp_fx + temp_radius_y1 Else temp_y -= 1 temp_fy -= temp_radius_x2 p += temp_fx + temp_radius_y1 - temp_fy Endif Wend DrawPoint(x+temp_x, y+temp_y) DrawPoint(x-temp_x, y+temp_y) DrawPoint(x-temp_x, y-temp_y) DrawPoint(x+temp_x, y-temp_y) p = temp_radius_y1 * (temp_x - 0.5) * (temp_x + 0.5) + temp_radius_x1 * (temp_y - 1)*(temp_y - 1) - temp_radius_x1 * temp_radius_y1 While temp_y > 0 temp_y -= 1 temp_fy -= temp_radius_x2 If p >= 0 p -= temp_fy + temp_radius_x1 Else temp_x += 1 temp_fx += temp_radius_y2 p += temp_fx - temp_fy + temp_radius_x1 Endif DrawPoint(x+temp_x, y+temp_y) DrawPoint(x-temp_x, y+temp_y) DrawPoint(x-temp_x, y-temp_y) DrawPoint(x+temp_x, y-temp_y) Wend End Function RotateAt:Void(x:Float, y:Float, angle:Float) Translate(x, y) Rotate(angle) Translate(-x, -y) End Class Program Extends App Field rotation:Float = 0 Method OnCreate:Int() SetUpdateRate 60 Return 0 End Method OnRender:Int() Local mid_x:Int = DeviceWidth() * 0.5 Local mid_y:Int = DeviceHeight() * 0.5 Cls 128,128,128 SetColor 0,0,0 Circle mid_x, mid_y,40 RotateAt(mid_x,mid_y,rotation) rotation += 5 'SetColor 255,255,255 'DrawEllipse mid_x, mid_y,100,60 'SetColor 0,0,0 For Local i:Int = 60 To 150 Step 5 Ellipse mid_x, mid_y,40+i,i Next Return 0 End End Function Main:Int() New Program Return 0 End |
| ||
Function DrawCircleOutline:Void(x:Float, y:Float, radius:Float, detail:Int = -1) If detail < 0 detail = radius / 2.0 ElseIf detail < 3 detail = 3 ElseIf detail > MAX_VERTS detail = MAX_VERTS End Local angleStep:Float = 360.0 / detail Local angle:Float Local offsetX:Float Local offsetY:float Local first:Bool = True Local firstX:Float Local firstY:float Local thisX:Float Local thisY:float Local lastX:Float Local lastY:Float For Local vertIndex:= 0 Until detail offsetX = Sin(angle) * radius offsetY = Cos(angle) * radius If first first = False firstX = x + offsetX firstY = y + offsetY lastX = firstX lastY = firstY Else thisX = x + offsetX thisY = y + offsetY DrawLine(lastX, lastY, thisX, thisY) lastX = thisX lastY = thisY EndIf angle += angleStep Next DrawLine(lastX, lastY, firstX, firstY) End You can leave the detail parameter out if you just want to draw a circle. detail is the number of lines that will be drawn so you can draw polygons with this function too. |
| ||
Bresenham performs in most cases faster and better, because it draws the exact amount of pixels which is necessary to close the radius. Only on very big circles you will see advantages with a 5°-steps method. Additional you can speed up this method, because you never need to draw all 360° as you see in the Bresenham. Also the 5°-steps method will be faster if you only draw 45° and mirror all this results 8 times. |
| ||
Bresenham does not use Sin() and Cos(). If you draw 72 lines for 5° steps, each line is still made up of points, so I think the Bresenham Circle is the simplest. The amount of points required to draw a 360° circle shouldn't differ much. You just can't take fewer points for the same closed circle. Could be an advantage when the lines/points get drawn with hardware acceleration, if available for a specific targets. |
| ||
And pre-creating a float array of a circle-like polygon and drawing it using DrawPoly with the given translate and scale? wouldn't this be faster taking into account that it is pre-calculated? |
| ||
The only bit that's precalculated is the initial positions. You're still translating and scaling each time. The actual polygon draw might well be faster though. I think everyone is getting a bit carried away here with theorising. As usual, Monkey is a cross-platform language. What's fast on one target may be slow on another. Also, this isn't 1990 so just thinking about CPU and avoiding trig isn't necessarily going to find the fastest method considering the way GL rendering works. Frankly, unless you're going circle crazy I doubt there's much noticeable difference between a doing some trig and getting a reasonable number of lines and doing Bresenham's on most of the targets. |
| ||
On HTML5 I created a native line circle function using the built in arc method. Seems very nippy. |
| ||
I think everyone is getting a bit carried away here with theorising. Yes! That's fun! |