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
End
Untested, 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! |