Code archives/Graphics/Draw Filled Ellipse Row by Row with Integer Math

This code has been declared by its author to be Public Domain code.

Download source code

Draw Filled Ellipse Row by Row with Integer Math by ImaginaryHuman2005
Draws a filled ellipse using (mostly) integer math, one row at a time. It doesn't use any trigonometry and only has two lines where it needs to set things up using a floating point operation. The rows are filled individually with separate calls to DrawRect. In this example a filled ellipse is drawn at the same time as a hollow ellipse, so there is some overlap of the pixels. Comment out the Plot calls to see only the filled ellipse, or comment out the DrawRect calls to see only the hollow ellipse.
'Midpoint ellipse algorithm

Strict
Graphics 640,480,0

Local xCenter:Int=320
Local yCenter:Int=240
Local Rx,Ry:Int
Local p,px,py,x,y,prevy:Int
Local Rx2,Ry2,twoRx2,twoRy2:Int
Local pFloat:Float
Repeat
	Cls
	If MouseDown(1)
		xCenter=MouseX()
		yCenter=MouseY()
	EndIf
	Rx=Abs(xCenter-MouseX())
	Ry=Abs(yCenter-MouseY())
	DrawText String(Rx)+" x "+String(Ry),20,20
	Rx2=Rx*Rx
	Ry2=Ry*Ry
	twoRx2=Rx2 Shl 1
	twoRy2=Ry2 Shl 1
	'Region 1
	x=0
	y=Ry
	SetColor $FF,$88,$00
	DrawRect xCenter-Rx,yCenter,Rx Shl 1,1
	SetColor $FF,$FF,$FF
	Plot xCenter+Rx,yCenter
	Plot xCenter-Rx,yCenter
	Plot xCenter,yCenter-Ry
	Plot xCenter,yCenter+Ry
	pFloat=(Ry2-(Rx2*Ry))+(0.25*Rx2)
	p=Int(pFloat + (Sgn(pFloat)*0.5))
	px=0
	py=twoRx2*y
	While px<py-1
		prevy=y
		x:+1
		px:+twoRy2
		If p>=0
			y:-1
			py:-twoRx2
		EndIf
		If p<0 Then p:+Ry2+px Else p:+Ry2+px-py
		If y<prevy And px<py-1
			SetColor $FF,$88,$00
			DrawRect xCenter-x,yCenter+y,x Shl 1,1
			DrawRect xCenter-x,yCenter-y,x Shl 1,1
			SetColor $FF,$FF,$FF
			Plot xCenter+x,yCenter+y
			Plot xCenter-x,yCenter+y
			Plot xCenter+x,yCenter-y
			Plot xCenter-x,yCenter-y
		EndIf
	Wend
	'Region 2
	pFloat=(Ry2*(x+0.5)*(x+0.5))+(Rx2*(y-1.0)*(y-1.0))-(Rx2*(Float(Ry2)))
	p=Int(pFloat + (Sgn(pFloat)*0.5))
	y:+1
	While y>1
		y:-1
		py:-twoRx2
		If p<=0
			x:+1
			px:+twoRy2
		EndIf
		If p>0 Then p:+Rx2-py Else p:+Rx2-py+px
		SetColor $FF,$88,$00
		DrawRect xCenter-x,yCenter+y,x Shl 1,1
		DrawRect xCenter-x,yCenter-y,x Shl 1,1
		SetColor $FF,$FF,$FF
		Plot xCenter+x,yCenter+y
		Plot xCenter-x,yCenter+y
		Plot xCenter+x,yCenter-y
		Plot xCenter-x,yCenter-y
	Wend
	Flip
Until KeyHit(KEY_ESCAPE)
End

Comments

N2005
I think it would have been more intelligent to have posted this as something like "Primitive Drawing Functions".

On another note, if you're calling 'Plot' a lot in these functions (and it seems you are), you might end up with a lot of slowdown if the calling function is called a lot.


Grey Alien2005
well the buffer can be locked as per my fast circle post in the code archives.


sswift2005
Oh yes, "Primitive Drawing Functions" is soooooo much more descriptive. :-)

Edit:

He's uisng PLOT? What's the point of even using integer math then? There's 90% of your slowdown there. Lock the buffer then use writepixelfast. Even if you lock the buffer before calling plot, it would still have to check to see if the buffer is locked.

Also, I question whether integer math would actually speed things up on modern PC's. But it probably wouldn't be slower than float either.

The main question is whether this function is faster than the internal Blitz functions for drawing those things? If it is, then Mark should be ashmed of himself! :-)

Code would still be useful for those instances where you need to draw circles AND know where all the pixels go though. Like if you wanted to draw a circle in an array. Or if you wanted to draw a textured circle.


Yan2005
He's uisng PLOT? What's the point of even using integer math then? There's 90% of your slowdown there. Lock the buffer then use writepixelfast.

This is BMAX code!
He just forgot to change the category. ;o)


Grey Alien2005
I didn't mean *just* lock the buffer, it implied using WritePixelFast, esp. if you check my fast circle post ...


ImaginaryHuman2005
Hi guys. This is not meant to be in the .bb code section, it is a BlitzMax routine, sorry.

Also since I am the one posting the code, I get to decide what it's called ;-)

However, I've now edited and uploaded a modified version which only fills each row once, so it's faster and works with other blend modes properly.

I do agree that Plot and DrawRect are not efficient ways of rendering the actual graphics. Those instructions are really irrelevant. You can use the data generated in whatever way you wish. I am using them with a custom bitmap type writing to main memory by writing Integers directly to memory pointers. I just put the plots etc in there to be friendly and to show that it works.


ImaginaryHuman2005
Thanks to BRL for moving this to the BMX section.


Code Archives Forum