Нарисуйте квадратичную кривую Безье через три заданные точки
У меня три точки в 2D, и я хочу провести через них квадратичную кривую Безье. Как вычислить среднюю контрольную точку (x1
и y1
как в quadTo)? Я знаю линейную алгебру из колледжа, но мне нужна простая помощь.
Как я могу вычислить среднюю контрольную точку так, чтобы она также проходила через нее?
Ответы
Ответ 1
Пусть P0, P1, P2 - контрольные точки, а Pc - ваша фиксированная точка, через которую вы хотите пройти кривую.
Тогда кривая Безье определяется выражением
P(t) = P0*t^2 + P1*2*t*(1-t) + P2*(1-t)^2
... где t идет от нуля до 1.
На ваш вопрос бесконечное количество ответов, так как оно может пройти через вашу точку для любого значения t... Так что просто выберите один, например t = 0,5, и решите для P1:
Pc = P0*.25 + P1*2*.25 + P2*.25
P1 = (Pc - P0*.25 - P2*.25)/.5
= 2*Pc - P0/2 - P2/2
Здесь значения "P" являются (x, y) парами, поэтому просто применяйте уравнение один раз для x и один раз для y:
x1 = 2*xc - x0/2 - x2/2
y1 = 2*yc - y0/2 - y2/2
... где (xc, yc) - это точка, которую вы хотите пройти, (x0, y0) - начальная точка, а (x2, y2) - конечная точка. Это даст вам Безье, проходящее через (xc, yc) при t = 0,5.
Ответ 2
Я использовал ответ Nemos в моем приложении JavaFX, но моя цель состояла в том, чтобы нарисовать кривую, чтобы визуальная точка поворота кривой всегда соответствовала выбранной фиксированной (CP).
CP = ControlPoint
SP = StartPoint
EP = EndPoint
BP (t) = переменная точка на BeziérCurve, где t находится между 0 и 1
Чтобы достичь этого, я сделал переменную t (not fix 0.5). Если выбранная точка CP больше не находится посередине между SP и EP, вам нужно немного поменять ее вверх или вниз.
В качестве первого шага вам нужно знать, находится ли CP ближе к SP или EP:
Пусть distanceSP - расстояние между CP и SP
и distanceEP - расстояние между CP и EP
то я определяю соотношение как:
ratio = (distanceSP - distanceEP) / (distanceSP + distanceEP);
Теперь мы будем использовать это для изменения t вверх и вниз:
ratio = 0.5 - (1/3) * ratio;
Примечание: это все еще приближение, и 1/3 выбирается с помощью попытки и ошибки.
Вот моя Java-функция:
(Point2D - класс JavaFX)
private Point2D adjustControlPoint(Point2D start, Point2D end, Point2D visualControlPoint) {
// CP = ControlPoint, SP = StartPoint, EP = EndPoint, BP(t) = variable Point on BeziérCurve where t is between 0 and 1
// BP(t) = SP*t^2 + CP*2*t*(1-t) + EP*(1-t)^2
// CP = (BP(t) - SP*t^2 - EP*(1-t)^2) / ( 2*t*(1-t) )
// but we are missing t the goal is to approximate t
double distanceStart = visualControlPoint.distance(start);
double distanceEnd = visualControlPoint.distance(end);
double ratio = (distanceStart - distanceEnd) / (distanceStart + distanceEnd);
// now approximate ratio to be t
ratio = 0.5 - (1.0 / 3) * ratio;
double ratioInv = 1 - ratio;
Point2D term2 = start.multiply( ratio * ratio );
Point2D term3 = end.multiply( ratioInv * ratioInv );
double term4 = 2 * ratio * ratioInv;
return visualControlPoint.subtract(term2).subtract(term3).multiply( 1 / term4);
}
Надеюсь, это поможет.
Ответ 3
Если вам не нужна точная средняя точка, скорее вы хотите любое значение для t (от 0 до 1), уравнение равно:
controlX = pointToPassThroughX/t - startX*t - endX*t;
controlY = pointToPassThroughY/t - startY*t - endY*t;
Конечно, это также будет работать для средней точки, просто установите t равным 0,5. Просто!: -)
Ответ 4
Надеюсь, вам пригодится моя статья о квадратичном Безье через три точки, но с "средней" точкой в "лучшем месте", где "изгибается кривая".
https://microbians.com/math/Gabriel_Suchowolski_Quadratic_bezier_through_three_points_and_the_-equivalent_quadratic_bezier_(theorem)-.pdf