Форум: "Media";
Текущий архив: 2007.08.05;
Скачать: [xml.tar.bz2];
ВнизКривые Безье Найти похожие ветки
← →
Jimmy (2006-10-31 18:58) [0]Написал программу для построения графиков в векторном формате с помощью PolyBezier. Но чтобы приближение было хорошим, пришлось брать точки с очень маленьким шагом - в 2 пикселя. Если шаг больше, то кривые Безье в некотрых
местах сильно отличаются от настоящего графика. Вероятно, если кривизна не большая, то шаг можно увеличивать, если сильная - уменьшать. Но может быть существуют готовые алгоритмы выбора точек для качественной апроксимации
графиков кривыми Безье? Или я что-то не понимаю? Заранее спасибо.
← →
MBo © (2006-10-31 19:35) [1]Как ты рассчитываешь кривые Безье?
← →
Jimmy (2006-10-31 20:02) [2]Сначала заполняю массив a:array[1..n]of TPoint. Перебираю значения пикселей по горизонтали с шагом, например 2, заношу в a[i].x, для каждого x нахожу с помощью функции соответствующее знаяение y в пикселях, заношу в a[i].y. И в конце один раз, что-то вроде PolyBezier(a,31).
← →
Pavia © (2006-10-31 20:13) [3]
> Перебираю значения пикселей по горизонтали с шагом
Безье лучше строиться по другому. Как
x:=X(t);
y:=Y(t);
Число точек можешь выбрать как длина ломанной умноженная на Pi.
← →
Pavia © (2006-10-31 21:38) [4]Я перестраховался и на Pi можно и не множить.
← →
Jimmy (2006-10-31 21:39) [5]Pavia! Не совсем понял Ваш ответ. Так следует строить кривые Безье с помощью команды PolyBezier или нет? Нельзя ли поподробнее описать алгоритм построения графика Вашим способом? Также непонятна фраза относительно числа точек.
← →
Pavia © (2006-10-31 23:40) [6]
// Hарисовать кривую Безье
//R(t) = P0*(1-t)^3 + P1 * t * (1-t)^2 + P2 * t^2 * (1-t) + P3 * t^3 ,
// где 0<=t<=1
//P0,P3 - опорные точки
//P1,P2 - управляющие точки и
procedure DrawBezier(Canvas:TCanvas; P0,P1,P2,P3:TPoint);
var
LenP,i:Integer;
Step,t,q0,q1,q2,q3,qx,qy:Real;
begin
LenP:=50;
//Можно
//LenP:=Round(LenLine(p0,p1)+LenLine(p1,p2)+LenLine(p2,p3))/10
//function LenLine(P0,P1:TPoint):Real;
//begin
//result:=sqrt(sqr(P0.X-P1.X)+sqr(P0.Y-P1.Y));
//end;
Step:=1/LenP;
Canvas.MoveTo(P0.X,P0.Y);
For i:=0 to LenP do
begin
t:=i*step;
q0:=(1-t)*(1-t)*(1-t);
q1:=3*(1-t)*(1-t)*t;
q2:=3*(1-t)*t*t;
q3:=t*t*t;
qx:=P0.X*q0+P1.X*q1+P2.X*q2+P3.X*q3;
qy:=P0.Y*q0+P1.Y*q1+P2.Y*q2+P3.Y*q3;
Canvas.LineTo(round(qx),round(qy));
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
DrawBezier(canvas,Point(0,0),Point(800,30),Point(10,600),Point(750,600));
end;
← →
Pavia © (2006-10-31 23:43) [7]И еще практика показывает что в компьютерной графике лучше при выводе округлять не так
Canvas.LineTo(round(qx),round(qy));
А так
Canvas.LineTo(trunc(qx),trunc(qy));
← →
Ketmar © (2006-10-31 23:47) [8]>[7] Pavia(c) 31-Oct-2006, 23:43
>Canvas.LineTo(trunc(qx),trunc(qy));
обоснуй.
← →
Pavia © (2006-11-01 00:19) [9]Пока нет обоснования, еще мало примеров набрал. И это проявляетя только при построении без сглаживания. Я думаю это связанно с дискретностью исходных данных. Но пока в серьез моии слова не воспринемать.
← →
Ketmar © (2006-11-01 01:09) [10]любое округление искажает. разница в том, что round() быстрее работает. %-)
← →
MBo © (2006-11-01 06:59) [11]Кривые Безье - графический примитив, позволяющий отрисовать кубические параметрические кривые. Для того, чтобы аппроксимировать график, можно их непосредственно рассчитать, но значительно проще использовать кубические сплайны - интерполяционные или сглаживающие (в инете есть исходники), а затем преобразовать полученный набор согласованных полиномов в форму Безье.
← →
Наиль © (2006-11-01 09:30) [12]> Canvas.LineTo(round(qx),round(qy));
> А так
> Canvas.LineTo(trunc(qx),trunc(qy));
С математической точки зрения
Round(qx)=Trunc(qx+0.5)
Так что, это одно и тоже, но с разницей в пол пиксела
← →
Ketmar © (2006-11-01 18:38) [13]>[12] Наиль(c) 1-Nov-2006, 09:30
>С математической точки зрения
а с программной round() шустрее. %-)
← →
Gyrus © (2006-11-02 15:11) [14]Интересно, с чего это Round быстрее trunc?
← →
Gyrus © (2006-11-02 15:14) [15]Действительно, быстрее, а по логике выполнения и не скажешь.
← →
MBo © (2006-11-03 05:53) [16]>Действительно, быстрее, а по логике выполнения и не скажешь.
Trunc устанавливает, а потом возвращает контрольное слово сопроцессора, поэтому и медленнее.
А вообще тут это оффтопик, тем более, что приведенный код рисования Безье нехороший.
← →
Pavia © (2006-11-03 14:58) [17]
> код рисования Безье нехороший.
Почему?
← →
MBo © (2006-11-03 15:09) [18]>Почему?
Потому что он неадаптивный. И при простой кривой, и при сложной форме он будет рисовать заданное число отрезков с равномерным шагом по t, в то время как правильный алгоритм выводит немного отрезков на гладких участках, и тщательно прорисовывает участки с большой кривизной и особыми точками ( "клювиком").
Ведь в этих кривых выбран базис полиномов Бернштейна не только потому, что это дает интуитивное представление о форме кривой (направление в конечных точках), но и обеспечивает легкий способ деления - метод de Casteljau
← →
Pavia © (2006-11-03 16:16) [19]
> Потому что он неадаптивный.
Не как раз адаптивный. Посмотри на рисунки. На прямых участках как раз немного отрезков а на изгибе их уже больше.
То что t с равномерном шагом это не означает что P(t) - будет с равномерным шагом.
Да и помойку у тебя первый абзац противоречит второму. Так что можешь привести пример как это по-твоему должно выглядеть?
← →
Jimmy (2006-11-04 22:38) [20]Если я правильно понимаю, то векторный MetaCanvas понимает грубо говоря 2 типа объектов - Line и CurveBezier. Line, что приведено в примере, меня в принципе не устраивает. С помощью Line я могу нарисовать график "точно" и без всяких апроксимаций. А мне надо чтобы 1) При увеличении в 500% график оставался гладким (Line отпадает) 2) В последующей редакции в CorelDraw появлялись именно кривые Безье а не Lines. Итак вопросов появилось еще больше, пока 2 из них:
1. Учитывая это кроме PolyBezier ничего не подойдет или я не прав?
2. Как тогда все же выбирать шаг, чтобы учитывать кривизну?
Заранее спасибо.
← →
MBo © (2006-11-05 16:26) [21]Pavia
>На прямых участках как раз немного отрезков а на изгибе их уже больше
Тем не менее равномерный шаг по t не обеспечивает правильной обработки сложных участков. Конечно, при большом числе точек отрисовка будет нормальной, но адаптивный алгоритм позволит сделать отрисовку с меньшими усилиями, да и зачем писать самому то, что уже сделано в Windows
Jimmy
> Как тогда все же выбирать шаг, чтобы учитывать кривизну?
GDI правильно отрисует кривые, а твоя проблема - правильно задать их, так что существа проблемы ты так и не раскрыл. Кое-что я предположил в [11], но пока неясно, имеет ли это отношение к твоей задаче
Страницы: 1 вся ветка
Форум: "Media";
Текущий архив: 2007.08.05;
Скачать: [xml.tar.bz2];
Память: 0.5 MB
Время: 0.083 c