Důležité!

Pozorně si přečtěte pokyny k výuce během rektorského volna!

HW06: Grafy funkcí v SVG

Odevzdávání úkolu je ukončeno.
Autor zadání Milan Fabian
Úprava Roman Lacko Peter Stanko Miroslav Jaroš
Odevzdávané soubory upřesněno na konci zadání
Začátek odevzdávání viz diskusní fórum
Bonus za brzké odevzdání neurčeno
Konec odevzdání 2020-09-03 24:00
K úkolu žádná kostra není
Deadline úkolu

Termín posledního odevzdání je na 95 % finální. Může se ještě posunout, pokud se vypíše nový zkouškový termín.

Doplnění zadání:

zatím žádné

Představení úkolu

Často se setkáváme s potřebou zobrazit více matematických funkcí graficky do jednoho obrázku. Ať už jde o graf závislosti ujeté vzdálenosti na čase, nebo graf závislosti teploty na dodané energii, sloučení více grafů do jedné (kartézské) souřadnicové soustavy nám pomáhá lépe si představit danou situaci.

Vaším úkolem bude napsat program, který umožňuje vykreslení více grafů jednoduchých funkcí do jednoho obrázku. Používat budete XML formát SVG který se dá jednoduše upravovat jako textový soubor.

Zadání

Notací $ \mathbb{X}_0 $ a $ \mathbb{X}^+ $ značíme číselnou množinu $ \mathbb{X} $ včetně nuly resp. kladnou část této množiny. Např. $ \mathbb{R}_0^+ $ jsou nezáporná reálna čísla.

Vytvořte kompletní spustitelný program, který bude číst zadání funkcí:

  • $ x + c $ pro nějaké $ c \in \mathbb{R_0^+} $

  • $ x - c $ pro nějaké $ c \in \mathbb{R_0^+} $

  • $ a x $ pro nějaké $ a \in \mathbb{R} $

  • $ \sin x $

  • $ \cos x $

Pro každou zvolenou funkci $ f $ program vypíše tabulku s funkčními hodnotami pro $ x \in \{-5, \dots, 5\} $ na standardní výstup. Zároveň, pokud je to požadováno, bude program vykreslovat do souboru v SVG formátu grafy zadaných funkcí.

Požadavky

Spouštění programu

Program se bude spouštět bez parametrů nebo s pěti parametry:

./svggraph
./svggraph FILE W H X Y

Parametry programu jsou:

FILE

Název SVG souboru, do kterého se vykreslí grafy funkcí.

W, H

Šířka a výška grafu v SVG souboru v pixelech.

X, Y

Relativní velikost grafu na zadaných osách. Graf bude pokrývat hodnoty $ x \in \left[ -X, X \right] $ resp. $ y \in \left[ -Y, Y \right] $.

W, H, X a Y musí být přirozená čísla ($ \mathbb{N} $).

V případe spuštění bez parametrů program vypisuje pouze tabulky na standardní výstup. Jestliže se program spustí s pěti parametry, vypisuje se na standardní výstup a zároveň do SVG souboru.

Pokud uživatel zadá špatný počet nebo nesprávný formát parametrů, program vypíše na standardní chybový výstup hlášku s vysvětlením, kde nastala chyba, a skončí s nenulovou návratovou hodnotou.

Příklad spuštění s výstupem do SVG

./svggraph output.svg 500 500 10 15

Načítání vstupů

Vždy, když program očekáva zadání příkazu, vypíše na standardní výstup znaky > a  (mezera).

Program bude umět načítat, zpracovat a vykreslovat následující typy funkcí přesně v tomto tvaru):

y = a x

a je libovolné (i desetinné) číslo, například y = -1.5 x

y = x + a

a je nezáporné číslo, například y = x + 3 (pozor, y = x + -3 není korektní zadání funkce!)

y = x - a

a je nezáporné číslo, například y = x - 4.32

y = sin x
y = cos x
  • Program akceptuje i předpis funkce, ve kterém jsou mezery ze vzoru nahrazeny více mezerami, např.

    y  = sin     x
  • Každé zadání funkce musí být na vstupu ukončeno znakem nového řádku.

  • Můžete si pro vlastní zábavu přidat i další funkce (vzorové řešení jich má několik). Nedoporučujeme však zavádět „exotické formáty“, protože se můžete trafit do něčeho, co testy považují za neplatný vstup.

