Logo: použití barev a ovládání kreslicího pera

4. 9. 2007
Doba čtení: 12 minut

Sdílet

V dnešním článku o programovacím jazyce Logo si představíme a na šesti demonstračních příkladech vysvětlíme některé pokročilejší operace, které je možné provádět s želví grafikou. Pomocí těchto operací lze nastavovat styl vykreslování, zejména barvu a šířku pera, ovládat režim kreslicího pera a podobně.

Obsah

1. Logo: použití barev a ovládání kreslicího pera
2. Želví grafika a barvy
3. První demonstrační příklad – vícebarevné obrazce vytvořené s využitím základní barvové palety
4. Demonstrační příklady – práce s větším počtem barev
5. Nastavení stylu vykreslování želví grafiky
6. Čtvrtý demonstrační příklad – zvednutí a spuštění pera při kresbě složitějších obrazců
7. Pátý demonstrační příklad – vytvoření kola s loukotěmi
8. Šestý demonstrační příklad – zobecnění vykreslení kola s loukotěmi
9. Obsah následující části tohoto seriálu

1. Logo: použití barev, stylů želví grafiky, textů, oblouků a výplní

V prvních implementacích programovacího jazyka Logo byly podporovány pouze základní příkazy určené pro práci s želví grafikou. Jednalo se o příkazy provádějící posun želvy dopředu i zpět (procedury forward a back), otáčení želvy okolo její osy (procedury left, right a setheading) a dále o příkazy pro přesun želvy na absolutní souřadnice a smazání grafické plochy (procedury home, setpos, setx, sety, setxy, clearscreen a clean).

Společně s prudkým rozvojem grafických schopností počítačů se repertoár příkazů určených pro práci s grafickou plochou, po které se při kreslení pohybuje želva, rozšiřoval. Dnes si některé tyto příkazy podrobněji popíšeme. Bude se jednat o příkazy pro změnu barvy, kterou želva vykresluje stopu a o příkazy určené pro ovládání stylu vykreslování (především zvedání a spuštění kreslicího pera).

2. Želví grafika a barvy

Většina obrázků, které jsme vytvářeli pomocí příkazů uvedených v předchozích částech tohoto seriálu, byla vykreslena pouze pomocí dvou barev – buď bílou barvou na černém pozadí (implementace Turtle Tracks a USB Logo) nebo naopak černou barvou na bílém pozadí (MSW Logo a většina implementací Loga určených pro operační systémy Microsoft Windows). V každém moderním Logu je však samozřejmě možné vybírat barvu, kterou se mají vytvářené obrazce vykreslovat. Pro tento účel je ve většině dnešních implementací Loga k dispozici procedura setpencolor, kterou je možné volat v několika variantách. V základní variantě je této proceduře předáno pouze jedno nezáporné celé číslo představující index do barvové palety. Jak délka barvové palety (tj. celkový počet vybíratelných barev), tak i její vlastní obsah není standardizován a jednotlivé implementace Loga se v tomto ohledu odlišují.

Například v Turtle Tracks a USB Logu je možné použít pouze barvy s indexy 0 až 7, v MSW Logu existuje v paletě šestnáct barev s indexy 0 až 15 atd. Také samotné barvy uložené v paletě se odlišují. Typicky bývá barva číslo nula nastavená na barvu pozadí (bílá či černá) a barva číslo 7 je inverzní k barvě pozadí (černá či bílá). Ostatní barvy buď odpovídají zbylým šesti barvám RGB spektra (červená, modrá, zelená, fialová, modrozelená a žlutá – tak jako na ZX Spectru) nebo jsou systémově závislé, například na implicitní paletě použité grafické karty. V některých implementacích Loga je možné barvy v paletě měnit pomocí procedury setpalette, které se předá index barvy, která se má změnit a jako druhý parametr je předán seznam trojic hodnot základních barvových složek R, G a B.

logo1101
Obrázek 1: ZX Spectrum nabízí osm barev, které jsou shodné s některými implementacemi procedury setpalette

