Krzywa Béziera/kod

Z Wikiźródeł, repozytorium wolnych materiałów źródłowych
Skocz do: nawigacji, wyszukiwania


Krzywa Béziera • Kod źródłowy
Krzywa Béziera
Kod źródłowy
Wikipedia
Zobacz w Wikipedii hasło krzywa Béziera

Program przedstawiony poniżej potrafi narysować wielomianowe krzywe Béziera dowolnego stopnia, został napisany w języku 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.

Obliczenia są wykonywane w sposób "naiwny", wprost z definicji.

# -*- 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")


Godło PRL
Ten tekst nie podlega pod prawa autorskie. Jest zatem własnością publiczną, ponieważ jego autor przekazał tekst do domeny publicznej.

Osobiste
Przestrzenie nazw

Warianty
Działania
Nawigacja
Dla edytorów
Drukuj lub eksportuj
Narzędzia