MFF UK / Ústav teoretické fyziky / Tomáš Ledvinka
Přednášky
. . . . . . . . . . . . . . . . . . . . . . . . . .
Programování pro fyziky (1.r)
  Úvod
  Programy a algoritmy
  Píšeme program
  Píšeme program II
  Procedury a funkce
  Malujeme funkce
  Chyby. Typy I.
  Typy II. Pole a Záznamy
  Pole II.Řetězce.Soubory.
  Gnuplot.Interpolace...
  Matice. Velké O...
  Fronta,Zásobník. Postscript
    Fronta
    Zásobník
    Postscript I
    Postscript II
    Postscript - cvičení
  Bin. soubory, ...
  Ukazatele,Objekty, ...
Počítačová algebra
Klasická elektrodynamika (2.r)
Vybrané partie OTR

Cvičení
. . . . . . . . . . . . . . . . . . . . . . . . . .
Programování pro fyziky (1.r)
Teoretická mechanika (2.r)
Klasická elektrodynamika (2.r)


Věda
. . . . . . . . . . . . . . . . . . . . . . . . . .
Diskové zdroje v OTR
Hyperbolické systémy v OTR


Kontakt
. . . . . . . . . . . . . . . . . . . . . . . . . .
Email
Konzultační hodiny


Ostatní
. . . . . . . . . . . . . . . . . . . . . . . . .
Mallorca
Ze společnosti

Grafický stav

Na výše uvedených příkladech vidíme, že

  • čáry mohou být různé
  • systém interpretující postscriptový obrázek si udržuje informaci o grafickém stavu
  • grafický stav měníme voláním specializovaných procedur
  • příkazy, např. stroke, pak malují podle toho, jaký je zrovna grafický stav (stroke namaluje jednou spodní oranžový, podruhé horní zelený trojúhelník)

Mimo jiné je součástí grafického stavu

  • okažitá poloha (nastaví moveto, mění mj. lineto)
  • cesta (newpath, moveto, lineto, curveto, closepath)
  • barva (mění procedura setcolor)
  • měřítko, poloha počátku a natočení os x a y (scale, translate a rotate, viz dále)
  • font ( viz Poznámky pro život a ne zkoušku dále)
  • způsob čárkování čáry (setdash, viz cvičení pro zvědavé.)

Princip grafického stavu má svůj původ již u souřadnicových zapisovačů, kde se barva měnila výměnou malovacího pera, a běžná poloha byla opravdu polohou pera nad papírem. Pro nás znamená existence grafického stavu, že vystačíme s jedinou procedurou stroke pro malování čáry, ať už je barevná, čárkovaná, rovná nebo křivá.

Cvičení: Měňte barvy

Cvičení: Vynechte přepnutí do barevného módu a změňte počet parametrů u všech volání procedury setcolor tak aby měly jeden parametr (0.0 = černá,1.0 = bílá).

Cvičení pro zvídavé: Přidejte do příkladů 1 a 3 před newpath příkaz
[30 30 160 30] 0 setdash
a pozorujte co se stane (první parametr je typu pole, proto ty hranaté závorky, druhý parametr je reálné číslo).

Příkazem setcolor se mění nenávratně barva jíž malujeme, podobně newpath nenávratně ničí dosavadní cestu. Protože barva i aktuální cesta jsou součástí grafického stavu, můžeme si je schovat pomocí procedury gsave, která na vnitřní zásobník (jiný, než ten pro předávání paramtrů procedurám) uloží kompletní grafický stav. Nyní můžeme dle potřeby měnit barvu, měřítka, aktuální polohu atd.a až skončíme, obnovíme původní grafický stav zavoláním procedury grestore.

Transformace souřadnic

Prozatím jsme respektovali, že počátek souřadnic se nachází vlevo dole, a že jednotkou jsou "body". Následujícími příkazy změníme nejprve měřítko z bodů na milimetry a poté si posuneme počátek do prostřed strany A4 ( 72 bodu na palec / 25.4 milimetrů na palec= 2.8346...bodu na milimetr ):

2.8346 2.8346 scale
105 148.5 translate

