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

Answer

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();
ellipticalPath.AddArc(
    ellipseBounds,
    0.0F,
    (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

Comments