Python - Vektorska grafika u jeziku Python (turtle graphics)


Vektorska grafika je način kreiranja grafičkih prikaza pomoću osnovnih geometrijskih objekata. Poseban pristup kreiranju vektorske grafike je tzv. turtle grafika, gde se objekti crtaju pomoću relativnih koordinata i komandi za crtanje geometrijskih objekata koje se izdaju zamišljenoj olovci, popularno nazvanoj "kornjača" (turtle). Olovka ili "kornjača" se na ekranu prikazuje u obliku malog trougla, koji pokazuje smer crtanja . Za korištenje ovakvih grafičkih naredbi u jeziku Python potrebno je prethodno uključiti odgovarajuću programsku biblioteku naredbom import turtle. Neke od osnovnih funkcija iz ove biblioteke su:

  • pendown() - spuštanje olovke, nakon čega olovka prilikom pomjeranja crta liniju odgovarajuće dužine, boje i debljine, koji se mogu podesiti.
  • left(ugao), right(ugao) - promjena smijera strelice u izabranom smeru, za zadani ugao.
  • forward(rastojanje), back(rastojanje) - pomjeranje olovke za zadani broj piksela u smijeru strelice ili u suprotnom smijeru.

Crtanje jednostavnih geometrijskih figura vrši se postavljanjem olovke na izabranu početnu tačku ekrana s koordinatama (x, y), nakon čega se linije crtaju promenom smijera i pomijeranjem olovke i izabranom smijeru za određeni broj tački ekrana (piksela). Program za crtanje pravougaonika i šestougla, čije su dužine stranica 100 piksela od podrazumevajuće početne pozicije olovke (0,0), može se izvršiti sljedećim kratkim programom u jeziku Python:

import turtle
turtle.pendown()

# Pravougaonik
for i in range(4):
    turtle.forward(100)
    turtle.right(90)

# Šestougao
for i in range(6):
    turtle.forward(100)
    turtle.right(60)

Pokretanjem programa otvara se novi grafički prozor za prikaz vektorske grafike. Pokazivač (olovka, "kornjača") na početku je u težištu grafičkog prozora, koje ima koordinate x=0 i y=0, Sl. 17.




Podrazumevajuća boja pozadine ekrana je bijela, a boja pera crna. Pomoću metoda turtle.color() može se izabrati druga boja, koja se zadaje kao tekst (engleski naziv ili Veb kod boje) ili numerički, pomoću RGB komponenti. Ako se postavi turtle.colormode(255), sljedeće naredbe su ekvivalentne:

turtle.color('red') # Naziv boje
turtle.color('#FF0000') # Veb kod crvene boje
turtle.color(255, 0, 0) # Numerički kod crvene boje

Iterativni program za crtanje oblika koji podsjeća na cvijet ili zvijezdicu određene boje, zadane funkcijom turtle.color(), prikazan je u sljedećem primjeru:

import turtle
turtle.color('red')
crtaj = True
while crtaj:
    turtle.forward(200)
    turtle.left(170)
    crtaj = abs(turtle.position()) >= 1

Pokretanjem programa, otvara se grafički prozor i iscrtava niz obojenih duži, koje zajedno daju geometrijsku figuru koja podseća na cvet, kao što je prikazano na sljedećoj slici.




Fraktalno stablo

Fraktalno stablo je rekurzivni geometrijski oblik, koji podsjeća na stablo drveta čije se grane dalje dijele tako da detaljnije reprodukuju istu strukturu grananja. Osnovna struktura je linija, koja se na svom kraju dijeli na dve grane, svaka pod uglom od 45º u odnosu na stablo.




Svaka od grana osnovne strukture dalje se rekurzivno dijeli na isti način, samo se dužina osnovne strukture svaki put smanjuje. Funkcija za crtanje fraktalnog stabla ima jedan parametar, fraktalnu dužinu stabla, koji predstavlja aktuelnu dužinu stabla u pikselima. Prilikom prvog poziva nacrta se vertikalno stablo, a zatim se rekurzivno poziva ista procedura radi crtanja listova kao kraćih stabala, pod različitim uglovima u odnosu na prethodno nacrtano stablo. Program za crtanje fraktalnog stabla zadane veličine je:

import turtle

def fraktalnoStablo(f_duzina, min_duzina=10):
# Funkcija rekurzivno crta stablo s dva lista
    turtle.forward(f_duzina)
    if f_duzina > min_duzina:
        turtle.left(45)
        fraktalnoStablo(0.6*f_duzina, min_duzina)
        turtle.right(90)
        fraktalnoStablo(0.6*f_duzina, min_duzina)
        turtle.left(45)
    turtle.back(f_duzina)
    
turtle.left(90)
fraktalnoStablo(100)