Vidíme, že práce s barvovou paletou může být problematická a vytvořené programy nepřenositelné na jiné implementace Loga. Pokud například program používá barvy s indexy většími než 7, bude se při spuštění v Turtle Tracks hlásit chyba, kdežto v MSW Logu program poběží bez chyby. Proceduru setpencolor je však také možné volat s jiným typem parametrů – jedná se o seznam (list) obsahující přímo hodnoty základních barvových složek R (červená), G (zelená) a B (modrá). Tyto hodnoty by měly být v rozsahu 0..255, což odpovídá obecným zvyklostem (HTML barvy, grafické knihovny) i schopnostem dnešních grafických karet, monitorů a tiskáren. Jednou z výjimek je UCB Logo, ve kterém je rozsah hodnot barvových složek R, G a B mnohem větší: 0..65536, což odpovídá 655363=281474­976710656 barevným odstínům.

3. První demonstrační příklad – vícebarevné obrazce vytvořené s využitím základní barvové palety

V dnešním prvním demonstračním příkladu si ukážeme použití základní barvové palety. Procedura spiral slouží k vykreslení lomené čáry, která při větší hustotě čar připomíná ulitu či spirálu. Z geometrického hlediska se samozřejmě o žádnou spirálu nejedná. Tato procedura je osmkrát volaná z procedury demo, ve které se pomocí příkazu setpencolor nastavuje jedna ze základních osmi barev standardní barvové palety. Když se však podíváme na druhý obrázek, uvidíme pouze sedm „spirál“. Je to z toho důvodu, že první spirála je vykreslena barvou číslo 0, která odpovídá barvě pozadí a obrazec tedy není viditelný. Samotná procedura spirala je vytvořena tak, aby se všech sedm vykreslených spirál pravidelně rozmístilo kolem společného středu.

; "spirála" složená z lomené čáry o 97 segmentech
to spiral :angle
    make "side 0
    repeat 97 [
        forward :side
        right :angle
        make "side :side + 1
    ]
end

; vykreslení osmi "spirál" - každá spirála
; je obarvena jednou ze základních osmi barev
to demo
    clearscreen
    hideturtle
    repeat 8 [
        ; procedura repcount vrací hodnotu čítače smyčky
        setpencolor repcount-1
        ; přesun na začátek dalšího objektu
        penup
        forward 200
        pendown
        spiral 88
    ]
end

; změna velikosti kreslicí plochy - tento příkaz
; je platný pouze pro Turtle Tracks
(draw 300 300)

; vykreslení obrazce
demo 

logo1102
Obrázek 2: Sedm různobarevných objektů vykreslených procedurou spiral

4. Demonstrační příklady – práce s větším počtem barev

Druhý způsob použití procedury setpencolor si můžeme ukázat na jednoduchém příkladu, po jehož spuštění dojde k vykreslení dvou barevných pruhů s lineárním přechodem mezi dvojicí barev. Tento příklad je odladěn pro Turtle Tracks, proto jsou barevné složky každého odstínu vypočteny tak, aby ležely v rozsahu 0..255. Další nová procedura, která se v tomto příkladu objevuje, se jmenuje repcount a slouží k získání aktuální hodnoty čítače smyčky. Musíme si pouze dát pozor na to, že se v Logu začíná čítat od jedničky a nikoli od nuly, což znamená, že poslední hodnota čítače odpovídá číslu zapsanému za procedurou repeat a ne číslu o jedničku menšímu:

; Vykreslení dvou barevných pruhů
; Jsou použity příkazy, které nemusí být platné
; ve všech implementacích Loga!
to color_demo
    clearscreen
    hideturtle
    repeat 256 [
        ; procedura repcount vrací hodnotu čítače smyčky

        ; vykreslení horního barevného pruhu
        setpencolor (list repcount-1 repcount-1 256-repcount)
        penup
        setpos (list repcount-127 1)
        pendown
        setpos (list repcount-127 100)

        ; vykreslení dolního barevného pruhu
        setpencolor (list repcount-1 256-repcount repcount-1)
        penup
        setpos (list repcount-127 -1)
        pendown
        setpos (list repcount-127 -100)
    ]
