2009-08-20 2 views
4

Я пытаюсь использовать System.Drawing.Drawing2D.GraphicsPath.AddArc, чтобы нарисовать дугу эллипса, начиная с 0 градусов и подметая до 135 градусов.Как GraphicsPath.AddArc использует параметры startAngle и sweepAngle?

Проблема, с которой я столкнулся, заключается в том, что для эллипса нарисованная дуга не соответствует тому, что я ожидаю.

Например, следующий код генерирует изображение ниже. Зеленые круги - это то место, где я ожидаю, что конечные точки дуги будут использовать формулу для точки вдоль эллипса. Моя формула работает для кругов, но не для эллипсов.

Связано ли это с полярными или декартовыми координатами?

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

ответ

3

GraphicsPath.AddArc делает именно то, что вы просите его сделать - это дуги до линии, проходящей от центра эллипса, точно под углом 135 градусов по часовой стрелке от оси х ,

К сожалению, это не поможет, когда вы используете угол в виде прямой доли кусочка круговой диаграммы, которую хотите нарисовать. Для того, чтобы выяснить, угол B необходимо использовать с AddArc, учитывая угол А, который работает по кругу, в радианах, используйте:

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

Где ширина и высота те эллипса.

В примере кода, попробуйте добавить следующую строку в конце 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); 

Результат должен выглядеть следующим образом: alt text http://img216.imageshack.us/img216/1905/arcs.png

+0

Прохладный! Это работает. Но я до сих пор не понимаю, почему это работает. Какова логика вашего расчета? Это имеет какое-либо отношение к полярным или декартовым координатам? – jameswelle

+0

GetPointOnEllipse находит точку в два этапа: 1. она находит точку на окружности круга с R = 1 под углом A от оси X, at (cos (A), sin (A)) 2. он преобразует точку с растягивающим преобразованием в (w * cos (A), h * sin (A)) Преобразование растяжения меняет угол! (представьте, какой угол был бы, если бы мы растянули круг очень широко) Чтобы найти новый угол B, обратите внимание, что tan (B) = y/x, и, следовательно, B = atan (y/x). Чтобы избежать деления на ноль, мы будем использовать B = atan2 (y, x) As (x, y) = (w * cos (A), h * sin (A)), получаем B = atan2 (h * sin (A), w * cos (A)) Разделить на w, чтобы получить B = atan2 (sin (A) * h/w, cos (A)) Имеет смысл? –

+0

Я не совсем понимаю ваше утверждение: «Трансформат растяжения меняет угол!». Из выходного изображения видно, что угол отличается. Но меня смущает формула для точки на эллипсе. Формула x = a cos (theta), y = b sin (theta).Означает ли тот факт, что он рисует в другой точке, означает, что измеряемый угол отличается от угла, который измеряется с помощью AddArc? Я нашел еще одну тему на эту тему. Кажется, это указывает на то, что имеет какое-то отношение к полярным коордам. http://bytes.com/topic/c-sharp/answers/665773-drawarc-ellipse-geometry-repost – jameswelle

2

enter image description here я путаюсь о том, как GraphicsPath.AddArc работал & Я не нашел подходящих диаграмм, поэтому я нарисовал один. На всякий случай, если кто-то еще страдает! http://imgur.com/lNBewKZ