Čárkování, lomení a šipky v Metapostu

26. 3. 2007
Doba čtení: 5 minut

Sdílet

Dnes se soustředíme na některé detaily vykreslování čar sledujících cesty. Seznámíme se s předdefinovaným vzorováním čar v Metapostu a s tím, jak vytvářet čárkování dle vlastního vzoru. Dále si ukážeme jednu někdy důležitou podrobnost při vykreslování lomených čar a na závěr probereme vykreslování šipek.

Vzorování čar

Předdefinované čáry

Metapost má předdefinovány čáry čárkované a tečkované. Syntaxe příkazu je následující:

draw cesta dashed evenly; vykreslí čáru čárkovanou úseky 3 pt vyplněnými a 3 pt vynechanými.

draw cesta dashed withdots; vykreslí tečkovanou čáru tečkami vzdálenými od sebe 5 pt.

Oba příkazy lze kombinovat s příkazem scaled (viz transformace, budeme se jimi teprve zabývat) takže:

draw cesta dashed evenly scaled 2; nakreslí čárkovanou čáru sledující path cesta s čárami a mezerami dvojnásobné velikosti,

draw cesta dashed withdots scaled 3; nakreslí tečkovanou čáru s tečkami 15 pt od sebe.

Obrázek ukazuje čtyři čáry, nakreslené shora dolů příkazy:

  • draw (0,10u)–(10u,10u) dashed evenly;
  • draw (0,7u)–(10u,7u) dashed withdots;
  • draw (0,4u)–(10u,4u) dashed evenly scaled 2;
  • draw (0,u)–(10u,u) dashed withdots scaled 2;
Cary1

Text celého programu je natolik triviální, že byste měli být schopni příkazy předcházející samotnému kreslení i příkazy následující napsat sami na základě obsahu předchozích dílů.

Složitější vzory je nutno nejprve registrovat jako obrázek a teprve poté použít. Manuál i práce Krátké uvádějí poměrně složitou konstrukci, která má dvě nevýhody, jednak se musí v obrázku použít na první kreslící příkaz, jednak v obrázku nemůže být víc než jeden vlastní vzor. V opačném případě Metapost při překladu hlásí chybu „příliš složitý obrázek“. Uvádím ji zde pro úplnost:

u=3mm; picture mojecary; umístíme někde na začátku, kde definujeme proměnné a měřítko

draw dashpattern(on 2u off .5u on u off 3u);

mojecary=curren­tpicture;curren­tpicture:=nullpic­ture; tyto příkazy umístíme někde dříve než budeme potřebovat vykreslit vzorkovanou čáru

draw(-5u,–15u)–(7u,25u) dashed mojecary; tento příkaz spojí příslušné body čarou, která má 2u délky vyplněno, mezeru 0,5u, 1u vyplněno a mezeru 3u.

Lze pochopitelně vymyslet i vzor složitější. Příkazy v závorce musí začínat příkazem on a končit off (nebo naopak), protože jinak by se čára (mezera) z konce vzoru spojila nerozeznatelně se začátkem dalšího.

V manuálu metapostu je uvedena též kombinace vlastní čáry s předdefinovaným čárkováním:

picture p; %definice názvu vzoru

draw dashpattern(on 15bp off 15bp) dashed evenly;

p=currentpictu­re;currentpic­ture:=nullpic­ture;% Nadefinování a zaregistrování vzoru, který je kombinací čárkované čáry a vlastního vzoru

draw cesta dashed p; % použití takto nadefinovaného vzo­ru.

