Я уже некоторое время работаю над этой проблемой, и пока не могу найти хорошее решение.
Проблема: у меня упорядоченный список из трех (или более)2D точки, и я хочу обвести их с помощью кубической кривой Безье таким образом, чтобы она «хорошо выглядела».Часть «хорошо выглядит» довольно проста: я просто хочу, чтобы клин во второй точке сглаживался (например, кривая не сгибается назад).Итак, учитывая три точки, куда следует поместить две контрольные точки, которые будут окружать вторую точку в триплете при рисовании кривой.
Мое решение пока следующее, но оно неполное.Идея также может помочь передать внешний вид, который мне нужен.
Учитывая три точки, (x1, y1), (x2, y2), (x3, y3).Возьмем круг, вписанный каждой тройкой точек (если они коллинеарны, мы просто рисуем прямую линию между ними и идем дальше).Возьмите линию касательную к этому кругу в точке (x2, y2) - мы разместим контрольные точки, которые окружают (x2, y2) на этой касательной линии.
Это последняя часть, на которой я застрял,У меня проблема в том, чтобы найти способ разместить две контрольные точки на этой касательной линии - у меня есть достаточно хорошая эвристика относительно того, как далеко от (x2, y2) на этой линии они должны быть, но, конечно, естьдве точки на этой линии, которые находятся на таком расстоянии.Если мы вычислим один в «неправильном» направлении, кривая зациклится на себе.
Чтобы найти центр круга, описанного тремя точками (если любая из точек имеет одинаковое значение x, простоизмените порядок точек в приведенном ниже расчете):
double ma = (point2.y - point1.y) / (point2.x - point1.x);
double mb = (point3.y - point2.y) / (point3.x - point2.x);
CGPoint c; // Center of a circle passing through all three points.
c.x = (((ma * mb * (point1.y - point3.y)) + (mb * (point1.x + point2.x)) - (ma * (point2.x + point3.x))) / (2 * (mb - ma)));
c.y = (((-1 / ma) * (c.x - ((point1.x + point2.x) / 2))) + ((point1.y + point2.y) / 2));
Затем, чтобы найти точки на касательной, в этом случае найдите контрольную точку для кривой, идущей от точки 2 к точке 3:
double d = ...; // distance we want the point. Based on the distance between
// point2 and point3.
// mc: Slope of the line perpendicular to the line between
// point2 and c.
double mc = - (c.x - point2.x) / (c.y - point2.y);
CGPoint tp; // point on the tangent line
double c = point2.y - mc * point2.x; // c == y intercept
tp.x = ???; // can't figure this out, the question is whether it should be
// less than point2.x, or greater than?
tp.y = mc * tp.x + c;
// then, compute a point cp that is distance d from point2 going in the direction
// of tp.