Obecně příkaz
x y translate
posune počátek na uvedenou polohu [x,y], podobně
uhel rotate
pootočí osy o daný úhel, a
meritko_x meritko_y scale
změní měřítka, ne nezbytně na obou osách stejně.

Následující příklad je ilustrací výše uvedených operací, tedy schovánání grafického stavu, rotací, posunů a škálování.

%priklad 4
2.8346 2.8346 scale
105 148.5 translate 

newpath
0 0 moveto
gsave
 20 0 lineto
 stroke
grestore 
gsave
 30 rotate
 2 2 scale 
 20 0 lineto
 stroke
grestore 
gsave
 60 rotate
 3 3 scale 
 20 0 lineto
 stroke
grestore 
gsave
 90 rotate
 3 3 scale 
 20 0 lineto
 stroke
grestore 
showpage

Cvičení: Napište program v Pascalu, který namalujte (tedy vytvoří postscripový soubor, který se vykreslí jako) ony kompletní n-úhelníky z minulé přednášky.

Poznámka: Operacemi moveto lineto lineto moveto linet

Křivky

V praxi bychom neměli používat cestu složenou ze stovek kousků. Pokud jde o malování plných čar vystačíme s jejím rozložením na více kratších cest (až na artefakty při napojování, které jsou vidět u tlustých čar, viz Příklad 3). Pokud je cesta obzvlášť křivá a na její konstrukci bychom potřebovali příliš mnoho úseček tak, aby nebyla viditelně polámaná, máme k dispozici proceduru na malování křivky curveto. Ta maluje parametrickou křivku [x(t),y(t)], kde funkce x(t) a y(t) jsou jsou kubické polynomy. (Mimochodem, úsečka je také takovou parametrickou křivkou, ale polynomy jsou jen prvního stupně.)

x(t) = x0+3 (x1-x0) t + 3(x2-2 x1+x0) t^2 + (x3- x0+3 x1-3 x2) t^3
y(t) = y0+3 (y1-y0) t + 3(y2-2 y1+y0) t^2 + (y3- y0+3 y1-3 y2) t^3
Vzorečky
(C) Bezier
Obrázek
(C) Adobe

Třetí stupeň byl zvolen proto, aby si člověk mohl zvolit nejen počáteční a koncový bod křivky (na to stačí úsečka - první stupeň), ale také tečny v obou koncových bodech (viz obrázek). To že tečný vektor[dx(t)/dt,dy(t)/dt] v bodě [x0,y0] (tedy v t=0 ) míři do bodu [x1,y1] se z derivace výše uvedených polynomů v t=0 pozná snadno. O něco méně je vidět, že v hodnotě parametru t=1, je [x(t),y(t)]=[x3,y3], a ješte skrytější je fakt, že tečna míří z [x3,y3] do bodu [x2,y2].

Pro nás nejjednodušší použití curveto je prosté proložení křivky čtyřmi body, A,B,C a D. Budeme požadovat aby v hodnotě parametru t=0 křivka procházela bodem A, v hodnotě t=1/3 bodem B, v hodnotě t=2/3 bodem C, v hodnotě t=1 bodem D. Tak dostaneme soustavu čtyř lineárních rovnic
x(0/3) = Ax
x(1/3) = Bx
x(2/3) = Cx
x(3/3) = Dx
pro čtyři neznámé x0,x1,x2,x3 (nacházející se ve funkci x(t)) a další, nezávislou soustavu čtyř rovnic pro čtyři neznámé y0,y1,y2,y3. Její řešení je

x0 = Ax
x1 = (18*Bx-5*Ax+2*Dx-9*Cx)/6
x
2 = (2*Ax-5*Dx+18*Cx-9*Bx)/6
x3 = Dx
  y0 = Ay
y1 = (18*By-5*Ay+2*Dy-9*Cy)/6
y
2 = (2*Ay-5*Dy+18*Cy-9*By)/6
y3 = Dy

Následující obrázek ilustruje, jak dobrou aproximací skutečné křivky mohou tyto kubické křivky být.

Červená křivka je čtvtkružnice. Modrá je výsledek curveto s parametry podle výše uvedených vzorečků. Zelené kroužky vyznačují polohu boudů A.B,C a D a odpovídají středovému úhlu kruhového oblouku 0,30,60 a 90 stupňů.

