-
Всем привет! Есть кубическая или квадратичная функция Безье. В ней есть параметр t =[0..1]. X и Y рассчитывается в зависимости от этого параметра. Все бы хорошо, но при одинаковом шаге (например 0.023) данная f(x) разница между X и предыдущем X может быть очень большая или очень маленькая. Хотелось бы узнать, если кто занимался этой функцией, возможно ли t сделать адаптивной переменной? Т.е. в зависимости от убывания/возрастания f(x) менять t или рассчитывать t от желаемого X или Y? Нужно для равномерности отрисовки самой Безье и заливки. Тут есть пример: https://cloud.mail.ru/public/8Bm6/CcsrjWdR3Включить следующие галочки: Мод. Безье Сглаживание Заливка Прозрачность Расстояние между вертикальными полосами и есть та самая t. Буду рад услышать любые дельные советы.
-
-
Можно. Делайте. Есть 2 метода. 1) Подбор шага 2) Подбор разбиения 1) Подбор как и в разбиении. Или если вы знакомы с градиентным методом с переменным шагом. Шаг параметр увеличивается или уменьшается в зависимости от требуемой точности отображения. Обычно 0.5 пикселя иногда 1/8 пикселя. За управляющие векторы кривая никогда не выходит поэтому оценку ошибки для Бизье 4 порядка достаточно просто. Как сумма по абсолютному значению двух упрочивающих векторов. 2) Разбиение. Любую кривую Безье можно представить в виде двух кривых со состыкованных в этой точке. http://antigrain.com/research/adaptive_bezier/Код переведенный на паскаль есть в aggpas
-
Сделал коррекцию точек на прямой. Вроде рисует все ровно, но вот есть одна неувязочка: http://hostingkartinok.com/show-image.php?id=ff6b6322ce61723727ab68088937c5f4На сильно острых углах функция не работает :( Вернее работает, если задать шаг 0.1, но это приводит к избыточности точек самой кривой. Можно ли определить, в каких случаях функция Безье так себя ведет?! >Pavia © (29.05.16 16:52) [2]AGG малость «тормознутая» библиотека. Кроме того у него все рисуется через рекурсивную безье. Жесть как медленно. Я рисую строго по функции и точками. Получается очень шустро.
-
> Можно ли определить, в каких случаях функция Безье так себя > ведет?!
Можно считайте углы. Если они тупые, то нормально. Если острые, и очень острые, то надо бить сильнее.
> AGG малость «тормознутая» библиотека. Кроме того у него > все рисуется через рекурсивную безье. Жесть как медленно.
Не замечал, что медленно. Но вариант, да не самый быстрый. Быстрее всегда бить на 16 участков, а для сложных случаев хватает 32.
-
>Можно считайте углы. В безье нет углов к сожалению. Там кубическое возрастание и обратная квадратичная коррекция.
-
Зато у кривых Безье, ест базовые и опорные точки. Вот они образуют ломанную. У этой ломаной есть углы.
-
Нет там ничего такого. Это просто функция, которая вычисляет X и Y. Просто в некоторых случаях происходит удлинение сегментов. Конечно же логических. Все соединяется точками. http://hostingkartinok.com/show-image.php?id=61d3b9c7681c1e689f593a11377272c4 while (t <= 1) do
begin
fP0 := GetFloatBezierPoint(pA, pA1, pB1, pB, t);
if (i mod seg) = 0 then
begin
nt := t + ts;
fP1 := GetFloatBezierPoint(pA, pA1, pB1, pB, nt);
if i <> 0 then
begin
eR := NormalizeRegion(Round(fP0.X), Round(fP0.Y), Round(fP.X), Round(fP.Y));
sBmp.RectAA(eR, crYellow, 255, 32);
end;
sBmp.FloatQPixel(fP0.X, fP0.Y, crWhite, 255, glvOpacity);
sBmp.FloatQPixel(fP0.X, fP0.Y, crWhite, 255, glvOpacity);
sBmp.FloatQPixel(fP0.X, fP0.Y, crWhite, 255, glvOpacity);
sBmp.FloatQPixel(fP0.X, fP0.Y, crWhite, 255, glvOpacity);
fW := Abs(fP1.X - fP0.X);
fH := Abs(fP1.Y - fP0.Y);
h := (fW >= fH);
if (fW <> 0) and (fH <> 0) then
begin
sqrtSL := sqrt(fW * fW + fH * fH);
sc := 1 / sqrtSL; TSL := TSL + sqrtSL; end;
s1 := Ansistring(FloatToStrF(sc, ffNumber, 18, 2)); sBmp.DrawHText5x7(eR.EX + 3, eR.Y + (eR.H div 2) - 4, s1, 1, crWhite, 255, 32);
fP := fP0;
end;
inc(i);
sBmp.FloatQPixel(fP0.X, fP0.Y, crLtGreen, 255, glvOpacity);
t := t + (ts * sc); end;
Ну и сама кривая: [X,Y] = (1-t)^3A + 3t(1-t)^2A1 + 3t^2(1-t)B1 + Bt^3
-
Не знаю как математически отловить удлинение сегмента :(
-
Вот вам примерный код.
step:=0.1; while (t <= 1) do
begin
repeat
P0 := GetFloatBezierPoint(pA, pA1, pB1, pB, t);
P1 := GetFloatBezierPoint(pA, pA1, pB1, pB, t+step*0.5);
P2 := GetFloatBezierPoint(pA, pA1, pB1, pB, t+step);
dH:=DistancePointLine(p1, Line(P0,p2)); if (dh>=0.5) then step:=step*0.5; if (dh<=0.1) and (step<0.1) then step:=step*2; until (dh<0.5);
DrawLine(P0,P2);
t:=t+step;
end;
-
-
|