-
Как нарисовать кривую Безье из 3 точек, чтобы она проходила точно через точки. К примеру рисуем параболу вверх, соответственно пиковая точка на кривой Безье будет ниже нужной нам точки. Как сделать чтобы пиковая точка проходила через нужную координату? Как ее рассчитать? Спасибо
-
Вопрос именно про то как ее рассчитать крайнюю точку. Нарисовать ее в FMX просто - CurveTo.
-
-
Я правильно понимаю, что, по приведённой ссылке, до раздела "Как провести кривую Безье через нужные точки?" ты не дочитал?
-
-
Точнее дочитал, но так и не понял как сделать интерполяцию.
-
Я сейчас пытаюсь разобраться с этим, так все сложно. Интерполяция, полиномы третьей степени, кубический сплайн дефекта 1. Поэтому задал вопрос здесь, может кто готовую формулу приведет.
-
Может помочь - функция аппроксимации кривой Безье 3-го порядка ломаной линией:
procedure TPolygon.AddBezier(X0, Y0, X1, Y1, X2, Y2, X3, Y3: Double; N: Integer); var X, Y, T, DT: Double; i: Integer; begin DT := 1 / N; T := DT; for i := 1 to N do begin X := (1-T)*(1-T)*(1-T)*X0 + 3*T*(1-T)*(1-T)*X1 + 3*T*T*(1-T)*X2 + T*T*T*X3; Y := (1-T)*(1-T)*(1-T)*Y0 + 3*T*(1-T)*(1-T)*Y1 + 3*T*T*(1-T)*Y2 + T*T*T*Y3; AddVertex(X, Y); T := T + DT; end; end;
-
-
-
Она не должна через управляющие проходить вроде. Это уже не Безье получается. А формулы вот:
type TFloatPoint = record X, Y: double; end;
//Прямая Безье //P = ((1-t) * A) + (t * B) function LinearBezier(P0, P1: TPoint; t: double): TFloatPoint; begin Result.X := ((1 - t) * P0.X) + (t * P1.X); Result.Y := ((1 - t) * P0.Y) + (t * P1.Y); end;
//Квадратичная Безье //P = (1-t)^2P0 + 2t(1-t)P1 + t^2P2
function QuadraticBezier(P0, P1, P2: TPoint; t: Double): TFloatPoint; begin Result.X := (((1 - t) * (1 - t)) * P0.X) + ((2 * t) * (1 - t) * P1.X) + ((t * t) * P2.X); Result.Y := (((1 - t) * (1 - t)) * P0.Y) + ((2 * t) * (1 - t) * P1.Y) + ((t * t) * P2.Y); end;
//Кубическая Безье //P = (1-t)^3P0 + 3t(1-t)^2P1 + 3t^2(1-t)P2 + P3t^3 , //где t = [0..1] function QubicBezier(P0, P1, P2, P3: TPoint; t: double): TFloatPoint; begin Result.X := ((1.0 - t) * (1.0 - t) * (1.0 - t) * P0.X) + (t * 3.0 * (1.0 - t) * (1.0 - t) * P1.X) + (3.0 * (t * t) * (1.0 - t) * P2.X) + (t * t * t) * P3.X; Result.Y := ((1.0 - t) * (1.0 - t) * (1.0 - t) * P0.Y) + (t * 3.0 * (1.0 - t) * (1.0 - t) * P1.Y) + (3.0 * (t * t) * (1.0 - t) * P2.Y) + (t * t * t) * P3.Y; end;
-
-
Итак, вот ребята что получилось:
> smoothness := 30; > path.moveTo(TPointF.Create(point[0].x, point[0].y)); > dl := 0; > t := 0.33; > for I := 1 to Length(point) - 2 do > begin > dr := (point[i+2].y - point[i].y) / 2 * t; > > p1 := TPointF.Create(point[i].x + t * smoothness, point[i]. > y+dl); > P2 := TPointF.Create(point[i+1].x - t* smoothness, > point[i+1].y - dr); > P3 := TPointF.Create(point[i+1].x, point[i+1].y); > path.CurveTo(p1, p2, p3); > dl := dr; > end;
В FMX рисуем Path в векторе, затем выводим на канву.
-
smoothness := 30; path.moveTo(TPointF.Create(point[0].x, point[0].y)); dl := 0; t := 0.33; for I := 1 to Length(point) - 2 do begin dr := (point[i+2].y - point[i].y) / 2 * t;
p1 := TPointF.Create(point[i].x + t * smoothness, point[i].y+dl); P2 := TPointF.Create(point[i+1].x - t* smoothness, point[i+1].y - dr); P3 := TPointF.Create(point[i+1].x, point[i+1].y); path.CurveTo(p1, p2, p3); dl := dr; end;
-
Всем спасибо за помощь!
-
Вот этот код дает отличные результаты без петель. Проверял на Delphi FMX (vector Path) все отлично (используйте Path.QuadCurveTo):
move to the first point ctx.moveTo(points[0].x, points[0].y);
for (i = 1; i < points.length - 2; i ++) { var xc = (points[i].x + points[i + 1].x) / 2; var yc = (points[i].y + points[i + 1].y) / 2; ctx.quadraticCurveTo(points[i].x, points[i].y, xc, yc); } // curve through the last two points ctx.quadraticCurveTo(points[i].x, points[i].y, points[i+1].x,points[i+1].y);
-
> без петель
Точнее без безье пиков (визуально - "скобок") на каждой точке, при любых разрешениях канваса.
-
|