DrawOval

BlitzMax Forums/BlitzMax Beginners Area/DrawOval

Is it possible to paint a circle without filling?

Example:
------------------------------
Graphics 800,600,32,60
Setcolor 100,100,100
DrawOval 100,100,50,50
Flip
While Not KeyHit(KEY_ESCAPE)
Wend
End
------------------------------

This code draw a filled circle on the screen.
But i want to draw a circle without filling.
I have searched a possibility but I dont found.
Hopefull waiting for an answer...

Thommes (t.carstens@...)

You have two ways of doing this, you can use lines or points. THere arn't any draw unfilled shapes.

Make a black outline circle on an image with centre as alpha colour, then scale/rotate/sethanble and paste it.

here is a circle routine I just made using Bresenham Algorith :

'
' program : circle drawing lib using Bresenham algrorith
' using the circle drawint algorithm at:
'    <a href="http://www.gamedev.net/reference/articles/article767.asp" target="_blank">http://www.gamedev.net/reference/articles/article767.asp</a>
' created by  Jesse Perez    8/20/2006
'
' draws a circle with:
'
' offsetx = center x
' offsety = center y
' Radius = circle radius in pixels
'
' note: no clipping is done so may become extremely slow if excessibly large circles are drawn. 
' also: also if the screen resolution is not proportionally correct it will not look round.