V případě zadání desetinného čísla se číslo před použitím ve výpočtech zaokrouhlí na 2 desetinná místa. Rovněž všechny vypisované hodnoty je třeba zaokrouhlit na 2 desetinná místa.

Hodnoty se zaokrouhlují matematicky, tj. výsledkem je číslo s dvěma desetinnými místy, které je na číselné ose nejblíže zaokrouhlovanému číslu.

Jestliže uživatel zadá nekorektní funkci, program o tom vypíše následující hlášku na standardní chybový výstup:

Bad command or function

včetně znaku pro nový řádek a pokračuje dál v načítání od uživatele.

Příklady nesprávně zadaných funkcí

> y = 2x
Bad command or function
> y = x -2
Bad command or function
> y = 3 x#
Bad command or function
> zadání stejně nikdo nečte
Bad command or function

Program musí být ukončen zadáním příkazu exit, po kterém uvolní zdroje a skončí úspěšně. Můžete implementovat příkaz list, který vypíše všechny dostupné funkce.

Standardní výstup

Výstupem je orámovaná tabulka. Formát orámování musí odpovídat vzorové implementaci.

  • První řádek obsahuje hodnoty x (pro $ x \in \{-5, \dots, 5\} $).

  • Druhý řádek pak odpovídající hodnoty $ f(x) $ pro zvolenou funkci $ f $.

Všechny hodnoty jsou zarovnané doprava a vypsané s přesností na dvě desetinná místa podle stejných pravidel zaokrouhlování jako pro vstup.

Kromě prvního sloupce mají všechny buňky stejnou šířku.

Příklad výstupu pro funkce $ y = 0.5 x $ a $ y = \cos x $

> y = 0.5 x
+---+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| x |-5.00|-4.00|-3.00|-2.00|-1.00| 0.00| 1.00| 2.00| 3.00| 4.00| 5.00|
| y |-2.50|-2.00|-1.50|-1.00|-0.50| 0.00| 0.50| 1.00| 1.50| 2.00| 2.50|
+---+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
> y = cos x
+---+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| x |-5.00|-4.00|-3.00|-2.00|-1.00| 0.00| 1.00| 2.00| 3.00| 4.00| 5.00|
| y | 0.28|-0.65|-0.99|-0.42| 0.54| 1.00| 0.54|-0.42|-0.99|-0.65| 0.28|
+---+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+

SVG soubor

Pokud je program spuštěn s parametry, pak při spuštění otevře soubor v prvním argumentu pro zápis. Jestliže již existuje, jeho obsah se zahodí. Pokud se soubor nepodaří otevřít, program o tom vypíše hlášku na standardní chybový výstup a skončí s nenulovou návratovou hodnotou.

Do SVG souboru se hned po spuštění programu (ještě před načítáním vstupu od uživatele) zapíše hlavička SVG souboru a vykreslí se (alespoň) osy kartézské souřadnicové soustavy včetně popisků. Můžete vykreslit i další dekorace, např. mřížku.

Pokud uživatel zadá korektní předpis funkce, pak se do souboru přidá její graf. V souboru musí zůstat všechny dosud vykreslené grafy.

Žádná část grafu nesmí být vizuálně vykreslená do záporných souřadnic SVG souboru, ani do souřadnic větších než zadaná výška a šířka SVG souboru (druhý a třetí parametr při spouštění programu).

Vykreslování mimo souřadnice SVG můžete odhalit pomocí značky g:
<?xml ... ?>
<svg ...>
    <g transform="translate(100 100)">
        <!-- původní obsah SVG souboru -->
    </g>
</svg>

Zkuste hodnoty v translate taky změnit i na záporné. Pak by vám mělo vzniknout něco takového.

Graf každé zadané funkce bude vykreslený jinou (náhodnou) barvou. Barva nesmí být příliš světlá, zabraňte vygenerování přiliš světlé barvy.

Velice jednoduchá heuristika (kterou používá i vzorové řešení) je např. generování barvy, kde průměrná hodnota (nebo součet) R, G a B složek nesmí překročit určitou hranici.

Kromě grafu funkce se do SVG souboru vypíše do pravého horního rohu zadání funkce, stejnou barvou, jakou je vykreslený graf. Zadání dalších funkcí se vypisují pod sebe.

Po zadání příkazu exit program dokončí práci se souborem tak, aby jeho obsah byl korektní SVG obrázek.

Přesné rozvrhnutí barev a velikosti písma není požadováno, výstupní SVG soubor bude kontrolovat cvičící.