Příklad

Když už mluíme o parametrických křivkách, nelze vynechat zmínku o těch nejznámějších, Lissajousových obrazcích. Zde je program, který je za nás namaluje

program LissaPS;
{
  Maluje Lissajousovy obrazce
  Umí je malovat čarou nebo vyplnit
  Postscriptový obrázek vypíše na standardní výstup
}
const Vybarvit = true;

var AktualniPoloha : record
           x,y : real;
            OK : boolean;
    end;

procedure KusKrivky(Ax,Ay, Bx,By, Cx,Cy, Dx,Dy : real);
{Používá výše uvedené vzorečky a proloží body ABCD kubický oblouk}
var x1,y1,x2,y2 : real;
begin
           { nejdriv spocist polohu ridicich bodu }
       x1 := (18*Bx-5*Ax+2*Dx-9*Cx)/6.0;
       x2 := (2*Ax-5*Dx+18*Cx-9*Bx)/6.0;
       y1 := (18*By-5*Ay+2*Dy-9*Cy)/6.0;
       y2 := (2*Ay-5*Dy+18*Cy-9*By)/6.0;
           { na pocatku cesty musi byt newpath & moveto }
       if (not AktualniPoloha.OK) then Writeln('newpath');
       if (not AktualniPoloha.OK) or (AktualniPoloha.x<>Ax) or (AktualniPoloha.y<>Ay)
                                  then Writeln(Ax:4:2,' ',Ay:4:2,' moveto');
           { pokazde pak curveto }
       Writeln(x1:4:2,' ',y1:4:2,' ',x2:4:2,' ',y2:4:2,' ',Dx:4:2,' ',Dy:4:2,' ',' curveto');
       AktualniPoloha.x := Dx;
       AktualniPoloha.y := Dy;
       AktualniPoloha.OK:= true;
end;

procedure Obtahni;
begin
  Writeln('stroke');
  AktualniPoloha.OK:= false;
end;

procedure Vybarvi;
begin
  Writeln('fill');
  AktualniPoloha.OK:= false;
end;

procedure Lissajous(sx, sy, Polomer, fazex,fazey : real; kx,ky:integer);
{[sx,sy] je stred, faze* jsou faze obou harm. oscilatací ve stupních}
var i : integer;
    N : integer;
    Ax,Ay,Bx,By,Cx,Cy,Dx,Dy : real;

   function x(m:integer) :real; begin x:=sx+Polomer*sin(fazex+2*Pi/N*kx*(i+m/3.0)); end;
   function y(m:integer) :real; begin y:=sy+Polomer*sin(fazey+2*Pi/N*ky*(i+m/3.0)); end;

begin
    N := kx; if N<ky then N:=ky;
    N := N*8; {videli jsme, ze 4 staci na kruznici}

    fazex := fazex*Pi/180.0/kx;
    fazey := fazey*Pi/180.0/ky; {uz jsou v radianech}
    for i := 0 to N-1 do begin
       KusKrivky(
             x(0),y(0), {pocatecni bod krivky}
             x(1), y(1), { t = 1/3 }
             x(2), y(2), { t = 2/3 }
             x(3), y(3) {koncovy bod oblouku krivky}
                );
    end;
    if Vybarvit then Vybarvi else Obtahni;
    Writeln;
end;

Procedure SetColor(r,g,b:byte); {R G B v rozsahu 0..255}
begin
  Writeln(r/255.0:6:3,g/255.0:6:3,b/255.0:6:3,' setcolor');
end;

const R = 50; {polomer v milimetrech}

begin
    Writeln('/DeviceRGB setcolorspace');

    Writeln('2.8346 2.8346 scale'); {milimetry}
    Writeln('105 148.5 translate'); {do stredu A4}
    Writeln('0.1 setlinewidth');    {tenke cary}

    SetColor(255,174,17);
    Lissajous(-R,R, 40, 0,0, 1,2);

    SetColor(155,0,0);
    Lissajous(R,R, 40, 0,0, 3,4);

    SetColor(130,0,130);
    Lissajous(-R,-R, 40, 0,0, 7,8);

    SetColor(11,80,50);
    Lissajous(R,-R, 40, 10,0, 15,16);

    Writeln('showpage');
