С# Рисованная дуга с тремя точками

Мне нужно рисовать дугу с помощью 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);

Ответ 1

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

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

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

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

Изменить: этот метод найдет круговую дугу и не обязательно дугу "наилучшего соответствия" в зависимости от вашего ожидаемого поведения конечной точки.

Ответ 2

Вы пробовали метод 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