Izvršavanje programa za crtanje fraktalnog stabla dimenzija 100 piksela prikazano je na sljedećoj slici.




Trougao Serpinskog

Trougao Serpinskog4, prikazan na slici pod brojem 2, primjer je fraktalnog oblika, koji se dobija rekurzivnom diobom stranica trougla sledećim postupkom [1], [2]:

  1. Nacrta se osnovni trougao.
  2. Svaki veliki trougao podjeli se na četiri manja trougla povezivanjem sredina njegovih stranica.



  3. Ista procedura rekurzivno se primjenjuje na tri nova manja trougla, koji se nalaze u uglovima većeg, dok se srednji novi trougao delje ne dijeli.

Dubina rekurzije određuje ukupni broj trouglova koji se crta. Svaki rekurzivni poziv umanjuje promjenjljivu dubinu za jedan, a kad promjenjljiva poprimi vrijednost nula, postupak rekurzivnog pozivanja se prekida. Program za crtanje trougla Serpinskog, koji je zadan koordinatama uglova osnovnog trougla i brojem nivoa rekurzivnih podjela u Pythonu se može napisati kao:

import turtle

# Trougao Serpinskog zadan koordinatama uglova
def trougao(uglovi):
    turtle.color('violet')
    turtle.up()
    turtle.goto(uglovi[0][0],uglovi[0][1])
    turtle.down()
    turtle.goto(uglovi[1][0],uglovi[1][1])
    turtle.goto(uglovi[2][0],uglovi[2][1])
    turtle.goto(uglovi[0][0],uglovi[0][1])

# Vraća koordinate sredine stranice između dva ugla
def sredina(u1,u2):
    return [(u1[0]+u2[0])/2, (u1[1]+u2[1])/2]

# Rekurzivni prikaz osnovnog i tri manja trougla
def serpinski(uglovi,dubina):
    trougao(uglovi)
    if dubina > 0:
        serpinski([uglovi[0],
            sredina(uglovi[0], uglovi[1]),
            sredina(uglovi[0], uglovi[2])],
            dubina-1)
        serpinski([uglovi[1],
            sredina(uglovi[0], uglovi[1]),
            sredina(uglovi[1], uglovi[2])],
            dubina-1)
        serpinski([uglovi[2],
            sredina(uglovi[2], uglovi[1]),
            sredina(uglovi[0], uglovi[2])],
            dubina-1)
            
uglovi = [[-150,-50],[0,200],[150,-50]]
serpinski(uglovi,4)

Rezultat izvršavanja programa za zadane koordinate osnovnog trougla i tri nivoa rekurzivne podjele prikazan je na sljedećoj slici.




Pahuljica

Osnova fraktalnog oblika pahuljice (snowflake) je Kohova kriva sa koja se dobija rekurzivno. Program za crtanje Kohove krive u jeziku Python, relizovan pomoću funkcija iz modula turtle grafike, veoma je kratak:

import turtle

# Kohova kriva
def koch(f_duzina, dubina):
    if dubina > 0:
        for ugao in [60, -120, 60, 0]:
            koch(f_duzina/3, dubina-1)
            turtle.left(ugao)
        else:
            turtle.forward(f_duzina)
# Test
koch(400,3)

Rekurzivna funkcija Koch() poziva samu sebe za iscrtavanje tri duži sve manje dužine pod tri različita ugla, sve dok vrednost promjenjljive dubine ne poprimi vrijednost nula. Duži iste dužine iscrtavaju se naredbom forward(f_duzina) samo na konačnoj rekurzivnoj dubini.


Kohova kriva rekurzivne dubine 3, koja se dobije nakon tri rekurzivna koraka, prikazana je na sljedećoj slici.




Pahuljica se dobija tako što se Kohova kriva crta više puta, svaki put pod različitim uglom. Kompletan program za crtanje pahuljice u jeziku Python je:

import turtle

# Kohova kriva
def koch(f_duzina, dubina):
    if dubina > 0:
        for ugao in [60, -120, 60, 0]:
            koch(f_duzina/3, dubina-1)
            turtle.left(ugao)
    else:
        turtle.forward(f_duzina)

# Test
velicina = 300
dubina = 3

# Centriranje pahuljice
turtle.penup()
turtle.backward(velicina/1.73)
turtle.left(30)
turtle.pendown()

# Tri Kohove krive
for i in range(3):
    koch(velicina, dubina)
    turtle.right(120)

Kompletna pahuljica, prikazana je na sljedećoj slici, dobijena je crtanjem tri Kohove krive rekurzivne dubine 3, s tim da je prva pod uglom od 30º u odnosu na prethodni primjer, a naredne su međusobno rotirane za 120º.