end.

Výstup tohoto programu je potřeba přesměrovat do souboru, a ten si poté můžeme prohlédnout, vytisknout či poslat emailem.

C:\Adresar>LissaPS>obr.ps
C:\Adresar>start obr.ps
C:\Adresar>

Příkaz start nám spustí ten program, který má v počítači na starosti postscriptové obrázkya pak uvidíme:

.

a nebo

 

Cvičení: Upravte program tak, aby místo křivek používal lomenou čáru. Použít můžete následující proceduru

procedure Lomenice(Ax,Ay, Bx,By, Cx,Cy, Dx,Dy : real);
begin
           { na pocatku cesty musi byt newpath & moveto }
       if (not AktualniPoloha.OK) then Writeln('newpath');
       if (not AktualniPoloha.OK) or (AktualniPoloha.x<>Ax) or (AktualniPoloha.y<>Ay)
                                  then Writeln(Ax:4:2,' ',Ay:4:2,' moveto');
           { pokazde pak 3x lineto }
       Writeln(Bx:4:2,' ',By:4:2,' lineto ',Cx:4:2,' ',Cy:4:2,' lineto ',Dx:4:2,' ',Dy:4:2,' ',' lineto');
       AktualniPoloha.x := Dx;
       AktualniPoloha.y := Dy;
       AktualniPoloha.OK:= true;
end;

Výsledek by pak měl vypadat takto:

Poznámky pro život a ne zkoušku:

Jazyk Postscript vziknul jako jazyk pro ovládání počítačových tiskáren a proto je největším odborníkem na písmenka. Protože může být někdy užitečné doplnit do obrázku pár písmenek, je v následujícím příkladě shrnuto několik nejpotřebnějších procedur pro práci s textem.

%priklad 5

(Helvetica) 40 selectfont

300 420 moveto

(ABC) show
(123) show

showpage


Vidíme, že

  • Řetězce jsou, jak vidíme uzavřeny v závorkách
  • procedura show má jediný parametr a to řetězec
  • show píše se na aktuální polohu a tu pak změní o šířku vypsanécho textu
  • Druh a velikost písma se nastavuje procedurou selectfont

Procedura selectfont má za první parametr název písma, druhý je jeho velikost.
Vždy k dispozici by (mimo jiné) měla být následující písma:

Vypadá to, že bychom už měli o jazyce postscript vědět to nejpodstatnější. Třeba bychom si mohli myslet, že když si budme prohlížet postscriptový soubor narazíme na série příkazů 213 321 moveto 545 545 lineto 45 544 moveto 577 889 lineto 54 889 lineto ....
Když ale nějaký otevřeme v textovém editou, zjistíme, že na počátku nejsou skoro žádná čísla, takže se tam dost dobře nemohou malovat příslušné křivky, na konci zase narazíme na spousti čísel a skoro žádná písmena. Vysvětlení je jednoduché. Postscritpt je programovací jazyk. Proto na začátku narazíme na oblast definic procedur a funkcí, tzv. prolog, na konci se pak tyto funkce používají. Proto program který má v úmyslu malovat spoustu trojúhelníků nejprve definuje proceduru pro malování trojúhelníků, a pak už používá ji místo neustálého newpath, moveto ...

%priklad X
/t {
 newpath 
 moveto 
 lineto 
 lineto 
 fill
} def

100 100 300 100 100 300 t
200 200 400 200 200 400 t
300 300 500 300 300 500 t

showpage

Programu nejlépe porozumíme, přeložíme-li si začátek podle tabulky

/t { --->
procedure
t;
begin
} def --->
end;

a uvědomíme-li si, že procedury moveto, lineto a ještě jednou lineto vyzvednou ze zásobníku každá dva parametry. Pak je zřejmé, že procedura t jich potřebuje šest.

Zájemce o další informace o jazyce Postscript může použít dokumenty, které firma Adobe dává volně k dipozici, především pak učebnici, kterou lze vygooglovat dotazem "postscript bluebook pdf" (240 stran), případně referenční příručku ("postscript PLRM pdf", 912 stran).

Konec poznámek pro život a ne zkoušku.

.