Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
2-1184074625
WebSQLNeederr
2007-07-10 17:37
2007.08.05
Ламерский вопрос - как перейти на следующую итерацию цикла?


1-1179985999
Бульбаш
2007-05-24 09:53
2007.08.05
Возможно ли реализовать средствами Delphi?


15-1184083274
Курдль
2007-07-10 20:01
2007.08.05
Oracle. Прокси - аутентификация.


3-1177490026
zero
2007-04-25 12:33
2007.08.05
Долго выполняеться запрос


15-1183714852
Panel
2007-07-06 13:40
2007.08.05
Ошибка при компиляции модуля





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский