Obsah
1. Nástroje pro tvorbu grafů a diagramů z příkazové řádky
2. Základní informace o aplikaci gnuplot
3. Vytváření grafů funkcí a grafů vytvořených z externích dat
7. Jednoduché neorientované grafy
9. Praktický příklad – zobrazení závislostí mezi instalovanými balíčky
10. Ditaa aneb uživatelsky přívětivá tvorba diagramů z ASCII artu
12. Složitější příklady: styly spojnic
1. Nástroje pro tvorbu grafů a diagramů z příkazové řádky
V dnes již velmi rozsáhlé nabídce programů s otevřeným zdrojovým kódem můžeme nalézt poměrně velké množství aplikací určených pro interaktivní tvorbu diagramů a grafů. Jedná se například o známý program LibreOffice Draw či o aplikaci Dia, které jsou určeny mj. i pro tvorbu rozličných diagramů. Dvourozměrné a někdy i trojrozměrné grafy získané z různých typů dat lze vytvářet například v GNU Octave či (při menších nárocích) i v programu KChart. V praxi se však velmi často setkáme i s nutností vytvářet různé diagramy a grafy s využitím nástrojů ovládaných z příkazové řádky, tj. neinteraktivně a bez využití grafického uživatelského rozhraní.
Těchto nástrojů taktéž existuje celá řada, například specializovaný RRDtool či Ploticus. My se v dnešním článku seznámíme s poměrně známou aplikací gnuplot, dále pak s nástroji dostupnými v balíčku Graphviz a na závěr si popíšeme velmi zajímavý a přitom snadno ovladatelný nástroj nazvaný Ditaa, který se stává populární například mezi autory píšícími své knihy (či skripta) v jednoduchých značkovacích jazycích typu AsciiDoc či Markdown (evidentně tento nástroj vyhovuje filozofii takto zaměřených autorů).
2. Základní informace o aplikaci gnuplot
Aplikace gnuplot je určena pro tvorbu plošných (2D), ale i prostorových (3D) grafů, včetně možností vizualizace vektorových polí. Přitom se jedná o program, který je možné v celé šíři ovládat pouze z příkazové řádky, a to buď s využitím uživatelsky vytvořených skriptů, nebo interaktivním způsobem, tj. postupným zadáváním a následným prováděním příkazů zapsaných na standardní vstup (stdin), což většinou znamená z klávesnice, ale standardní vstup je samozřejmě možné pomocí prostředků operačního systému přesměrovat a použít místo něj například výstup z jiného běžícího procesu. Vývoj této aplikace probíhal velmi dlouho (poprvé jsem se s gnuplotem setkal ještě v dobách kralování DOSu na počítačích s procesorem 386 a pouhými čtyřmi megabyty RAM) a mimo jiné i proto se dnes jedná o jeden z nejvíce propracovaných programů určených pro dávkovou tvorbu grafů (mezi další používané aplikace s podobným zaměřením patří například plotutils, což je taktéž utilita, resp. sada utilit šířených pod GNU licencí).
Další předností gnuplotu je – minimálně pro programátory – zabudování poměrně sofistikovaného příkazového jazyka, pomocí kterého je možné zadávat a spouštět makra řídící načtení dat uložených v externím souboru, vytvoření grafu a jeho uložení, resp. export do zvoleného formátu atd. gnuplot se také vyznačuje malým počtem interních chyb – to je důležité zejména při dávkovém vytváření mnoha grafů, kdy není možná jejich důsledná kontrola člověkem a musíme se spolehnout na to, že grafy budou po automatickém zpracování korektní. gnuplot je k dispozici pro mnoho platforem, zjednodušeně je možné říci, že tam, kde se rozběhne nějaký překladač ANSI C (dokonce i šestnáctibitový), je možné zprovoznit i gnuplot.
Při popisu dalších vlastností gnuplotu začněme – možná poněkud netypicky – popisem možností exportu vytvořených grafů do některých podporovaných souborových formátů. Při výstupu grafů je možné použít jak rastrové, tak i vektorové grafické souborové formáty. Oba dva typy grafických formátů jsou totiž důležité: rastrovou grafiku využijeme například při publikování grafů na Internetu, vektorová grafika se naopak hodí při přípravě publikací určených pro tisk. Mezi podporované rastrové formáty patří PBM (Portable BitMap), PNG (Portable Network Graphics – vhodné pro web), GIF (pouze s podporou dalších knihoven), JPEG apod. Z vektorových formátů je podporován především PostScript, dále je pak možné provést výstup například do LATEXu, DXF (Drawing Interchange File Format – formát podporovaný prakticky každým CAD systémem) a do SVG.
S využitím gnuplotu je možné vytvářet velké množství grafů. Mezi nejjednodušší a současně také nejpoužívanější grafy patří zobrazení průběhů funkcí s jednou závislou a jednou nezávislou proměnnou. Takové funkce se vytvoří velmi jednoduše, například obligátní sinusovka vznikne příkazem:
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot1.png' plot sin(x)
Obrázek 1: Graf funkce jedné nezávislé proměnné.
Pokud je zapotřebí na grafu vyznačit průběhy více funkcí, není nic jednoduššího, než zadat například tento příkaz:
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot2.png' plot sin(x)/x, sin(x)/(x**2+1)
Jak je patrné z druhého obrázku, nastaví gnuplot automaticky i limity pro obě osy grafu. Tyto limity je však možné specifikovat i ručně či ve skriptu (to je nutné například při vytváření grafů, které se mají navzájem porovnávat).
Obrázek 1: Graf dvou funkcí jedné nezávislé proměnné.
Kromě grafů funkcí jedné nezávislé proměnné je však možné vytvořit složitější grafy, například parametrickou křivku:
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot3.png' i = {0.0,1.0} set parametric plot real(exp(i*t)), imag(exp(i*t*3))
Obrázek 3: Graf parametricky zadané funkce.
3. Vytváření grafů funkcí a grafů vytvořených z externích dat
Aplikace gnuplot podporuje i tvorbu grafů s využitím externích dat. Externí datové soubory, ve kterých jsou numerická data uložena, nemusí mít nějakou speciální předem předepsanou strukturu. Právě naopak, pomocí poměrně jednoduché syntaxe (příkazem using) se gnuplot nakonfiguruje přesně podle struktury konkrétního souboru, takže je možné zpracovat data vytvořená například ve formátu CSV apod. V podstatě je „pouze“ nutné specifikovat, které numerické hodnoty je potřeba ze souboru načíst a v jakém formátu se mají tyto údaje načítat. Gnuplot poté automaticky provede všechny potřebné konverze dat, data načte, zpracuje a následně vytvoří (tj. vykreslí či uloží do rastrového či vektorového souboru) požadovaný graf. Ukažme si tedy jednoduchý příklad, pomocí kterého je vykreslen graf sestrojený z několika hodnot uložených v textovém souboru. Příkaz provádějící načtení hodnot z textového souboru „test.txt“ a následné vytvoření grafu bude mít tento tvar:
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot4.png' plot "test.txt"
Datový soubor „test.txt“ byl získán následujícím skriptem napsaným v programovacím jazyku Lua:
local x for x=0.1, 25.0, 0.1 do local y = math.sin(x)/x print(y) end
Obrázek 4: Graf získaný z bodů uložených v externím souboru „test.txt“, ve kterém jsou specifikovány pouze jejich x-ové souřadnice.
4. Styly vykreslovaného grafu
Pokud by z libovolných důvodů nevyhovoval způsob kreslení jednotlivých bodů, ze kterých se graf skládá, pomocí malých křížků, je možné při kresbě grafu zadat specifikátor stylu kreslení – ten rozšiřuje možnosti příkazu plot. Existuje poměrně velké množství různých stylů, všechny si ukážeme na obrázcích, přičemž u každého popisu stylu bude uveden i příslušný příkaz, který vedl k tvorbě grafu. Na následujících screenshotech si všimněte, že v pravém horním rohu každého grafu je pomocí značky ukázáno, jaký styl (a mimo jiné také barva) je pro daný průběh funkce použit. To je výhodné zejména při slučování více průběhů funkcí do jednoho grafu.
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot5.png' plot "test.txt" with lines
Obrázek 5: Graf získaný předchozím skriptem, vrcholy jsou propojeny úsečkami.
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot6.png' plot "test.txt" with dots
Obrázek 6: Graf získaný předchozím skriptem, vrcholy se zobrazují formou bodů.
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot7.png' plot "test.txt" with linespoints
Obrázek 7: Graf získaný předchozím skriptem, kombinace předchozích dvou grafů.
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot8.png' plot "test.txt" with steps
Obrázek 8: Graf získaný předchozím skriptem, „schody“.
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot9.png' plot "test.txt" with boxes
Obrázek 9: Graf získaný předchozím skriptem, obdélníky začínající na x-ové ose.
5. Trojrozměrné grafy
gnuplot dokáže vykreslovat i trojrozměrné grafy, takže se v rychlosti podívejme na několik příkladů. Pro vytvoření trojrozměrných grafů, zejména grafů funkcí dvou nezávislých proměnných, se používá příkaz splot, kde písmeno „s“ značí surface.
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot10.png' splot x*y
Obrázek 10: Trojrozměrný graf získaný předchozím skriptem.
Poněkud složitější příklad se specifikací rozsahu v osách x a y:
set terminal png size 400,300 enhanced font "Helvetica,10" set output 'gnuplot11.png' set xrange [-10:10] set yrange [-10:10] splot sin(sqrt(x**2+y**2))/sqrt(x**2+y**2)
Obrázek 11: Trojrozměrný graf získaný předchozím skriptem.
6. Balíček nástrojů Graphviz
Zatímco nástroj gnuplot popsaný – i když pouze ve velmi zkrácené podobě – v předchozích pěti kapitolách je určený převážně pro kreslení různých typů dvourozměrných a trojrozměrných grafů, je v mnoha dokumentech popř. v různých reportech nutné vytvářet diagramy s uzly propojenými neorientovanými či orientovanými hranami. Pro tento účel je vhodné ve většině případů použít balíček nástrojů nazvaný Graphviz. V tomto balíčku nalezneme především utilitu dot, která na základě textové definice orientovaného či neorientovaného grafu vytvoří rastrový či vektorový obrázek s grafem, přičemž je možné zvolit, jaký algoritmus bude použit pro rozmístění uzlů a hran na vytvořeném obrázku. Textová definice grafu používá jednoduchý popisný jazyk, který je v současnosti podporován i několika dalšími nástroji a stává se tak nepsaným standardem pro mnoho programů pracujících s grafovými strukturami.
7. Jednoduché neorientované grafy
Podívejme se na jednoduchý příklad – graf se třemi uzly a čtyřmi hranami (spojnicemi) mezi těmito uzly. Takový graf může být popsán v textovém souboru s následující strukturou:
Obsah souboru graph1.dot:
graph languages { Algol -- "K&R C"; "K&R C" -- "ANSI C"; Algol -- Perl; Algol -- "PL/I"; }
Povšimněte si, že u některých uzlů bylo zapotřebí uzavřít jejich názvy do uvozovek. Není těžké zjistit proč – objevují se zde znaky, které by mohly být interpretovány odlišným způsobem (ampersand, mezera, lomítko) a uzavřením do uvozovek se (většina) těchto problémů automaticky vyřeší. Celý soubor začíná klíčovým slovem graph značící neorientovaný graf; ve skutečnosti je však možné celou hlavičku bloku vynechat (což ostatně dělají i některé nástroje). Neorientované hrany mezi jednotlivými uzly jsou naznačeny dvojicí znaků – a jak uvidíme v následující kapitole, bude tato značka u orientovaných grafů nahrazena šipkou.
O automatické rozmístění uzlů i hran a následné vykreslení diagramu do rastrového obrázku s formátem PNG se postará tento příkaz:
dot graph1.dot -T png & graph1.png
Výsledek si můžete prohlédnout na dalším obrázku zobrazeném pod tímto odstavcem. Příkaz dot v tomto případě vytvořil klasický strom s kořenem Algol, což nám v tomto případě vyhovuje.
Obrázek 12: Neorientovaný graf vytvořený na základě definičního souboru graph1.dot.
Zajímavé je, že příkaz dot zapisuje obrázek (či popis vektorového výkresu) na standardní výstup, takže je možné použít přesměrování standardního výstupu do souboru. Alternativní výstupní formáty jsou svg, gif a ps (PostScript).
Kromě příkazu dot lze použít i příkazy neato, fdp či sfdp, které se odlišují algoritmem použitým pro rozmístění uzlů diagramu.
8. Orientované grafy
Podívejme se nyní na tvorbu grafu, v němž jsou neorientované hrany mezi uzly nahrazeny šipkami. Použijeme přitom stejné uzly (přesněji řečeno uzly se stejným textem), jako tomu bylo i v předchozím příkladu. Změn v definičním textovém (zdrojovém) souboru je jen několik. První změnu můžeme vidět již na prvním řádku, protože se namísto klíčového slova graph používá slovo digraph. Dále se pak na dalších řádcích nahradila dvojice znaků – za šipku → naznačující přímo směr hrany:
Obsah souboru graph2.dot:
digraph languages { Algol -> "K&R C"; "K&R C" -> "ANSI C"; Algol -> Perl; Algol -> "PL/I"; }
Obrázek 13: Orientovaný graf vytvořený na základě definičního souboru graph2.dot.
U uzlů a hran je možné specifikovat různé vlastnosti a ovlivnit tak výsledné zobrazení grafu. Podívejme se na jednoduchou úpravu spočívající v tom, že se nejdříve deklaruje styl dvou uzlů (tvar uzlu + jeho barva) a následně se tyto uzly použijí pro specifikaci topologie grafu:
Obsah souboru graph3.dot:
digraph languages { Algol [shape=box]; Algol [color="#ff0000"]; "ANSI C" [color="#00ff00"]; Algol -> "K&R C"; "K&R C" -> "ANSI C"; Algol -> Perl; Algol -> "PL/I"; }
Obrázek 14: Orientovaný graf vytvořený na základě definičního souboru graph3.dot.
9. Praktický příklad – zobrazení závislostí mezi instalovanými balíčky
Jedním z praktických příkladů pro použití nástroje Graphviz je grafické znázornění závislostí mezi nainstalovanými balíčky. Na Linuxových distribucích založených na RPM je možné pro tento účel použít skript nazvaný rpmdep.pl, který vygeneruje soubor s koncovkou .dot a strukturou korespondující s výše popsanou strukturou orientovaných grafů. Nejdříve je nutné do systému nainstalovat balíček rpmorphan obsahující zmíněný skript rpmdep.pl:
yum install "rpmorphan"
Následně je již možné tento skript spustit s parametry -dot (určuje formát výstupního souboru), vim-enhanced.dot (jméno výstupního souboru) a vim-enhanced (jméno nainstalovaného balíčku, pro který zjišťujeme jeho závislosti):
rpmdep.pl -dot vim-enhanced.dot vim-enhanced
Skript by měl po svém spuštění vytvořit soubor nazvaný vim-enhanced.dot s následujícím obsahem. Konkrétní jména balíčků samozřejmě závisí na tom, v jaké distribuci a její verzi se tento skript spustí, příklad byl vytvořen pro Fedoru 20:
digraph "rpmdep" { vim_enhanced -> glibc; glibc -> basesystem; basesystem -> setup; basesystem -> filesystem; glibc -> glibc_common; glibc_common -> bash; bash -> ncurses_libs; ncurses_libs -> libstdc; libstdc -> libgcc; ncurses_libs -> ncurses_base; glibc_common -> tzdata; glibc_common -> libselinux; libselinux -> pcre; libselinux -> libsepol; libselinux -> xz_libs; glibc -> nss_softokn_freebl; vim_enhanced -> which; which -> info; info -> zlib; vim_enhanced -> perl_libs; perl_libs -> perl; perl -> perl_PathTools; perl_PathTools -> perl_Scalar_List_Utils; perl_Scalar_List_Utils -> perl_Carp; perl_Carp -> perl_Exporter; perl -> perl_constant; perl -> perl_threads_shared; perl_threads_shared -> perl_threads; perl -> gdbm; perl -> perl_Pod_Simple; perl_Pod_Simple -> perl_Pod_Escapes; perl_Pod_Simple -> perl_Getopt_Long; perl_Getopt_Long -> perl_Text_ParseWords; perl_Getopt_Long -> perl_Pod_Usage; perl_Pod_Usage -> perl_Pod_Perldoc; perl_Pod_Perldoc -> perl_podlators; perl_podlators -> perl_Encode; perl_Pod_Perldoc -> perl_parent; perl_Pod_Perldoc -> perl_HTTP_Tiny; perl_HTTP_Tiny -> perl_Time_Local; perl_Pod_Perldoc -> perl_File_Temp; perl_File_Temp -> perl_File_Path; perl_Pod_Perldoc -> groff_base; groff_base -> sed; sed -> libacl; libacl -> libattr; perl -> perl_Filter; perl -> perl_macros; perl -> perl_Socket; perl -> perl_Time_HiRes; perl -> perl_Storable; perl -> perl_Module_CoreList; perl_Module_CoreList -> perl_version; vim_enhanced -> gpm_libs; vim_enhanced -> vim_common; vim_common -> vim_filesystem; }
Nyní je již možné si známým postupem nechat vygenerovat příslušný (již poměrně rozsáhlý) graf:
Obrázek 15: Závislosti balíčku vim-enhanced zobrazené formou stromu.
Popř. lze příkaz dot nahradit jiným příkazem (neato, fdp či sfdp) a použít tak odlišný algoritmus určující rozmístění uzlů na obrázku:
Obrázek 16: Závislosti balíčku vim-enhanced zobrazené odlišným algoritmem.
Podobným způsobem lze vygenerovat graf závislostí i pro balíčky s mnohem větším množstvím závislostí. Jen na ukázku se podívejme na příklad balíčku java-1.7.0-openjdk, což je JRE Javy 1.7:
rpmdep.pl -dot openjdk.dot java-1.7.0-openjdk
digraph "rpmdep" { java_1_7_0_openjdk -> libXtst; libXtst -> glibc; glibc -> libgcc; glibc -> nss_softokn_freebl; glibc -> glibc_common; glibc_common -> tzdata; glibc_common -> bash; bash -> ncurses_libs; ncurses_libs -> ncurses_base; ncurses_libs -> libstdc; glibc_common -> libselinux; libselinux -> xz_libs; libselinux -> pcre; libselinux -> libsepol; glibc -> basesystem; basesystem -> setup; basesystem -> filesystem; libXtst -> libXi; libXi -> libXext; libXext -> libX11; libX11 -> libxcb; libxcb -> libXau; libX11 -> libX11_common; java_1_7_0_openjdk -> glib2; glib2 -> zlib; glib2 -> shared_mime_info; shared_mime_info -> pkgconfig; shared_mime_info -> libxml2; glib2 -> libffi; java_1_7_0_openjdk -> giflib; giflib -> libICE; giflib -> libSM; libSM -> libuuid; java_1_7_0_openjdk -> cups_libs; cups_libs -> openssl_libs; openssl_libs -> krb5_libs; krb5_libs -> sed; sed -> info; sed -> libacl; libacl -> libattr; krb5_libs -> coreutils; coreutils -> gmp; coreutils -> util_linux; util_linux -> libmount; libmount -> libblkid; util_linux -> audit_libs; util_linux -> pam; pam -> libpwquality; libpwquality -> cracklib_dicts; cracklib_dicts -> cracklib; cracklib -> gzip; pam -> libdb; util_linux -> libcap_ng; util_linux -> libutempter; libutempter -> shadow_utils; shadow_utils -> libsemanage; libsemanage -> ustr; libsemanage -> bzip2_libs; util_linux -> systemd_libs; systemd_libs -> dbus_libs; systemd_libs -> libgcrypt; libgcrypt -> libgpg_error; systemd_libs -> libcap; util_linux -> libuser; libuser -> popt; libuser -> openldap; openldap -> nss; nss -> nspr; nss -> chkconfig; nss -> nss_util; nss -> nss_softokn; nss_softokn -> sqlite; sqlite -> readline; nss -> nss_sysinit; openldap -> nss_tools; openldap -> cyrus_sasl_lib; coreutils -> grep; coreutils -> ncurses; krb5_libs -> gawk; krb5_libs -> keyutils_libs; krb5_libs -> libcom_err; krb5_libs -> libverto; openssl_libs -> ca_certificates; ca_certificates -> p11_kit; ca_certificates -> p11_kit_trust; p11_kit_trust -> libtasn1; cups_libs -> avahi_libs; java_1_7_0_openjdk -> libjpeg_turbo; java_1_7_0_openjdk -> java_1_7_0_openjdk_headless; java_1_7_0_openjdk_headless -> javapackages_tools; javapackages_tools -> libxslt; javapackages_tools -> lua; javapackages_tools -> python; python -> python_libs; python_libs -> gdbm; python_libs -> expat; javapackages_tools -> python_javapackages; python_javapackages -> python_lxml; python_lxml -> python_cssselect; java_1_7_0_openjdk_headless -> lcms2; java_1_7_0_openjdk_headless -> freetype; freetype -> libpng; java_1_7_0_openjdk_headless -> gdk_pixbuf2; gdk_pixbuf2 -> libtiff; libtiff -> jbigkit_libs; gdk_pixbuf2 -> jasper_libs; java_1_7_0_openjdk_headless -> atk; java_1_7_0_openjdk_headless -> pango; pango -> libthai; pango -> cairo; cairo -> pixman; cairo -> libXrender; cairo -> mesa_libGL; mesa_libGL -> libXfixes; mesa_libGL -> libdrm; libdrm -> systemd; systemd -> dbus; systemd -> tcp_wrappers_libs; systemd -> kmod_libs; systemd -> kmod; systemd -> cryptsetup_libs; cryptsetup_libs -> fipscheck_lib; fipscheck_lib -> fipscheck; cryptsetup_libs -> device_mapper_libs; device_mapper_libs -> device_mapper; systemd -> qrencode_libs; systemd -> acl; systemd -> diffutils; libdrm -> libpciaccess; libpciaccess -> hwdata; mesa_libGL -> libXdamage; mesa_libGL -> libXxf86vm; mesa_libGL -> mesa_libglapi; cairo -> mesa_libEGL; mesa_libEGL -> libwayland_client; mesa_libEGL -> libwayland_server; mesa_libEGL -> mesa_libgbm; cairo -> fontconfig; fontconfig -> fontpackages_filesystem; pango -> harfbuzz; harfbuzz -> graphite2; pango -> libXft; java_1_7_0_openjdk_headless -> tzdata_java; java_1_7_0_openjdk_headless -> gtk2; gtk2 -> libXcursor; gtk2 -> libXrandr; gtk2 -> hicolor_icon_theme; gtk2 -> libXinerama; gtk2 -> libXcomposite; java_1_7_0_openjdk -> pulseaudio_libs; pulseaudio_libs -> libsndfile; libsndfile -> libvorbis; libvorbis -> libogg; libsndfile -> flac_libs; libsndfile -> gsm; pulseaudio_libs -> libasyncns; pulseaudio_libs -> json_c; java_1_7_0_openjdk -> xorg_x11_fonts_Type1; xorg_x11_fonts_Type1 -> ttmkfdir; xorg_x11_fonts_Type1 -> xorg_x11_font_utils; xorg_x11_font_utils -> libfontenc; xorg_x11_font_utils -> libXfont; java_1_7_0_openjdk -> alsa_lib; }
Obrázek 17: Závislosti balíčku java-1.7.0-openjdk zobrazené odlišným algoritmem.
Obrázek 18: Závislosti balíčku java-1.7.0-openjdk zobrazené odlišným algoritmem (zvětšená část grafu).
10. Ditaa aneb uživatelsky přívětivá tvorba diagramů z ASCII artu
Třetím a současně i posledním nástrojem, s nímž se dnes alespoň ve stručnosti seznámíme, je aplikace nazvaná Ditaa. Jedná se o program vytvořený v Javě, nicméně nemusíte se bát, že jde o (další) typicky Javovský moloch :-), ale o relativně malou aplikaci, kterou lze získat na adrese http://sourceforge.net/projects/ditaa/. Ditaa slouží k převodu diagramů vytvořených v ASCII artu do bitmapových obrázků, typicky do formátu PNG. Tento program navíc – na rozdíl od výše popsané utility dot – zachovává umístění jednotlivých uzlů v diagramu, nesnaží se tedy o přeuspořádání do jiné podoby. To mj. znamená, že Ditaa bude používána v jiných oblastech než nástroje dostupné v balíčku Graphviz. Příklady si ukážeme v navazujících kapitolách.
11. Jednoduché příklady
Použití programu Ditaa je skutečně velmi jednoduché. Začněme s následujícím diagramem, který lze snadno vytvořit v jakémkoli textovém editoru (dokonce i v Notepadu :-):
+-------+ +------+ +------+ Algol +--->| PL/I + | +---+---+ +------+ | | | | v v +-------+ +-------+ | Perl | | K&R C | +-------+ +---+---+ | | v +-------+ | ANSI C| +-------+
Ditta automaticky zjistí, které znaky odpovídají uzlům a které hranám. Následně vytvoří tento obrázek:
Obrázek 19: První diagram vytvořený aplikací Ditaa.
V případě, že výsledný diagram neodpovídá očekávání, lze použít přepínač –debug, který povolí výpis různých ladicích informací na standardní výstup a současně do výsledného obrázku nakreslí mřížku:
ditaa version 0.9, Copyright (C) 2004--2009 Efstathios (Stathis) Sideris Running with options: debug Reading file: ditta1.txt Using grid: 0123456789012345678901234567890123456789 0 ( ) 1 ( ) 2 ( +-------+ +------+ ) 3 ( +------+ Algol +--->| PL/I + ) 4 ( | +---+---+ +------+ ) 5 ( | | ) 6 ( | | ) 7 ( v v ) 8 ( +-------+ +-------+ ) 9 ( | Perl | | K&R C | ) 10 ( +-------+ +---+---+ ) 11 ( | ) 12 ( | ) 13 ( v ) 14 ( +-------+ ) 15 ( | ANSI C| ) 16 ( +-------+ ) 17 ( ) 18 ( ) Locale: en_US Dialog.bold Rendering to file: ditta1_3.png Done in 0sec
Obrázek 20: První diagram vytvořený aplikací Ditaa při použití parametru –debug.
Podívejme se nyní na to, co se stane, když se jeden uzel posune (samozřejmě včetně spojnic):
+-------+ +------+ Algol +-+ | +---+---+ | | | | +------+ | | +-->| PL/I + v v +------+ +-------+ +-------+ | Perl | | K&R C | +-------+ +---+---+ | | v +-------+ | ANSI C| +-------+
Z obrázku je patrné, že i ve výsledku došlo k posunu uzlu:
Obrázek 21: Druhý diagram vytvořený aplikací Ditaa.
12. Složitější příklady: styly spojnic
Velmi snadným způsobem lze změnit styl spojnic (hran) mezi uzly. Stačí, aby jediný znak ve spojnici byl nahrazen znakem : (dvojtečka) nebo = (rovnost) a celá hrana bude vykreslena čárkovaně. Proč postačuje změnit jediný znak? Je tomu tak z toho důvodu, aby úpravy diagramu byly velmi rychlé, bez nutnosti „překreslovat“ celou hranu:
/-------\ +------+ Algol +-+ : \---+---/ | | | | +------+ | | +-->| PL/I + v v \------/ +-------+ +-------+ | Perl | | K∓R C | \-------/ +---+---+ | | v /-------\ | ANSI C| +-------+
Obrázek 22: Třetí diagram vytvořený aplikací Ditaa.
13. Změna stylu uzlů
Již na předchozím obrázku bylo naznačeno, jak lze jednoduše změnit styl uzlů, konkrétně zaoblení (libovolného) rohu: namísto znaku + (ostrý roh) se použije lomítko či zpětné lomítko (zaoblený roh). Různé varianty jsou ukázány níže:
/-------\ +------+ Algol +-+ | \---+---/ | | | | +------+ | | +-->| PL/I + v v \------/ +-------+ +-------+ | Perl | | K&R C | \-------/ +---+---+ | | v /-------\ | ANSI C| +-------+
Obrázek 23: Čtvrtý diagram vytvořený aplikací Ditaa.
Kromě toho je možné změnit i barevnou výplň jednotlivých uzlů. Jedná se sice o vlastnost, která není stabilizovaná, ale z dalšího obrázku je patrné, že (částečně) funguje. Částečně proto, že názvy barev roztáhnou jednotlivé uzly:
/------------------\ +------+ cRED Algol +--+ : \---+-----------+--/ | | | | | +------+ | | | +-->| PL/I + v v v \------/ +-------+ +------------------+ | Perl | | cBLU K&R C | \-------/ +---+-----------+--+ | | | | v v /------------------\ | cGRE ANSI C | +------------------+
Obrázek 24: Pátý diagram vytvořený aplikací Ditaa.
Poslední vlastností programu Ditaa je schopnost měnit tvar uzlů pomocí speciálních značek zapisovaných do složených závorek. Opět se podívejme na příklad:
/------------------\ +------+ cRED Algol {d} +--+ : \---+-----------+--/ | | | | | +------------+ | | | +-->| PL/I {s} | v v v \------------/ +-------+ +------------------+ | Perl | | cBLU K&R C {io} | \-------/ +---+-----------+--+ | | | | v v /------------------\ | cGRE ANSI C | +------------------+
Obrázek 25: Šestý diagram vytvořený aplikací Ditaa.
14. Odkazy na Internetu
- Plain-text diagrams take shape in Asciidoctor!
http://asciidoctor.org/news/2014/02/18/plain-text-diagrams-in-asciidoctor/ - Graphviz – Graph Visualization Software
http://www.graphviz.org/ - graphviz (Manual Page)
http://www.root.cz/man/7/graphviz/ - dot (Manual page)
http://www.root.cz/man/1/dot/ - Ditaa home page
http://ditaa.sourceforge.net/ - Ditaa introduction
http://ditaa.sourceforge.net/#intro - Ditaa usage
http://ditaa.sourceforge.net/#usage - Node, Edge and Graph Attributes
http://www.graphviz.org/doc/info/attrs.html - Graphviz (Wikipedia)
http://en.wikipedia.org/wiki/Graphviz