[...]

Here you can see that the green line doesn't reach as far around the arc

as

the red line, despite the fact that both are, in theory, drawing an arc

through 315Âº. It is this effect, that the DrawArc method seems to draw

"short", of which I would be interested in hearing an explanation.

Ahhh...I understand the question now.

The answer is that your ellipse function and what Windows does aren't the

same (obviously). More specifically, the algorithm you've used assumes

your ellipse was once a circle that's been squashed, and you are

designating the degrees in the coordinate space of the original perfectly

round circle. Of course, when you squash the circle in one dimension or

the other to get an ellipse, you wind up squashing your angles too.

Windows, on the other hand, is doing a true polar coordinate clipping of a

circle to obtain the arc. That is, the beginning and ending point of the

arc, specified in polar coordinates, assumes that you're really drawing an

ellipse, but designating the start and end points in an unmodified polar

coordinate space. That is, take the original ellipse, find where it

intersects with lines drawn from the center outward at the given angles,

and draw the arc between those lines.

IMHO, the Windows version is more mathematically correct, but I feel that

the main point is to decide which is more appropriate to your needs and

use it consistently. Obviously though, you can't mix and match without

seeing the discrepancy you're asking about.

For what it's worth, here's yet another version of your code (see below)

that I hopes makes it much clearer what's going on. I added a lot more

stuff, so that you can use the arrow keys to adjust the limits of your

arc, as well as drawing a perfectly round circle so that you can compare

the angles for that circle with the angles for the ellipse. In

particular, note that the version of the ellipse drawn with DrawArc()

aligns perfectly with the circle, while your ellipse calculate lags and

leads the circle depending on where in the arc you are.

Hope that helps.

Pete

Here's the code:

protected override void OnPaint(PaintEventArgs e)

{

base.OnPaint(e);

Draw(ClientRectangle, e.Graphics);

}

protected override void OnResize(EventArgs e)

{

base.OnResize(e);

Invalidate();

}

private float _degreesTotal = 360.0f;

protected override bool ProcessDialogKey(Keys keyData)

{

bool fHandled = false;

switch (keyData)

{

case Keys.Left:

_degreesTotal -= 1.0f;

fHandled = true;

break;

case Keys.Right:

_degreesTotal += 1.0f;

fHandled = true;

break;

}

if (fHandled)

{

if (_degreesTotal < 0)

{

_degreesTotal += 360.0f;

}

else if (_degreesTotal >= 360.0f)

{

_degreesTotal -= 360.0f;

}

Invalidate();

}

return base.ProcessDialogKey(keyData);

}

private Point RectCenter(Rectangle r)

{

return new Point((r.Left + r.Right) / 2, (r.Top + r.Bottom) /

2);

}

private PointF PointFromEllipse(Rectangle bounds, float degrees)

{

float a = bounds.Width / 2.0f;

float b = bounds.Height / 2.0f;

float rad = ((float)Math.PI / 180.0f) * degrees;

Point ptCenter = RectCenter(bounds);

float x = ptCenter.X + (a * (float)Math.Cos(rad));

float y = ptCenter.Y + (b * (float)Math.Sin(rad));

return new PointF(x, y);

}

private void Draw(Rectangle rect, Graphics g)

{

rect.Inflate(-5, -5);

Rectangle rectSquare;

Point ptCenter = RectCenter(rect);

int dxySquare = Math.Min(rect.Width, rect.Height);

rectSquare = new Rectangle(new Point(ptCenter.X - dxySquare /

2, ptCenter.Y - dxySquare / 2), new Size(dxySquare, dxySquare));

g.DrawLine(Pens.Black, rect.Location, new Point(rect.Left

+ rect.Width, rect.Top + rect.Height));

g.DrawLine(Pens.Black, new Point(rect.Left + rect.Width,

rect.Top), new Point(rect.Left, rect.Top + rect.Height));

g.DrawString("_degreesTotal: " + _degreesTotal.ToString(),

Font, Brushes.Black, 10.0f, 10.0f);

using (Pen penGreen = new Pen(Color.Green, 3.0f))

{

g.DrawArc(penGreen, rect, 0, _degreesTotal);

g.DrawArc(penGreen, rectSquare, 0, _degreesTotal);

}

PointF ptPrevSquare = PointFromEllipse(rectSquare, 0),

ptPrev = PointFromEllipse(rect, 0);

for (int i = 1; i <= _degreesTotal; i++)

{

PointF ptSquare = PointFromEllipse(rectSquare, i),

pt = PointFromEllipse(rect, i);

g.DrawLine(Pens.Red, pt, ptPrev);

g.DrawLine(Pens.Red, ptSquare, ptPrevSquare);

ptPrev = pt;

ptPrevSquare = ptSquare;

}

}