end

; zobrazení kreslicí plochy - tento příkaz
; je platný pouze pro Turtle Tracks
draw
color_demo 

logo1103
Obrázek 3: Grafická plocha Turtle Tracks po spuštění procedury color_demo

Ve třetím demonstračním příkladu je taktéž využita druhá varianta volání procedury setpencolor, při které se této proceduře předává seznam tří hodnot odpovídajících barvovým složkám R, G a B. Příklad je odladěn pro MSW Logo, což mimo jiné znamená, že se hodnoty všech barvových složek nastavují v rozsahu 0..255, celkem je tedy možné vybrat barvu z 224=16777216 dostupných odstínů. Dále je v tomto příkladu ukázáno, jakým způsobem je možné nastavit barvu pozadí. V případě MSW Loga se pro tuto operaci používá procedura setscreencolor, které se opět předává trojice hodnot R, G a B. Vzhledem k tomu, že jsou použity pouze konstantní hodnoty, je možné celou trojici zapsat do hranatých závorek (což je konstruktor statického seznamu) a není zapotřebí volat proceduru list (to je de facto konstruktor dynamického seznamu):

; Procedura pro vykreslení barevné spirály odladěná v MSW Logu
; Jsou použity příkazy, které nemusí být platné
; ve všech implementacích Loga!
to color_spiral

    ; vymazání grafické plochy a skrytí želvy
    clearscreen
    hideturtle

    ; nastavení černé barvy pozadí
    setscreencolor [0 0 0]

    ; volba velikosti kroku
    make "step 4

    ; sprirála se skládá ze 64 kružnic
    repeat 64 [
        ; na základě čítače smyčky (1..64) se nastaví
        ; hodnota barvové složky (0..255)
        make "color_val (repcount-1)*4
        ; nastavení barvy kreslicího pera
        setpencolor (list :color_val 255 255-:color_val)

        ; vykreslení kružnice s proměnlivým poloměrem
        repeat 180 [
            left 2
            forward :step
        ]
        left 10
        ; další kružnice bude zmenšena
        make "step :step-0.05
    ]
end 

logo1104
Obrázek 4: Třetí demonstrační příklad spuštěný v MSW Logu

Pokud by bylo zapotřebí výše uvedený demonstrační příklad spustit v UCB Logu, je nutné v programu provést několik menších úprav. Zejména se mění název procedury použité pro změnu barvy pozadí grafické plochy – místo setscreencolor se používá procedura setbackground. Druhá změna spočívá v tom, že se v této implementaci Loga zvětšuje povolený rozsah hodnot barvových složek: místo hodnot z rozsahu 0..255 se používá rozsah 0..65535. Kdyby nedošlo k úpravě programu, pravděpodobně by na grafické ploše nebyl obrazec vůbec viditelný, protože nízká hodnota barvových složek by vedla k namíchání barev blízkých černé barvě pozadí.

Z tohoto důvodu se hodnoty všech barvových složek násobí 256. Z rozdílů mezi oběma verzemi tohoto demonstračního příkladu je patrné, že pro dosažení co největší přenositelnosti programů je zapotřebí vytvořit si vlastní procedury pro nastavení barvy kreslení i barvy pozadí a striktně pracovat pouze s těmito novými procedurami.

; Procedura pro vykreslení barevné spirály odladěná v UCB Logu
; Jsou použity příkazy, které nemusí být platné
; ve všech implementacích Loga!
to color_spiral

    ; vymazání grafické plochy a skrytí želvy
    clearscreen
    hideturtle

    ; nastavení černé barvy pozadí
    setbackground [0 0 0]

    ; volba velikosti kroku
    make "step 4

    ; sprirála se skládá ze 64 kružnic
    repeat 64 [
        ; na základě čítače smyčky (1..64) se nastaví
        ; hodnota barvové složky (0..65536-1)
        make "color_val (repcount-1)*4*256
        ; nastavení barvy kreslicího pera
        setpencolor (list :color_val 65536-1 65536-:color_val-1)

        ; vykreslení kružnice s proměnlivým poloměrem
        repeat 180 [
            left 2
            forward :step
        ]
        left 10
        ; další kružnice bude zmenšena
        make "step :step-0.05
    ]