Jednodušší konstrukci vlastního vzoru čáry jsem objevil víceméně náhodně zkusmo (není popsána v dokumentaci, ale funguje:

  1. Definujeme měřítko a pole obrázků (datový typ picture):
    u=1mm; picture p[];
  2. Jednotlivým členům pole přidělíme vzory:
    p0:=dashpattern(on 2u off .5u on u off .5u);
    p1:=dashpattern(on 2u off .5u on u off u);
  3. definované vzory použijeme pomocí konstrukce:
    draw (-5u,–15u)–(7u,25u) dashed p0;
    draw (-5u,–15u)–(25u,7u) dashed p1;

Výhodou je, že vzorů můžeme mít v rámci jednoho obrázku více a lze je používat opakovaně v různém pořadí dle potřeby.

Program kreslící čáry definované vlastním vzorem ukazuje následující obrázek:

Cary2a

A výsledek jeho činnosti je zde:

Cary2b

Konce čar a jejich lomení

Pokud používáme silnější čáry, může pro nás být důležité ovlivnit konce čar, případně tvar čáry v místě zalomení křivky.

Použijeme-li pero typu pencircle, je obdélník představující čáru (cestu) implicitně zakončen půlkruhem, přičemž střed tohoto půlkruhu je konec cesty. Podobně je tomu i u jiných definovaných tvarů pera. U pencircle je to však možno změnit modifikátory butt a squared.

pickup pencircle scaled 10; draw z1–z2; vykreslí první možnost, s půlkruhem

linecap:=butt;pic­kup pencircle scaled 10; draw z1–z2; vykreslí konec křivky jako useknutý, takže nepřesahuje konec cesty.

linecap:=squa­red;pickup pencircle scaled 10; draw z1–z2; vykreslí rovněž jako useknutý, ale přesahující konec cesty o polovinu čtverce o straně rovné průměru pera.

Vykreslujeme-li lomenou křivku, pak implicitně je linie křivky na tupé straně úhlu zakulacená linejoin:=rou­nded;

Pokud chceme, aby byl na obou stranách ostrý úhel, musíme před vykreslením zadat linejoin:=mite­red;.

Pokud zadáme volbu linejoin:=beve­led;, pak je špička tohoto úhlu rovně odříznutá.

Chceme-li dosáhnout korektní vykreslení s volbou mitered u velmi ostrých úhlů, může se stát, že budeme nuceni změnit systémovou proměnnou miterlimit, která ošetřuje poměr mezi tloušťkou čáry a výškou trojúhelníka, který v místě zalomení trčí do tupého úhlu.

Demonstrace konců čar a úhlů:

Následující program narýsuje několik čar různé tloušťky nad sebe. Nejtlustší narýsuje nejprve v implicitním nastavení, poté v nastavení linecap = butt, poté linecap = squared a nakoneclinecap = rounded. Hodnoty musejí být přiděleny dvojtečkou a rovnítkem, protože linecap už na počátku běhu programu hodnotu má (implicitní = rounded).

Oproti svému původnímu dobrému předsevzetí jsem nakonec použil jednoduchá makra bez parametrů. Dostaneme se k nim, až probereme jednotlivé datové typy a prvky řízení chodu programu. Zatím to berte tak, že tato makra interpret přimějí do místa jejich volání vložit jejich obsah (tj. příkazy mezi def makro = a enddef;), tedy úplně stejně, jako byste to tam vložili příkazem copy – paste. Pochopitelně, ještě elegantnější by bylo použití cyklu a maker s parametry, ale to už bych v tom měl na vašem místě totální zmatek.

Koncea

A toto je vzniklý obrázek:

Konceb

Následně uvádím program vykreslující čtyři zalomené čáry. Poprvé (shora dolů) je použito implicitní nastavení proměnné linejoin. Podruhé je změněno na hodnotu mitered, potřetí na beveled. Počtvrté je přidělena hodnota rounded, což je hodnota implicitní a nejhornější a nejspodnější čára jsou stejné. Povšiměte si, že text programu vznikl jen drobnými úpravami předchozího.

Lomenia

A toto je výsledný obrázek:

Lomenib

Šipka arrow

V různých schématech se uplatňují také šipky. K jejich zadání potřebujeme příslušnou cestu a příkaz podobný příkazu draw:

drawarrow mojecesta; vykreslí šipku směřující od začátku do konce cesty mojecesta.

drawarrow reverse(mojeces­ta); vykreslí šipku směřující opačně. Pozor na poněkud odlišnou syntaxi!

drawdblarrow mojecesta; vykreslí čáru se šipkami na obou koncích.

Změnami proměnné ahlength a ahangle můžeme změnit délku šipky na konci cesty a úhel, který budou svírat její ramena. Předefinováním příkazu arrow můžeme např. dosáhnout i toho, že šipka je nikoli na konci ale např. uprostřed nebo ve třetině cesty.

Následující program nakreslí nakreslí čtyři šipky. První směřuje doprava. Druhé dvě doleva (ale jednou je toho dosaženo příkazem reverse, podruhé předefinováním cesty) a poslední šipka je dvojitá:

Sipkya

Toto je výsledný obrázek:

bitcoin_skoleni

Sipkyb

Poznámka: body nad a pod v tomto (a nad i v předchozích příkladech) jsou použity čistě jen proto, aby čáry neležely na samém okraji obrázku. Existuje na to elegantnější řešení (několik různých, jak bývá u kvalitních programovacích systémů dost běžné), postupně se s nimi seznámíme (v souvislosti s barvami a v souvislosti s datovým typem picture).

Co bude příště

Především se budeme věnovat zakřiveným cestám a ovlivnění jejich tvaru pomocí různých parametrů. Dnes probrané čárkování nám umožní podívat se co nejnázorněji, jak nastavení těchto parametrů ovlivní výsledný tvar.

Autor článku