Fák rajzolása
Czirkos Zoltán, Rakitai Balázs · 2021.05.31.
Különféle fafajtákat kirajzoló program. Éljen a rekurzió!
Ha fogunk egy függőleges szakaszt (fekete), aztán abból oldalra kiindulva rajzolunk két újabb, rövidebb szakaszt, meg fölfelé is egyet (kék)… Aztán az így kapott szakaszokból kiindulva megint rajzolunk szakaszokat (piros), amelyek ugyanolyan szögben állnak az előzőekhez képest, mint az az elsőhöz; aztán meg az ekkor kapottakból ugyanúgy (zöld) és így tovább… Akkor kapunk egy fát. Itt a jobb oldali rajzon egy kék–piros–zöld mini fa pont úgy néz ki, mint a tőle eggyel balra lévő piros–kék–fekete fa, csak kisebb.
Ha mindezt úgy csináljuk, hogy a kiinduló vonal még vastagabb legyen, utána egyre vékonyabb vonalakat rajzoljunk; a kiinduló vonal még barna legyen, utána egyre zöldebb vonalakat rajzolunk, akkor már kész is van a fánk. Csak tovább kell vinni a rajzolást, nem 3 lépésben rajzolni az ágakat, hanem mondjuk 8-10 lépésben, és akkor tényleg fának néz majd ki, nem pedig antennának.
A fát rajzoló függvény nagyon egyszerű. Megkapja, hányadik szinten van, és milyen hosszú szakaszokat kell rajzolnia, továbbá az
ágak adatait. Megrajzolja a törzset egy szakasszal. Utána pedig fogja az ágak listáját, és meghívja újra saját magát: de eltérő
pozíciókban (mert a törzs valamely pontjáról indul ki az ág), eltérő szöggel (mert valamerre nő az ág a törzshöz képest), és kisebb
hosszal (mert az ágak egyre rövidebbek). A rekurziót az n
paraméter csökkenése állítja meg:
FÜGGVÉNY fát_rajzol(n, ágak, hossz) HA n = 0, VÉGE szakasz(hossz) CIKLUS végig az ágakon elmozdulás/fordulás az ághoz fát_rajzol(n - 1, ágak, hossz - rövidülés) vissza az eredeti helyre CIKLUS vége FÜGGVÉNY vége
A fák változatosságát az ágak paraméterei adják. Ha nagy szögben hajlanak el, terebélyes fát kapunk, ha kicsiben, inkább magasat. Ha az ágak aljáról indítjuk az elágazásokat, bokrokat rajzol a program. Ha gyorsan rövidülnek az ágak (a „szülő” águkhoz képest), akkor facsemetéket. Az egyes ágak tulajdonságait ezért eltároljuk egy objektumban:
class AgAdat:
def __init__(self, doles, helyzet, rovidules):
# merre dől az eredeti ághoz képest (fok)
self.doles = doles
# honnan indul ki (0 = legalul, 1 = legfelül)
self.helyzet = helyzet
# mennyit rövidül (0 = semennyit, 1 = lenullázódik)
self.rovidules = rovidules
Minden ágból három másikat indítunk ki, egyet balra, egyet felfelé, egyet pedig jobbra (tehát a szögeket így kell majd beállítani). A rajzoló függvény az ágak listáját fogja átvenni. További változatosságot lehet bevinni a fák színének beállításával, az egyes ágak dőlésszögének kisebb véletlenszerű módosításaival és így tovább.
Hogy a sok véletlenszámot és lehetséges számtartományt könnyen tudjuk kezelni, érdemes egy intervallumot megadó típust is létrehozni, és egy ilyet átvevő véletlenszám-generátor függvényt írni:
class Intervallum:
def __init__(self, min, max):
self.min = min
self.max = max
def itv_rand(itv):
return random.uniform(itv.min, itv.max)
A fa rajzolása Python nyelven alig bonyolultabb a fenti pszeudokódnál. Közben a törzs barnájától a levelek zöldjéig egy színátmenetet kell létrehozni. Ezt két szín típusú objektum segítségével érjük el: minden lépésben csökken a szín vörös(-es barnás) komponense, és erősödik a zöld komponense. Ezt állítják be az RGB típusú objektumok összetevői.
def fat_rajzol(n, agak, hossz, dolesrand, szin, szin_valtozas):
if n == 0:
return
szakasz(n, hossz, szin)
for ag in agak:
# beállítjuk, honnan indul majd a következő ág
szog = ag.doles + itv_rand(dolesrand)
turtle.forward(hossz * (1 - ag.helyzet))
turtle.left(szog)
fat_rajzol(n - 1, agak, hossz * (1 - ag.rovidules), dolesrand,
szin + szin_valtozas, szin_valtozas)
# visszamegyünk az eredeti pozícióba
turtle.right(szog)
turtle.backward(hossz * (1 - ag.helyzet))
A paraméterek hatása a fa alakjára:
A teljes program letölthető innen: fa.py. A működés egy-két további részletével kapcsolatban lásd a forráskód kommentjeit!