end 

5. Nastavení stylu vykreslování želví grafiky

V prakticky všech implementacích Loga je možné použít příkazy penup a pendown, resp. jejich zkrácené podoby pu a pd, pro zvednutí a spuštění kreslicího pera, kterým želva na grafické ploše vytváří obrazce. Pokud je pero spuštěno, želva ze sebou při svém pohybu zanechává stopu, v opačném případě se pouze přesunuje bez kreslení. Samotný název příkazů má svoje kořeny ve stejně pojmenovaných operacích, které provádí perové plottery při kreslení nebo při přesunu kreslicího pera. Některé implementace Loga dovolují změnit i styl pera, zejména jeho tloušťku (setpensize), typ vykreslované čáry (setpenpattern) a někdy také dokonce i tvar štětce (viz podobný nástroj známý z kreslicích programů). Tyto příkazy však nejsou standardizovány, proto se ve většině demonstračních příkladů uvedených v této i dalších částech, spokojíme se základním nastavením stylu.

logo1105
Obrázek 5: Typický perový plotter – zařízení, které je vytlačováno velkoplošnými inkoustovými tiskárnami

6. Čtvrtý demonstrační příklad – zvednutí a spuštění pera při kresbě složitějších obrazců

Pomocí příkazů penup (pu) a pendown (pd) je možné zvednout a spustit pomyslné kreslicí pero, pomocí kterého želva při svém pohybu vykresluje stopu. Na první pohled mohou tyto příkazy vypadat jako nadbytečné, protože stačí nastavit barvu pera shodnou s pozadím kreslicí plochy, aby se želva přesunovala bez kreslení. Ve skutečnosti to však není pravda, protože by se současně překresloval (mazal) i již nakreslený obrazec. Použití příkazů pro zvedání a spouštění kreslicího pera si ukážeme na příkladu, ve kterém se v proceduře carky vykreslí úsečka složená z deseti čárek, z nichž každá má délku deset kroků želvy. Vzdálenost mezi čárkami je taktéž rovna deseti krokům želvy. Posléze se v proceduře carky2 vykreslí mnohoúhelník aproximující kružnici. Opět se jedná o objekt složený z čárek o délce deseti kroků želvy:

; Program ukazující použití příkazů penup a pendown

; procedura, která vykreslí čárkovanou úsečku
; o délce 200 kroků (vždy 10 kroků segment a 10 kroků mezera)
to carky
    repeat 10 [
        pendown
        forward 10
        penup
        forward 10
    ]
end

; procedura, která vykreslí čárkovanou kružnici
; (desetikrokový úsečkový segment je následován mezerou
; o délce také deseti kroků)
to carky2
    repeat 36 [
        pendown
        forward 10
        left 10
        penup
        forward 10
    ]
end

; změna velikosti kreslicí plochy - tento příkaz
; je platný pouze pro Turtle Tracks
(draw 300 300)

; příklad použití procedur carky a carky2
to demo_carky
    clearscreen
    ; nejdříve se vykreslí čárkovaně osy
    repeat 4 [
        penup
        setpos [0 0]
        pendown
        carky
        left 90
    ]
    ; nastavení želvy na počátek vykreslení kružnice
    penup
    home
    right 90
    forward 110
    left 90
    pendown

    ; spuštění procedury pro vykreslení čárkované kružnice
    carky2
end

demo_carky 

logo1106
Obrázek 6: Čtvrtý demonstrační příklad spuštěný v Turtle Tracks

7. Pátý demonstrační příklad – vytvoření kola s loukotěmi