Type Tcircle

	Method draw(OffsetX#,OffsetY#,Radius#) 
		If Radius <= 0 Return 
		If (offsetx-radius) > GraphicsWidth()  Return  
		If (offsety-radius) > GraphicsHeight()  Return
		If (offsetx+radius) < 0 Then Return
		If (offsety+radius) < 0 Then Return
		Local x = 0
		Local d = 3-(2*Radius)						
		Local y=Radius
		While x<y
			If d < 0 Then
				d = d + (4 * x) + 6
			Else
				d = d + 4 * (x - y) + 10
				y = y - 1
			End If
			Plot(offsetX + X, OffsetY + Y)
			Plot(OffsetX + X, OffsetY - Y)
			Plot(OffsetX - X, OffsetY + Y)
			Plot(OffsetX - X, OffsetY - Y)
			Plot(OffsetX + Y, OffsetY + X)
			Plot(OffsetX + Y, OffsetY - X)
			Plot(OffsetX - Y, OffsetY + X)
			Plot(OffsetX - Y, OffsetY - X)
			x=x+1
		Wend
	End Method
End Type

Graphics 800,600
Local circle:Tcircle= New Tcircle
For Local a = 1 To 10
circle.draw 100+Rand(0,600),100+Rand(0,400),Rand(10,100)
Next
Flip()
WaitKey()


I hope it can help.

Great job!!
It works fine and Iam verry happy!!
THANX!!!!

Try this code:

http://www.blitzbasic.com/codearcs/codearcs.php?code=1477

here are both routines incorporated in to a single user friendly file:

'**********************************************************************************
'*
'* This draws an unfilled ellipse one pixel at a time And uses only integer math 
'* To do it, except For one small part where two lines need To do a floating point 
'* calculation. Even so, there is no trigonometry involved. The ellipse is Not
'* rotatable unless the output Method (ie Plot) can be drawn with rotated coordinates
'* as part of the Graphics system (ie rotating the camera, etc).
'*  
'* xCenter = oval center X
'* yCenter = oval center Y
'* draw(integer width in pixels,integer height in pixels)
'*
'**********************************************************************************
Type Tobject
	Field xCenter:Int
	Field yCenter:Int
	Global c$[]=["OVAL","CIRCLE"]
	Method Draw(radiusX:Int,radiusY:Int=Null) Abstract
End Type
Type Toval Extends Tobject
	Method Draw(radiusX:Int,radiusY:Int=Null)
		
		Local Rx:Int,Ry:Int
		Local p:Int,px:Int,py:Int,x:Int,y:Int
		Local Rx2:Int,Ry2:Int,twoRx2:Int,twoRy2:Int
		Local pFloat:Float
		
		Rx=Abs(radiusX)
		Ry=Abs(radiusY)
		Rx2=Rx*Rx
		Ry2=Ry*Ry
		twoRx2=Rx2 Shl 1
		twoRy2=Ry2 Shl 1
		'Region 1
		x=0
		y=Ry
		Plot xCenter+x,yCenter+y
		Plot xCenter-x,yCenter+y
		Plot xCenter+x,yCenter-y
		Plot xCenter-x,yCenter-y
		pFloat=(Ry2-(Rx2*Ry))+(0.25*Rx2)
		p=Int(pFloat)
		If pFloat Mod 1.0>=0.5 Then p:+1
			px=0
			py=twoRx2*y
			While px<py
				x:+1
        		px:+twoRy2
           		If p>=0
					y:-1
					py:-twoRx2
				EndIf
				If p<0 Then p:+Ry2+px Else p:+Ry2+px-py
				Plot xCenter+x,yCenter+y
				Plot xCenter-x,yCenter+y
				Plot xCenter+x,yCenter-y
				Plot xCenter-x,yCenter-y
			Wend
			'Region 2
			pFloat=(Ry2*(x+0.5)*(x+0.5))+(Rx2*(y-1.0)*(y-1.0))-(Rx2*(Float(Ry2)))
			p=Int(pFloat)
			If pFloat Mod 1.0>=0.5 Then p:+1
			While y>0
				y:-1
				py:-twoRx2
				If p<=0
					x:+1
					px:+twoRy2
				EndIf
				If p>0 Then p:+Rx2-py Else p:+Rx2-py+px
				Plot xCenter+x,yCenter+y
				Plot xCenter-x,yCenter+y
				Plot xCenter+x,yCenter-y
				Plot xCenter-x,yCenter-y
			Wend
	End Method
End Type
'
' program : circle drawing lib using Bresenham algrorith
' using the circle draw int algorithm at:
'    <a href="http://www.gamedev.net/reference/articles/article767.asp" target="_blank">www.gamedev.net/reference/articles/article767.asp</a>
' created by  Jesse Perez    8/20/2006
'
' draws a circle with:
'
' xCenter = center x
' yCenter = center y
' circle(RadiusX,radiusY=Null) 'radiusx,radiusy = circle radius in pixels radius Y is optional
' but will calculate radius from the x axis only.
'
' note: no clipping is done so may become extremely slow if excessibly large circles are drawn. 
' also: also if the screen resolution is not proportionally correct it will not look round.


Type Tcircle Extends Tobject

	Method draw(radiusX:Int,radiusY:Int=Null) 
		Local radius=Sqr(radiusX*radiusX+radiusY*radiusY) 
		If (xCenter-radius) > GraphicsWidth()  Return  
		If (yCenter-radius) > GraphicsHeight()  Return
		If (xCenter+radius) < 0 Then Return
		If (yCenter+radius) < 0 Then Return
		Local x = 0
		Local d = (2*Radius)						
		Local y=Radius
		While x<y
			If d < 0 Then
				d = d + (4 * x) + 6
			Else
				d = d + 4 * (x - y) + 10
				y = y - 1
			End If
			Plot(xCenter + X, yCenter + Y)
			Plot(xCenter + X, yCenter - Y)
			Plot(xCenter - X, yCenter + Y)
			Plot(xCenter - X, yCenter - Y)
			Plot(xCenter + Y, yCenter + X)
			Plot(xCenter + Y, yCenter - X)
			Plot(xCenter - Y, yCenter + X)
			Plot(xCenter - Y, yCenter - X)
			x=x+1
		Wend
	End Method
End Type

Graphics 800,600
Local shape:Tobject[2]
Local index
shape[0]=New Toval
shape[1]=New tcircle
For index = 0 To 1
	shape[index].xCenter = GraphicsWidth()/2
	shape[index].yCenter = GraphicsHeight()/2
Next
index=0 	
Repeat

	If MouseHit(2)Then 
		index = 1 - index
		shape[index].xCenter=GraphicsWidth()/2
		shape[index].yCenter=GraphicsHeight()/2
		
	EndIf

	DrawText "Press the Right mouse Button",10,10
	DrawText "to switch from drawing "+shape[index].c$[index]+"S",10,25
	DrawText "to drawing "+shape[index].c$[1-index]+"S",10,40

	If MouseDown(1)
		shape[index].xCenter=MouseX()
		shape[index].YCenter=MouseY()
	EndIf
	shape[index].draw(shape[index].xCenter-MouseX(),shape[index].yCenter-MouseY())
	Flip(1)
	Cls
Until KeyHit(KEY_ESCAPE	)


Here's one that someone posted a while back. Should be faster since it uses GL Lines instead of plot.
Function DrawOvalUnfilled(x0#,y0#,w#,h#)
	Local xr#=(w)*.5
	Local yr#=(h)*.5
	Local segs=Abs(xr)+Abs(yr)
		
	segs=Max(segs,12)&~3

	x0:+xr
	y0:+yr

	Local px#,py#

	glBegin GL_LINES
	For Local i=0 Until segs+1
		Local th#=i*360#/segs
		Local x#=x0+Cos(th)*xr
		Local y#=y0-Sin(th)*yr
		If i>0
			glVertex2f px,py
			glVertex2f x,y
		EndIf
		px# = x
		py# = y
	Next
	glEnd
End Function


I am ignorant to openGL. TeaVirus. Can you give an example to show me how it works. I tried it like below but I can't get it to work:
Strict

Function DrawOvalUnfilled(x0#,y0#,w#,h#)
	Local xr#=(w)*.5
	Local yr#=(h)*.5
	Local segs=Abs(xr)+Abs(yr)
		
	segs=Max(segs,12)&~3

	x0:+xr
	y0:+yr

	Local px#,py#

	glBegin GL_LINES
	For Local i=0 Until segs+1
		Local th#=i*360#/segs
		Local x#=x0+Cos(th)*xr
		Local y#=y0-Sin(th)*yr
		If i>0
			glVertex2f px,py
			glVertex2f x,y
		EndIf
		px# = x
		py# = y
	Next
	glEnd
End Function
SetGraphicsDriver GLGraphicsDriver()

Graphics 640,480
glClear GL_COLOR_BUFFER_BIT
drawovalunfilled(300,300,50,50)
Flip()
WaitKey()


It's your projection matrix. The default is -1 to +1

call
gluOrtho2D(0,640,480,0) ; left/right/bottom/top
just after your Graphics call, with your window sizes.

If you are using OpenGL it's as easy as changing the rendering mode. Like this:
SetGraphicsDriver GLMax2DDriver()
Graphics 640,480,0,0

Local wire:Int = False

Repeat

	If KeyHit(KEY_SPACE)
		wire = Not wire
		If wire
			glPolygonMode(GL_FRONT, GL_LINE)
		Else
			glPolygonMode(GL_FRONT, GL_FILL)
		EndIf
	EndIf

	SetColor Rand(100,255),Rand(100,255),Rand(100,255)
	DrawOval Rand(0,540),Rand(0,380),Rand(10,100),Rand(10,100)

	SetColor 255,255,255
	DrawText "Hit space to toggle line mode",0,0
	
	Flip

Until KeyHit(KEY_ESCAPE) Or AppTerminate()

End


Or you could do a Max2D version and forget about gl at all :-

Strict

Function DrawOvalUnfilled(x0#,y0#,w#,h#)
	Local xr#=(w)*.5
	Local yr#=(h)*.5
	Local segs=Abs(xr)+Abs(yr)
		
	segs=Max(segs,12)&~3
	x0:+xr
	y0:+yr

	Local px# = x0 + xr
	Local py# = y0

	For Local i=1 To segs
		Local th#=i*360#/segs
		Local x#=x0+Cos(th)*xr
		Local y#=y0-Sin(th)*yr
		DrawLine px,py, x, y
		px# = x
		py# = y
	Next
End Function

Graphics 640,480

drawovalunfilled(320,220,100,100)

Flip
WaitKey()


This version slightly optimised since it doesn't need check with an If statement for every line. (first point is precalculated).

It's easy to modify this if you want it to be centred at the point specified rather than be 'boxed' by the dimensions.