coords.svg: ukázka možného výstupního SVG souboru po spuštění programu a příkazu exit:

./svggraph coords.svg 1000 500 10 5

coords2.svg: Jiný výstup pro stejný příkaz.

graph.svg: Ukázka výstupního SVG souboru se stejnými rozměry pro funkce y = x + 1.5 a y = sin x.

complex.svg: Zkuste implementovat tohle

Bonusy

Tangens (0,5 bodu)

Implementujte načítání, zpracování a vykreslování funkce tangens

y = tg x

podle stejných pravidel jako pro funkci $ \sin x $.

Kvadratická funkce (0,5 bodu)

Implementujte načítání, zpracování a vykreslování funkce

y = a x2 + b x + c

pro $ a \in \mathbb{R} $, $ b, c \in \mathbb{R}_0^+ $ včetně variant, kde se některé + nahradí za - (celkem tedy 4 předpisy).

Pro vhodně zvolené hodnoty konstant lze touto funkcí implementovat některé funkce ze základního zadání.

Nefunkce (0,5 bodu)

Implementujte příkazy, které se tváří jako funkce:

draw rectangle w h
draw circle r

Funkční hodnoty těchto předpisů nechť oscilují takovým způsobem, že výsledek vytvoří geometrický útvar, a to buď kruh nebo obdélník. Význam parametrů i polohy útvarů vyčtěte z chování vzorové implementace.

Pro uznání bonusu nelze použít značky SVG, které útvary vytvoří přímo (např. rect nebo circle). Tyto příkazy musí vykreslit funkční hodnoty!

V testech tohoto bonusu se konkrétní hodnoty v tabulce nekontrolují.

Hodnocení

  • Testy nanečisto (1 b) pokrývají pouze tabulkový výstup.

  • Testy naostro (9 b) mají hodnocení rozdělené následujícím způsobem:

    • (2 b) okrajové případy.

    • (3 b) testy pro tabulkový výstup,

    • (4 b) testy pro SVG výstup, hodnotí cvičící.

Lze tedy úkol implementovat i bez SVG výstupu, pokud vám stačí pouze 6 bodů.

Grafické provedení SVG výstupu se nemusí přesně shodovat se vzorem. Požaduje se pouze dodržet požadavky uvedené v zadání. Testy pouze ověří, že vygenerovaný soubor existuje a je korektní SVG. Pokud test je výstup v tabulce špatný nebo vygenerovaný SVG soubor není korektní, cvičící výstup nekontroluje!

Pro získání bodů z bonusových rozšíření musíte implementovat základní část včetně výstupu do SVG!

Poznámky

Odevzdávané soubory

V tomto úkolu můžete řešení úkolu rozdělit do souborů podle uvážení. Omezení jsou:

  • Odevzdávejte pouze soubory .c nebo .h.

  • Soubory v podadresářech nebo s prefixem test se ignorují.

Soubory s prefixem test použijte pro vlastní testy.

Nedoporučujeme nacpat celé řešení do main.c! Snažte se jej rozdělit rozumně na části.

Rozšíření

Je povoleno používat funkce matematické knihovny math.h. Program překládejte takto:

$ gcc ... -o svggraph -lm

(tj. -lm by měl být poslední argument příkazové řádky). Pokud používáte CMake, knihovnu přidáte příkazem target_link_libraries za add_executable.

Navíc je povoleno používat rozšíření POSIX.1-2008, které povolíte stejně jako v HW05. Nelze v tomto úkolu používat funkce GNU.

Materiály

  • Specifikaci formátu SVG můžete najít na stránkách W3C. Dobrý seriál o formátu SVG se nachází na portálu root.cz.

  • Zde si můžete zkontrolovat, zda je váš výsledný SVG soubor validní. Na kontrolu validity můžete taktéž využít nástroj xmllint dostupný na Aise.

Ostatní

  • Vzorové řešení naleznete na Aise:

    /home/kontr/pb071/hw06/svggraph
  • Protože má program pracovat s desetinnými čísly a přesnost typů float a double v C není při práci s velikými čísly v desítkové soustavě úplně přesná, nebude se kontrolovat práce s čísly většími než 5000.

  • Program může (ale nemusí) umět zpracovávat i hodnoty ve tvaru .1 a 1. (například y = x + .1). Toto vám dovolí použít některé funkce ze standardu jazyka C.

  • V případě nejasností se podívejte, jak reaguje vzorové řešení.