jameswelle jameswelle - 1 month ago 14
C# Question

How does GraphicsPath.AddArc use the startAngle and sweepAngle parameters?

I am trying to use System.Drawing.Drawing2D.GraphicsPath.AddArc to draw an arc of an ellipse starting at 0 degrees and sweeping to 135 degrees.

The issue I am running in to is that for an ellipse, the arc drawn does not match up with what I would expect.

For example, the following code generates the image below. The green circles are where I would expect the end points of the arc to be using the formula for a point along an ellipse. My formula works for circles but not for ellipses.

Does this have something to do with polar versus Cartesian coordinates?

private PointF GetPointOnEllipse(RectangleF bounds, float angleInDegrees)
float a = bounds.Width / 2.0F;
float b = bounds.Height / 2.0F;

float angleInRadians = (float)(Math.PI * angleInDegrees / 180.0F);

float x = (float)(( bounds.X + a ) + a * Math.Cos(angleInRadians));
float y = (float)(( bounds.Y + b ) + b * Math.Sin(angleInRadians));

return new PointF(x, y);

private void Form1_Paint(object sender, PaintEventArgs e)
Rectangle circleBounds = new Rectangle(250, 100, 500, 500);
e.Graphics.DrawRectangle(Pens.Red, circleBounds);

System.Drawing.Drawing2D.GraphicsPath circularPath = new System.Drawing.Drawing2D.GraphicsPath();
circularPath.AddArc(circleBounds, 0.0F, 135.0F);
e.Graphics.DrawPath(Pens.Red, circularPath);

PointF circlePoint = GetPointOnEllipse(circleBounds, 135.0F);
e.Graphics.DrawEllipse(Pens.Green, new RectangleF(circlePoint.X - 5, circlePoint.Y - 5, 10, 10));

Rectangle ellipseBounds = new Rectangle(50, 100, 900, 500);
e.Graphics.DrawRectangle(Pens.Blue, ellipseBounds);

System.Drawing.Drawing2D.GraphicsPath ellipticalPath = new System.Drawing.Drawing2D.GraphicsPath();
ellipticalPath.AddArc(ellipseBounds, 0.0F, 135.0F);
e.Graphics.DrawPath(Pens.Blue, ellipticalPath);

PointF ellipsePoint = GetPointOnEllipse(ellipseBounds, 135.0F);
e.Graphics.DrawEllipse(Pens.Green, new RectangleF(ellipsePoint.X - 5, ellipsePoint.Y - 5, 10, 10));

alt text


GraphicsPath.AddArc does exactly what you ask it to do -- it the arc up to a line projecting from the ellipse center, at an exact angle of 135 degrees clockwise from the x axis.

Unfortunately, this doesn't help when you're using the angle as a direct proportion of a pie chart slice you want to draw. To find out the angle B you need to use with AddArc, given an angle A that works on a circle, in radians, use:

B = Math.Atan2(sin(A) * height / width, cos(A))

Where width and height are those of the ellipse.

In your sample code, try adding the following at the end of Form1_Paint:

ellipticalPath = new System.Drawing.Drawing2D.GraphicsPath();
    (float) (180.0 / Math.PI * Math.Atan2(
        Math.Sin(135.0 * Math.PI / 180.0) * ellipseBounds.Height / ellipseBounds.Width,
        Math.Cos(135.0 * Math.PI / 180.0))));
e.Graphics.DrawPath(Pens.Black, ellipticalPath);

The result should look as follows: alt text