Krzywa Béziera
Z Wikipedii
Krzywa Béziera - parametryczna krzywa powszechnie stosowana w programach do projektowania inżynierskiego CAD (Microstation), projektowania grafiki komputerowej (Corel Draw, GIMP, Inkscape), do reprezentowania obrysów znaków w fontach komputerowych (TrueType, METAFONT, Type1) i systemach przetwarzania grafiki (PostScript, MetaPost) oraz w grafice wektorowej (np. format SVG).
Krzywe Béziera zostały niezależnie opracowane przez Pierre Béziera, francuskiego inżyniera firmy Renault oraz Paula de Casteljau pracującego dla konkurencyjnej firmy Citroën. Prace nad krzywymi prowadzone były przez obu naukowców od początku lat 60., ale przez długi okres objęte ścisłą tajemnicą służbową. Dopiero pod koniec lat 60. pojawiły się pierwsze ogólnodostępne publikacje Pierre Béziera przedstawiające jego koncepcje, natomiast prace de Casteljau ukrywał Citroen jeszcze przez kilka lat - pierwsze wzmianki o nim pojawiają się dopiero w 1971, gdy prace Béziera były znane od dawna. Do rozpowszechnienia się krzywych Béziera znacząco przyczynił się A.R. Forrest artykułem Interactive interpolation and approximation by Bezier polynomials opublikowanym w 1972 roku w branżowym piśmie The Computer Journal.
Krzywe Béziera są krzywymi parametrycznymi - każda współrzędna punktu krzywej jest pewną funkcją liczby rzeczywistej - parametru; żeby określić krzywą na płaszczyźnie potrzebne są dwie funkcje, żeby określić krzywą w przestrzeni - trzy, itd. Ze względu na rodzaj tych funkcji mówi się o krzywych wielomianowych oraz krzywych wymiernych. Powszechnie stosuje się również krzywe złożone z kawałków gładko połączonych krzywych wielomianowych bądź wymiernych - krzywe B-sklejane (także krzywe gładkie).
Niezależnie od rodzaju krzywej na jej przebieg wpływa łamana kontrolna określona za pomocą punktów kontrolnych; liczba punktów kontrolnych jest zwykle niewielka. Ta cecha bardzo ułatwia pracę interakcyjną, bowiem człowiek w naturalny sposób może ustalać położenie punktów i w łatwy sposób korygować błędy.
Spis treści |
[edytuj] Podstawowe wiadomości
- Krzywe wielomianowe są powszechnie stosowane, w praktyce wykorzystuje się krzywe niskich stopni, opisywane niewielką liczbą punktów kontrolnych. Najpowszechniej drugiego stopnia (trzy punkty kontrolne, np. fonty TrueType) lub trzeciego stopnia (cztery punkty kontrolne, np. fonty Type1, METAFONT, SVG, cała gama różne pakiety graficzne); rzadziej stosuje się krzywe wyższych stopni. Krzywe wielomianowe są również dostępne w wielu bibliotekach programistycznych, np. OpenGL, Java2D, TCL. Ogólnie biorąc krzywe niskich stopni są wygodniejsze w użyciu, łatwiejsze w realizacji są różne algorytmy związane z krzywymi (obcinanie, wyznaczanie przecięć z innymi krzywymi, wyznaczanie ekstremów itp.).
- Krzywe wymierne mają nad krzywymi wielomianowymi jedną zasadniczą przewagę - można za ich pomocą reprezentować wszystkie krzywe stożkowe, w szczególności okręgi, elipsy i ich wycinki, co ma fundamentalne znaczenie w projektowaniu wspomaganym komputerowo. Krzywe wielomianowe mogą okręgi i elipsy zaledwie aproksymować, co jednak nie jest aż wielką wadą np. w zastosowaniach rysunkowych, gdzie dokładność nie jest priorytetem.
Zarówno krzywe wielomianowe jak i wymierne cechuje jedna wspólną niedogodność - trudno za pomocą jednej krzywej przedstawiać skomplikowane kształty. Można co prawda dodawać nowe punkty kontrolne, ale to powoduje, że kontrola kształtu jest mocno utrudniona, bowiem przemieszczenie jednego punktu wpływa na całą krzywą, a ponadto im wyższy stopień tym zmiana położenia punktów kontrolnych jest mniej widoczna (mówiąc obrazowo, trzeba punkty przemieszczać na duże odległości, aby odniosło to jakiś widoczny skutek).
Dlatego powszechnie stosuje się krzywe B-sklejane, które oferują lokalną kontrolę kształtu - przemieszczając jeden punkt kontrolny zmianie ulegnie tylko jego bliskie otoczenie. Krzywe B-sklejane są to takie krzywe, które składają się z kawałków krzywych bądź to wielomianowych, bądź wymiernych (względnie niskiego stopnia), natomiast matematyczne równania opisujące taką krzywą gwarantują, iż w punktach połączenie tych kawałków krzywa będzie gładka. Szczególną popularność zyskały wymierne krzywe (oraz powierzchnie) B-sklejane, znane jako NURBS.
[edytuj] Podstawy matematyczne
[edytuj] Krzywe wielomianowe
Dane są punkty kontrolne w liczbie n + 1.
Kształt krzywej Béziera opisują wielomiany, dla których przyjęto dziedzinę [0,1]. Stopień wielomianu wprost zależy od liczby puktów kontrolnych - wynosi n (liczba punktów kontrolnych minus jeden). Wielomiany są zwykle przedstawiane w bazie wielomianów Bernsteina (oznaczane jako , bądź w literaturze anglojęzycznej Bi,j(t)). Wielomiany bazowe Bernstaina są wygodne w tym sensie, że punkty kontrolne są w naturalny sposób współczynnikami takiego wielomianu - nie trzeba dokonywać dodatkowych przeliczeń.
Dowolny punkt na krzywej jest opisywany zależnością:
np. krzywą dwuwymiarową opisuje para wielomianów:
Punkt p(t) można również znaleźć za pomocą algorytmu de Casteljau.
Cechy charakterystyczne wielomianowych krzywych Béziera:
- Krzywa interpoluje punkty kontrolne (tj. p(0) = p0 i p(1) = pn), a przybliża (aproksymuje) pozostałe.
- Krzywa ma własność otoczki wypukłej, tzn. dla
punkt p(t) leży w otoczce wypukłej punktów kontrolnych
.
- Konstrukcja krzywej jest niezmiennicza względem przekształceń afinicznych, tzn. krzywa wyznaczona z przekształconych punktów kontrolnych jest taka sama jak krzywa po tym przekształceniu.
- Pojedyncza krzywa ma nieskończenie wiele reprezentacji - dla krzywej opisywanej przez n punktów kontrolnych można wskazać taki ciąg punktów kontrolnych w liczbie n + k (
), które opisują dokładnie tę samą krzywą. Taka procedura wyznaczania dodatkowych punktów nosi nazwę podnoszenia stopnia (ang. degree elevation). W praktyce stosuje się jednak krzywe możliwie niskich stopni, natomiast zwiększanie ilości punktów kontrolnych służy do konwersji między różnymi krzywymi.
Wadą wielomianowych krzywych Béziera jest to, że nie można za ich pomocą reprezentować krzywych stożkowych, okręgów, elips, itd. Tej wady pozbawione są wymierne krzywe Béziera.
[edytuj] Wielomianowe krzywe Béziera trzeciego stopnia
Najczęściej używane są krzywe trzeciego stopnia leżące na płaszczyźnie. Definiując krzywą trzeciego stopnia określamy 4 punkty A, B, C i D (na rysuku odpowiednio P0,P1,P2,P3), których położenie wyznacza przebieg krzywej. Krzywa ma swój początek w punkcie A i skierowana jest w stronę punktu B. Następnie zmierza w stronę punktu D dochodząc do niego od strony punktu C. Odcinek jest styczny do krzywej w punkcie A, natomiast odcinek
jest styczny w punkcie D
Krzywą Béziera trzeciego stopnia określa następujące równanie:
- P(t) = A(1 − t)3 + 3Bt(1 − t)2 + 3Ct2(1 − t) + Dt3 dla
.
Czyli:
- Px(t) = Ax(1 − t)3 + 3Bxt(1 − t)2 + 3Cxt2(1 − t) + Dxt3
- Py(t) = Ay(1 − t)3 + 3Byt(1 − t)2 + 3Cyt2(1 − t) + Dyt3
Alternatywny zapis macierzowy:
Krzywa ma swój początek w punkcie A (t = 0) i koniec w punkcie D (t = 1) .
Krzywą Béziera trzeciego stopnia można też opisać następującym równaniem (dla A = (x0,y0),B = (x1,y1),C = (x2,y2),D = (x3,y3)):
- x(t) = axt3 + bxt2 + cxt + x0
-
- x3 = x0 + cx + bx + ax
- y(t) = ayt3 + byt2 + cyt + y0
-
- y3 = y0 + cy + by + ay
Zdefiniowane w ten sposób wzory mogą zostać odwrócone tak, by otrzymać zmienne kierunkowe (są one stałe dla każdej krzywej Béziera):
-
- ax = x3 − x0 − cx − bx
-
- ay = y3 − y0 − cy − by
[edytuj] Wymierne krzywe Béziera
-
Zobacz więcej w osobnym artykule: Wymierna krzywa Béziera.
Wymierna krzywa Béziera to rzut środkowy wielomianowej krzywej Béziera zdefiniowanej we współrzędnych jednorodnych na płaszczyznę W = 1. Tak samo dane jest n + 1 punktów kontrolnych.
Jeśli przestrzeń jednorodna jest k + 1-wymiarowa, wówczas do opisu krzywej potrzebne jest tyleż wielomianów. Dowolny punkt krzywej wielomianowej jest dany jako . Po przejściu na współrzędne kartezjańskie (rzucie środkowym P(t) na płaszczyznę W = 1) otrzymuje się k wyrażeń wymiernych, a punkt na tej płaszczyźnie dany jest wzorem
.
Jeśli W(t) = const to krzywa jest wielomianowa - mówiąc nieformalnie krzywe wielomianowe, to specjalny przypadek krzywych wymiernych.
Dowolny punkt na krzywej wymiernej dany jest wzorem:
Gdzie wi to współrzędna W, jednak częściej nazywana jest wagą punktu kontrolnego.
Aby wyznaczyć punkt na krzywej można także posłużyć się algorytmem de Casteljau (albo wariantem dla krzywych wymiernych, albo wielomianowych).
Atuty w stosunku do wielomianowych krzywych Beziera:
- mogą reprezentować wszystkie krzywe stożkowe (co ma znaczenie w zastosowaniach CAD);
- rzut perspektywiczny krzywej wymiernej jest zawsze krzywą wymierną, podczas gdy rzut perspektywiczny krzywej wielomianowej nie musi być krzywą wielomianową (co ma znaczenie w grafice komputerowej);
- wagi wi pozwalają na lepszą kontrolę nad kształtem krzywej.
[edytuj] Krzywe B-sklejane
-
Zobacz więcej w osobnym artykule: Krzywa B-sklejana.
Krzywe B-sklejane składają się z kawałków wielomianowych bądź wymiernych krzywych Béziera, najczęściej niskiego stopnia (n). Dla krzywej B-sklejanej parametr t również należy do przedziału [0,1]. Przedział ten jest dzielony na podprzedziały, a liczby określające ich granicę nazywane są węzłami (ang. knot). Kolejne węzły mogą być sobie równe, tworząc w ten sposób puste podprzedziały - nie jest to błąd.
Jeśli węzłów jest m + 1 (), a stopień wielomianów jest równy n, to do określenia krzywej potrzebne jest m − n punktów kontrolnych, zaś liczba krzywych, które składają się na całość, wynosi m − 2n. Sklejane krzywe są zdefiniowane na przedziale [un,um − n], nie na [0,1].
Dowolny punkt na krzywej B-sklejanej jest dany wzorem, który wynika z algorytmu Mansfielda-de Boora-Coxa:
gdzie to unormowane funkcje B-sklejane stopnia n.
Krzywe B-sklejane mają następujące zalety w stosunku do krzywych wielomianowych i wymiernych:
- Lokalna kontrola kształtu - przemieszczanie jednego punktu kontrolnego wpływa na niewielkie otoczenie tego punktu (najwyżej n sąsiednich krzywych).
- Możliwość dowolnego rozmieszczania węzłów daje lepszą i większą kontrolę nad kształtem krzywej. Dodatkowo jeśli węzły pokrywają się, tzn. istnieją puste podprzedziały, uzyskuje się "ostre" (nie gładkie) połączenia.
- W łatwy sposób można wstawiać nowe węzły (ang. knot insertion), dzięki czemu proces modelowania jest prostszy.
Szczególne znaczenie i popularność zyskały wymierne krzywe B-sklejane (NURBS), łączące zalety zwykłych krzywych wymiernych z wymienionymi wyżej.
[edytuj] Program rysujący wielomianowe krzywe Béziera
Program przedstawiony poniżej potrafi narysować krzywe Béziera dowolnego stopnia, został napisany w jezyku Python. Domyślnie punkty kontrolne są losowane, przy jednym uruchomieniu generowane jest kilka krzywych. Liczbę krzywych, liczbę punktów kontrolnych i rozdzielczość obrazu można ustawić zmieniając wartości odpowiednich zmiennych.
# -*- coding: iso-8859-2 -*- # # Program rysuje dowolną liczbę krzywych Beziera dowolnego stopnia. # Do uruchomienia wymaga biblioteki PIL (Python Imaging Library). newton_cache = {} # pamięć podręczna dla wyników funkcji newton def Newton(n,k): '''Funkcja oblicza wartość symbolu Newtona''' global newton_cache if (n,k) not in newton_cache: # licznik = n*(n-1)*...*(n-k+1) licznik = 1 for i in xrange(n-k+1, n+1): licznik *= i # mianownik = k! mianownik = 1 for i in xrange(1, k+1): mianownik *= i newton_cache[(n,k)] = licznik/mianownik return newton_cache[(n,k)] def B(n,i,t): ''' Funkcja oblicza wartość wielomianu bazowego Bernsteina dla zadanego parametru t. ''' return Newton(n,i) * (t**i) * (1.0-t)**(n-i) def Bezier2D(punkty_kontrolne, k): ''' Funkcja przybliża dwuwymiarową krzywą Beziera za pomocą łamanej złożonej z k segmentów. Zwraca listę wierzchołków łamanej. punkty_kontrolne - lista punktów kontrolnych: [(x0,y0), ..., (xn,yn)] k - ilość segmentów ''' n = len(punkty_kontrolne)-1 # stopień krzywej Beziera # funkcja obliczająca współrzędne (x,y) punktu krzywej dla zadanego t def p(t): ''' x = \sum_{i=0}^n x_i B^n_i(t) y = \sum_{i=0}^n y_i B^n_i(t) ''' x = 0.0 y = 0.0 for i in xrange(n+1): x += punkty_kontrolne[i][0]*B(n,i,t) y += punkty_kontrolne[i][1]*B(n,i,t) return (x,y) dt = 1.0/k # krok parametru t return [p(i*dt) for i in xrange(k+1)] # program główny if __name__ == '__main__': import Image import ImageDraw # parametry programu n = 15 # liczba punktów kontrolnych (stopień krzywej+1) rozdzielczosc = 600 # rozdzielczość obrazów k = 200 # liczba segmentów łamanej przybliżającej krzywą l = 10 # liczba obrazów generowanych przy jednym # uruchomieniu programu image = Image.new("RGB", (rozdzielczosc, rozdzielczosc)) draw = ImageDraw.Draw(image) from random import randint as R for i in xrange(l): print "Tworzenie krzywej %d z %d" % (i+1, l) # 1. Wylosowanie n punktów kontrolnych punkty_kontrolne = [(R(0,rozdzielczosc), R(0,rozdzielczosc)) for _ in xrange(n)] # 2. Wyznaczenie łamanej p przyliżającą krzywą Beziera p = Bezier2D(punkty_kontrolne, k) # 3. Rysowanie krzywej: # 3a. wyczyszczenie obrazu (kolorem białym) draw.rectangle( [0,0, rozdzielczosc,rozdzielczosc], fill="#fff") # 3b. rysowanie łamanej kontrolnej (w kolorze jasnoszarym) draw.line(punkty_kontrolne, fill="#ccc") # 3c. zaznaczenie niebieskimi kółkami punktów kontrolnych r = 2 # promień for (x,y) in punkty_kontrolne: draw.ellipse([x-r,y-r, x+r,y+r], fill="#00f") # 3d. rysowanie krzywej Beziera (w kolorze czerownym) draw.line(p, fill="#f00") # 4. Zapisanie obrazu do pliku image.save("Krzywa-Beziera_%03d_%04d.png" % (n,i), "PNG")
[edytuj] Bibliografia
- Przemysław Kiciak, Podstawy modelowania krzywych i powierzchni, WNT 2005
- Foley, van Dam, Wprowadzenie do grafiki komputerowej, WNT 1995