Po spuštění pátého demonstračního příkladu se na grafickou plochu Loga vykreslí kolo s 36 loukotěmi. Samotné vytvoření kola sestaveného z jednotlivých segmentů je poměrně jednoduché – v proceduře wheel je v počítané programové smyčce volaná procedura segment, která vytvoří čtverec a následně je želva po svém návratu do původní pozice (tou je střed kola) otočena o 10° doprava, což po dokončení vykreslení všech 36 segmentů vede k vygenerování kruhového útvaru. V proceduře segment je sice skutečně vykreslován čtverec, ovšem tak, že vždy pouze část strany čtverce je vykreslena se spuštěným perem (a tedy viditelná) a zbylou část želva projde s perem zvednutým, tj. bez vykreslování či dalšího ovlivnění již vytvořené části grafického objektu:

; vykreslení kola s 36 loukotěmi
to wheel
    repeat 36 [
        right 10
        segment
    ]
end

; vykreslení jednoho segmentu - čtverce,
; s viditelnou částí stran
to segment
    repeat 4 [
        penup
        forward 60
        pendown
        forward 70
        left 90
    ]
end

; změna velikosti kreslicí plochy - tento příkaz
; je platný pouze pro Turtle Tracks
(draw 300 300)

; vykreslení celého obrazce
clearscreen
hideturtle
wheel 

logo1107
Obrázek 7: Pátý demonstrační příklad spuštěný v Turtle Tracks

8. Šestý demonstrační příklad – zobecnění vykreslení kola s loukotěmi

Proceduru pro vykreslení segmentu, která byla použita v pátém demonstračním příkladu, je možné zobecnit tak, aby bylo možné měnit poměr mezi vykreslenou a nevykreslenou částí strany čtverce. Čtverec má celkovou délku strany rovnou 144 krokům želvy a pomocí parametru :d je určeno, jak dlouhá má být neviditelná oblast, tj. oblast, přes kterou želva prochází se zvednutým kreslicím perem. V případě, že se hodnota tohoto parametru postupně zvyšuje (opět je použita procedura repcount pro zjištění aktuální hodnoty čítače smyčky), můžeme na výsledném obrázku vidět, jak se původní čtverec mění v několik krátkých čárek. Příklad je možné dále upravovat, například vynucením zpětného pohybu želvy při zadání záporného kroku, což je patrné z desátého obrázku.

; vykreslení obrace složeného z 36 segmentů
to wheel
    repeat 36 [
        right 10
        segment 2*repcount
    ]
end

; vykreslení jednoho segmentu - čtverce,
; s viditelnou částí stran
; poměr dělení stran je určen parametrem "d"
to segment :d
    repeat 4 [
        penup
        forward 2*:d
        pendown
        forward 2*(72-:d)
        left 90
    ]
end

; změna velikosti kreslicí plochy - tento příkaz
; je platný pouze pro Turtle Tracks
(draw 300 300)

; vykreslení celého obrazce
clearscreen
hideturtle
wheel 

logo1108
Obrázek 8: Šestý demonstrační příklad spuštěný v Turtle Tracks

logo1109
Obrázek 9: Zvýšený počet segmentů na 72 spolu se zmenšením úhlu otočení želvy na 5° po dokončení každého segmentu

logo1110
Obrázek 10: Obrázek vytvořený tak, že se příkaz forward 2(72-:d) zaměnil za forward 272–6*:d, tj. došlo k couvání želvy

logo1111
Obrázek 11: Při vykreslení každého čtverce se želva posunula o deset kroků dopředu

logo1112
Obrázek 12: Obdoba předchozího obrázku

bitcoin_skoleni

logo1113
Obrázek 13: Při vykreslení každého čtverce se želva posunula o deset kroků dozadu

9. Obsah následující části tohoto seriálu

V další části seriálu o programovacím jazyce Logo dokončíme poměrně rozsáhlou oblast želví grafiky a nakonec si vysvětlíme i další velmi důležitou součást tohoto jazyka – práci se seznamy a řetězci.

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.