C # Рисование дуги с 3 точками - PullRequest
10 голосов
/ 24 мая 2010

Мне нужно нарисовать дугу с использованием GraphicsPath и иметь начальную, среднюю и конечную точки.Дуга должна пройти по ним.

Я пытался .DrawCurve и .DrawBezier, но результат не совсем дуги.

Что я могу сделать?

РЕШЕНИЕ:

После пары часов написания кода мне удалось нарисовать то, что я хотел, с помощью этого алгоритма (укажите 3 точки a, b, c и путь GraphicsPath):

double d = 2 * (a.X - c.X) * (c.Y - b.Y) + 2 * (b.X - c.X) * (a.Y - c.Y);
double m1 = (Math.Pow(a.X, 2) - Math.Pow(c.X, 2) + Math.Pow(a.Y, 2) - Math.Pow(c.Y, 2));
double m2 = (Math.Pow(c.X, 2) - Math.Pow(b.X, 2) + Math.Pow(c.Y, 2) - Math.Pow(b.Y, 2));
double nx = m1 * (c.Y - b.Y) + m2 * (c.Y - a.Y);
double ny = m1 * (b.X - c.X) + m2 * (a.X - c.X);
double cx = nx / d;
double cy = ny / d;
double dx = cx - a.X;
double dy = cy - a.Y;
double distance = Math.Sqrt(dx * dx + dy * dy);
Vector va = new Vector(a.X - cx, a.Y - cy);
Vector vb = new Vector(b.X - cx, b.Y - cy);
Vector vc = new Vector(c.X - cx, c.Y - cy);
Vector xaxis = new Vector(1, 0);
float startAngle = (float)Vector.AngleBetween(xaxis, va);
float sweepAngle = (float)(Vector.AngleBetween(va, vb) + Vector.AngleBetween(vb, vc));
path.AddArc(
    (float)(cx - distance), (float)(cy - distance),
    (float)(distance * 2), (float)(distance * 2), 
    startAngle, sweepAngle);

Ответы [ 2 ]

6 голосов
/ 24 мая 2010

Я бы использовал DrawArc(), как предложено ANC_Michael. Чтобы найти дугу, которая проходит через 3 точки, вы хотите вычислить окружность треугольника, образованного точками.

Как только у вас будет окружность, вычислите ограничивающий прямоугольник для круга, который нужно использовать с DrawArc, используя минимальные / максимальные размеры (центр +/- радиус). Теперь вычислите ваши начальный и конечный углы, переместив точки так, чтобы окружность была центрирована относительно начала координат (переведите -circumcenter), и возьмите скалярное произведение нормализованных векторов начала и конца с осью X:

double startAngle = Math.Acos(VectorToLeftPoint.Dot(XAxis));
double stopAngle = Math.Acos(VectorToRightPoint.Dot(XAxis));

Обратите внимание, что DrawArc ожидает углов по часовой стрелке от оси X, поэтому вы должны добавить Math.PI, если вычисленный вектор находится выше оси X. Этого должно быть достаточно, чтобы позвонить DrawArc().

Редактировать: Этот метод найдет круговую дугу и не обязательно является "наиболее подходящей" дугой в зависимости от ожидаемого поведения конечной точки.

0 голосов
/ 24 мая 2010

Вы пробовали метод DrawArc и проверяли, можете ли вы каким-либо образом манипулировать своими 3 точками?

возможно

Pen blackPen= new Pen(Color.Black, 3);
// Create rectangle to bound ellipse.
Rectangle rect = new Rectangle(initial x, initial y, final x, median y);
// Create start and sweep angles on ellipse.
float startAngle =  0F;
float sweepAngle = 270.0F;
// Draw arc to screen.
e.Graphics.DrawArc(blackPen, rect, startAngle, sweepAngle);

http://msdn.microsoft.com/en-us/library/system.drawing.graphics.drawarc%28VS.71%29.aspx

...