Drawing rotated ellipses, Please help.

BlitzMax Forums/BlitzMax Beginners Area/Drawing rotated ellipses, Please help.

Once again I've come across a problem that I need assistance with. The goal was to draw a rotated ellipse if a given width and height. My initial code could produce the ellipse with no rotation. The code simply used a for loop and n many points. I found that this method worked but the ellipses formed were not always symmetrical. This probably arises from the fact that a single center point was used regardless if the shape was odd or even in width and height. This is for a lower resolution game so odd shaped ellipses aren't passable and anti aliasing would ruin the feeling of the art. I really need symmetry in these n-gon circles.

The second problem is how to go about rotating the shapes at a given angle. I tinkered around a bit with my code but could never actually implement rotation.


The two problems at a glance:
1. Symmetry is important here with no anti aliasing
2. Rotation of the ellipse is unclear to me.

The code:
Function draw_oval(centerx#,centery#,width#,height#,rot#,n#)
	' draw the shape with a for loop
	Local angle#=360.0/n
	Local r1#=width/2.0
	Local r2#=height/2.0
	For Local i=0 To n-1
		Local x1=centerx+Cos(i*angle)*r1
		Local x2=centerx+Cos((i+1)*angle)*r1
		Local y1=centery+Sin(i*angle)*r2
		Local y2=centery+Sin((i+1)*angle)*r2
		DrawLine(x1,y1,x2,y2)
	Next
End Function


A picture showing both unsymmetrical ellipses and the intended result with rotation parameter. If you look at the quadrants of the ellipse you can see that 1 and 2 are more round that qudrants 3 and 4.



Something like:
Graphics 640,480
i=0
While Not KeyHit(KEY_ESCAPE)
	Cls
	SetColor 255,255,255
	SetHandle 150/2,50/2
	SetRotation i
	DrawOval 100,100,150,50
	i:+1
	If i=360 Then i=0
	Flip
Wend


No, the need to be n-gons and unfilled.

How about something like this

Function CreatePolygon:TImage(width#,height#,n#)
	' draw the shape with a for loop
	Local image:TImage=CreateImage(width+2,height+2,1,DYNAMICIMAGE|FILTEREDIMAGE)
	Local angle#=360.0/n
	Local r1=width/2.0
	Local r2=height/2.0
	Local centerx:Float = width / 2.0
	Local centery:Float = height / 2.0

	For Local i=0 To n-1
		Local x1=centerx+Cos(i*angle)*r1
		Local x2=centerx+Cos((i+1)*angle)*r1
		Local y1=centery+Sin(i*angle)*r2
		Local y2=centery+Sin((i+1)*angle)*r2
		DrawLine(x1 , y1 , x2 , y2)
	Next
	GrabImage Image , 0 , 0
	Return Image
End Function

Graphics 640 , 480
AutoMidHandle True
Local Polygon:TImage=CreatePolygon(100 , 200 ,33)
Local rot:Float = 0

Repeat
	Cls
	SetRotation rot
	DrawImage Polygon,320,240
	Flip
	Delay(2000)
	rot :+ 20.0
Until AppTerminate()


Thanks for all the help so far.

After a brief head explosion and some mopping of the floor I came up with this.
Function draw_oval(centerx#,centery#,width#,height#,rot#,n#)
	' draw the shape with a for loop
	
	
	Local angle#=360.0/n
	Local r1#=width/2.0
	Local r2#=height/2.0

	For Local i#=0 To n-1
	
		Local x1#=centerx+Cos(i*angle)*r1
		Local y1#=centery+Sin(i*angle)*r2
		Local x2#=centerx+Cos((i+1)*angle)*r1
		Local y2#=centery+Sin((i+1)*angle)*r2
		' get new data
		Local d1#=point_distance(centerx,centery,x1,y1)
		Local a1#=point_direction(centerx,centery,x1,y1)
		Local fx#=centerx+Cos(a1+rot)*d1
		Local fy#=centery+Sin(a1+rot)*d1
		
		Local d2#=point_distance(centerx,centery,x2,y2)
		Local a2#=point_direction(centerx,centery,x2,y2)
		Local fx2#=centerx+Cos(a2+rot)*d2
		Local fy2#=centery+Sin(a2+rot)*d2
	
		DrawLine(fx,fy,fx2,fy2)
		
	Next
End Function


The problem if drawing even width ovals remains. I don't know how to draw an oval with an even width. Using a central pixel always will make the width odd. If I tell it to draw a 32x32 oval I get a 31x31 oval.

Maybe a bit faster. Have not really tested it much though, so not sure about the even width problem you mention.

Function draw_oval(centerx#,centery#,width#,height#,rot#,n#)
	' draw the shape with a for loop

	Local angle# = 360.0/n
	Local r1# = width/2.0
	Local r2# = height/2.0
	
	Local crot# = Cos(rot)
	Local srot# = Sin(rot)

	Local lx# = centerx + r1 * crot
	Local ly# = centery + r1 * srot

	For Local i#=1 To n
	
		Local rx# = Cos(i*angle)*r1
		Local ry# = Sin(i*angle)*r2
		
		Local tx# = centerx+(rx * crot - ry * srot)
		Local ty# = centery+(rx * srot + ry * crot)
	
		DrawLine(lx,ly,tx,ty,False)
		
		lx=tx
		ly=ty
		
	Next
	
End Function


Ok thanks for the tip. I was double calculating I suppose...

I do NOT want to use rotated pixmaps for this because this bit of code is for a drawing program for artists. I need precision that tends to make symmetrical circles rather than mathmatically represented ones on pixels. Why do some circles produced lack symmetry? It's as if the plotting method truncates fractional pixel values rather than rounding them.

I am not sure exactly how it works in DirectX. However my driver offers an option to change the pixel centre so as far as I can see you can't be certain exactly which pixel will be filled for fractional values without running some sort of profiling routine...

Maybe there is some way to get DX to cough up that information?

Failing that perhaps the best option is to do your own rounding and truncation.

Look up a fully integer-based bresenham-like rotatable ellipse routine, it will be much quicker than doing all that trigonometry.

and much slower again due to the 2D through 3D implementation and the need to draw to pixmap and draw that one to the backbuffer.

You want to draw the ellipse rotating directly to the display in realtime, I take it?

You could assemble a vertex array and pass it to OpenGL