February 2012
Get Version

January 2007
Bezier Text

December 2005
» Rotated Ellipses

December 2004
PDF Page Count

January 2003
Boolean Blues

March 2002
Networked Drives

January 2002
Treeview Troubles
Appending to Exe's

Freeware Components
 Rotated Ellipses December 2005 There is no native Windows function to draw ellipses at rotated angles, so every programmer has to do the drawing themselves. It took me a while to find some decent code on the internet. However, I did find this excellent C++ code which I've used as the basis of my Delphi code below. The rotated ellipse is constructed by a series of 4 bezier curves. The codeguru site linked to above also has a good summary of other ways to draw rotated ellipses so I wont repeat here what was said there. Although not demonstrated in the code below, a reasonable approximation of the bounding rectangle of the rotated ellipse - aligned with the x-y axis - can be derived by finding both the minimum and maximum values for x and y from the 13 points used to define the bezier curves. The calling function Button1Click() also demonstrates how to assign a record constant, something newcomers to Delphi may not be aware is possible. You can see where I've used this function if you download my collection of 16 Delphi Draw Objects components here. Anyhow, here's my Delphi function DrawRotatedEllipse().

Code snippet ...
 ```uses Math; procedure RotatePts(var pts: array of TPoint; origin: TPoint; radians: single); var i,x,y: integer; cosAng, sinAng: single; begin cosAng := cos(radians); sinAng := sin(radians); for i := low(pts) to high(pts) do begin x := pts[i].X - origin.X; y := pts[i].Y - origin.Y; pts[i].X := round((x * cosAng) - (y * sinAng)) + origin.X; pts[i].Y := round((x * sinAng) + (y * cosAng)) + origin.Y; end; end; //-------------------------------------------------------------- //see - http://www.codeguru.com/Cpp/G-M/gdi/article.php/c131 procedure DrawRotatedEllipse(canvas: TCanvas; rec: TRect; degrees: integer); const //Magic constant = 2/3*(sqrt(2)-1) offset: single = 0.27614237; var midx, midy, offx, offy: integer; pts: array [0..12] of TPoint; radians: single; begin degrees := degrees mod 360; if degrees < 0 then inc(degrees, 360); radians := degrees *pi / 180; //if there's no rotation, use the standard Windows function if radians = 0 then canvas.Ellipse(rec) else begin with rec do begin dec(right); dec(bottom); //empirically this seems better midx := (right + left) div 2; midy := (bottom + top) div 2; offx := round((right - left) * offset); offy := round((bottom - top) * offset); pts[0] := Point(left, midy); pts[1] := Point(left, midy - offy); pts[2] := Point(midx - offx, top); pts[3] := Point(midx, top); pts[4] := Point(midx + offx, top); pts[5] := Point(right, midy - offy); pts[6] := Point(right, midy); pts[7] := Point(right, midy + offy); pts[8] := Point(midx + offx, bottom); pts[9] := Point(midx, bottom); pts[10] := Point(midx - offx, bottom); pts[11] := Point(left, midy + offy); pts[12] := pts[0]; //rotate all points about the ellipse center ... RotatePts(pts, Point(midx,midy), radians); end; with canvas do begin beginPath(Handle); canvas.PolyBezier(pts); EndPath(Handle); if canvas.Brush.Style = bsClear then StrokePath(Handle) else StrokeAndFillPath(Handle); end; end; end; //-------------------------------------------------------------- procedure TForm1.Button1Click(Sender: TObject); const rec: TRect = (left:100; top:100; right:300; bottom:200); begin canvas.Pen.Width := 2; canvas.Brush.Color := clWhite; DrawRotatedEllipse(Canvas, rec, 0); //now overlay the same sized ellipse, //but rotated at several angles ... canvas.Brush.Style := bsClear; DrawRotatedEllipse(Canvas, rec, -45); DrawRotatedEllipse(Canvas, rec, 45); DrawRotatedEllipse(Canvas, rec, 90); end; ```