\setupoutput[pdftex]
\input ../pre-elug.tex
\useencoding[win]
\mainlanguage[de]
\definetyping[MP][option=MP]
\setuptyping[file][option=MP, small]
\runMPgraphicstrue

\appendtoks \let\handlecompoundcharacter\string \to \everyMPgraphic

%\showframe


\starttext

\subject{Geschichte}

\subsubject{\TEX\ und \METAFONT}

Donald Knuth schrieb sein Buch \quotation{The Art of Computer
  Programming}. Als die Druckfahnen vom Verleger zurückkamen, ärgerte
er sich so sehr über den verkorksten Satz des Buches, dass er sein
eigenes Textsatzprogramm \TEX\ schrieb. Weniger bekannt ist das
Programm \METAFONT, mit dem er passende Schriften dazu entwerfen
konnte. Seine Schriften sind sehr stark parametrisiert, das heisst,
es gibt globale Parameter, die die Serifenlänge, die x-Höhe, die
Kapitalhöhe, die Unterlänge etc.\ festlegen.  

\subsubject{Postscript}
 
Die Firma Adobe, eine Gründung ehemaliger Xerox-Mitarbeiter,
entwickelte eine Programmiersprache, die sich insbesondere zur
Beschreibung von Gedrucktem eignet.

\subsubject{Vor- und Nachteile}

\startitemize
\head{Vorteil von Postscript und \METAFONT}

reichhaltige Befehle für das Zeichnen von Linien

\head{Vorteil von Postscript}

wird direkt oder indirekt von den meisten Druckern (und Plottern)
verstanden 

\head{Vorteil von \METAFONT}

parametrische Kurven sind hervorragend darstellbar, Strichstärken sind
variabel 

\head{Nachteil von Postscript}

gewöhnungsbedürftige Postfix-Sprache

\head{Nachteil von \METAFONT}

Ausgabe ist geräteabhängige Bitmap

\stopitemize

\subsubject{Synthese}

Anfang der 90er Jahre veröffentlicht John Hobby von AT\&T Bell
Laboratories \METAPOST. Die Sprache ähnelt sehr stark \METAFONT, hat
aber Postscript als Ausgabeformat. Damit sind erzeugte Grafiken an
andere Geräte übertragbar, auf denen kein \METAFONT\ installiert ist
und die benötigte Auf\/lösung variiert. 

Was leider verlorengeht: Die Variation von Strichstärken während eines
Strichs. 

\subject{Eigenschaften von \METAPOST}

\subsubject{Makrosprache}

\METAPOST\ ist eine Makrosprache wie \TEX. Es ist sehr einfach, neue
Makros zu definieren. Da \METAPOST\ eine Interpretersprache ist,
werden Makros quasi zur Laufzeit aufgelöst. 

\startbuffer[pentagramm]
draw
  for i=0 upto 4:
    (50, 0) rotated (i*144) --
  endfor        
  cycle withcolor .8*red; 
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[pentagramm]}
\typebuffer[pentagramm]

%\iffalse

\subject{Wichtige Datentypen}

\subsubject{numeric}

Das sind Skalare, und zwar Vielfache von $1/65536$. Wenn sie als
Längenangaben herhalten, sind Postscriptpunkte gemeint, es sei denn,
sie sind mit einer Maßeinheit versehen.

\subsubject{Tupel}

Tupel können miteinander addiert und subtrahiert werden und mit
Variablen vom Typ \type{numeric} multipliziert oder durch sie
dividiert werden.

Es gibt drei Arten von Tupel: pair, color und transform.

\startitemize

\head{pair}

wird zur Angabe von Koordinaten verwendet. 

\startbuffer[quadrat]
pair a, b, c, d;
a := (50, 0);
b := (50, 50);
c := (0, 50);
d := (0, 0);
draw a--b--c--d;
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[quadrat]}
\typebuffer[quadrat]
%\setupbackgrounds[right][text][background=Quadrat]


\head{color} 

gibt eine Farbe als (Rot, Grün, Blau)-Tupel an.

\startbuffer[rgdemo]
for i=0 upto 5:
  fill fullcircle xyscaled 10 shifted (i*15,0) 
       withcolor (i/6*red+(1-i/6)*green);
endfor

for i=0 upto 5:
  fill fullcircle xyscaled 10 shifted (i*15,0) 
       withcolor (i/6*red+(1-i/6)*green);
endfor

\stopbuffer
\placefigure[right]{none}{\processMPbuffer[rgdemo]}
\typebuffer[rgdemo]
%\setupbackgrounds[right][text][background=Farbwechsel]


\head{transform}

ist ein Sextupel, das eine zweidimensionale Transfomation des Paars
$x$ in $y$ durch $y=Ax+b$ beschreibt ($A$ ist eine $2\times2$-Matrix
und $b$ ein pair). Die Transformationen sind meist einfacher
ausgedrückt, und zwar als \type{shifted}, \type{rotated},
\type{xscaled}, \type{yscaled}, \type{xyscaled}.

Transformationen lassen sich transformieren!

\startbuffer[rgbdemo]
for i=0 upto 5:
  fill fullcircle xyscaled 10 
       shifted (15i,0) 
       withcolor (i/6*red+(1-i/6)*green);
endfor

for i=0 upto 5:
  fill fullcircle xyscaled 10 
  shifted (15i,0) rotated 120
  shifted ((90,0) rotated -60)
  withcolor (i/6*green+(1-i/6)*blue);
endfor

for i=0 upto 5:
  fill fullcircle xyscaled 10 
  shifted (15i,0) rotated 240
  shifted (90,0)
  withcolor (i/6*blue+(1-i/6)*red);
endfor
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[rgbdemo]}
\typebuffer[rgbdemo]
%\setupbackgrounds[right][text][background=Farbrausch]

\stopitemize


\subsubject{Pfade}

Zwei Arten sind hier zu unterscheiden: path und pen.

Ein pen ist ein geschlossener Pfad, der eine konvexe Figur
beschreibt. Damit kann man dann malen. 

Im nächsten Beispiel ist der Stift als Ellipse vordefiniert. 

\startbuffer[pentagramm-fett]
pickup pencircle xscaled 10 yscaled 5;
draw 
for i=0 upto 4:
(50, 0) rotated (i*144) --
endfor
cycle;
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[pentagramm-fett]}
\typebuffer[pentagramm]
%\setupbackgrounds[right][text][background=Pentagramm fett]

Im nächsten Beispiel ist der Stift ein Fünfeck, das sehr ähnlich
definiert wird wie das Pentagramm.

\startbuffer[pentagramm-5]
pickup makepen (
for i=0 upto 4:
(5, 0) rotated (i*72) --
endfor
cycle)
draw 
for i=0 upto 4:
(50, 0) rotated (i*144) --
endfor
cycle;
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[pentagramm-5]}
\typebuffer[pentagramm]
%\setupbackgrounds[right][text][background=Pentagramm 5]

\subject{Pfade näher betrachtet}

\subsubject{gekrümmte Pfade}

Häufig möchte mann nicht nur Polygonzüge, sondern auch krumme Linien
malen. \METAPOST\ unterstützt kubische Splines. Ein kubischer Spline
über eine Abfolge von Punkten hat folgende Eigenschaften:

\startitemize
\item Er berührt alle Punkte.
\item Zwischen zwei Punkten ändert sich die Krümmung gleichmäßig. 
\item Die Krümmung in einem Punkt ist stetig (ändert sich nicht
  abrupt). 
\stopitemize

Für einen gekrümmten Pfad werden die beteiligten pairs einfach mit
\quotation{..} anstatt mit \quotation{--} verbunden.

\startbuffer[lakritz]
pickup pencircle scaled 3;
draw 
    (0,0) 
  for i=1 upto 8:
    ..(0,(i-.5)*10)..(0,-(i+.0)*10)
  endfor
  withcolor .8blue;
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[lakritz]}
\typebuffer[lakritz]
%\setupbackgrounds[right][text][background=Lakritz]

Man kann einen geraden Pfad in einen krummen Pfad übergehen
lassen. Ein Beispiel ist mein Vorschlag zum ELUG-Logo (nur der Vogel). 

\startbuffer[pinguin]
u = 20pt;

fill (0.4u,0)--(3.6u,0)..(3.2u,1.0u)..(3.2u,1.2u)
     ..(3.6u,1.6u)--(5.2u,2.0u)--(3.6u,2.4u)..(3.2u,2.8u)
     ..(2.0u,3.2u)..(1.2u,3.2u)..(0.8u,2.8u)..(0.4u,1.6u)
     ..cycle withcolor .2[white, black];
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[pinguin]}
\typebuffer[pinguin]
%\setupbackgrounds[right][text][background=Pinguin]

Auf diese Weise knickt ein Pfad beim Übergang ab. Wenn man am Übergang
auch Stetigkeit will, muss man drei statt zwei Striche setzen. 

\startbuffer[pinguinstetig]
u = 20pt;

fill (0.4u,0)---(3.6u,0)..(3.2u,1.0u)..(3.2u,1.2u)
     ..(3.6u,1.6u)---(5.2u,2.0u)---(3.6u,2.4u)..(3.2u,2.8u)
     ..(2.0u,3.2u)..(1.2u,3.2u)..(0.8u,2.8u)..(0.4u,1.6u)
     ..cycle withcolor .2[white, black];
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[pinguinstetig]}
\typebuffer[pinguinstetig]
%\setupbackgrounds[right][text][background=Pinguin krank]

\subsubject{Pfade lassen sich aufteilen}

Man kann einen Pfad in Abschnitte zerlegen. Ein Pfad beginnt bei 0 und
geht bis Anzahl der Punkte minus eins. So lassen sich die Pfeile,
leicht aufgespreizt, genau parallel zu den Windungen zeichnen (um
beispielsweise eine Gebrauchsanweisung für das Abrollen einer
Lakritzschnecke zu illustrieren).

\startbuffer[lakritzpfeil]
numeric windungen;
path lakritz, pfeil[];

windungen := 2;
lakritz :=
   for i=windungen step -1 until 1:
    (0,(i+.0)*10){right}..(0,-(i-.5)*10){left}..
  endfor
    (0,0){right} 
  for i=1 upto windungen:
    ..(0,(i-.5)*10){left}..(0,-(i*10)){right}
  endfor;

% Der erste und der letzte Abschnitt des Pfades
pfeil.1 := subpath (0.5, 0.1) of lakritz;
pfeil.2 := subpath (4windungen-0.5, 4windungen-0.1) of lakritz;

pickup pencircle scaled 3;
draw lakritz
  withcolor black;

% Diese Abschnitte werden leicht aufgespreizt gezeichnet
drawarrow pfeil.1 xyscaled 1.2 withcolor .5white; 
drawarrow pfeil.2 xyscaled 1.2 withcolor .5white; 
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[lakritzpfeil]}
\typebuffer[lakritzpfeil]
%\setupbackgrounds[right][text][background=Lakritz mit Pfeil]

An diesem Beispiel sieht man auch, dass man Kurven in bestimmten
Punkten eine Richtung aufzwingen kann, in diesem Fall durch \arg{left}
und \arg{right}. 

\subsubject{Überschneidungen}

Es lassen sich Überschneidungen von Pfaden finden, auch eine
Überschneidung eines Pfades mit sich selbst. Der Befehl dazu ist
\type{p intersectionpoint q}, der ein \type{pair} zurückgibt. Wenn
zwei Pfade einander mehrmals schneiden, wird nur ein Punkt
zurückgegeben. 

\startbuffer[schnpkt]
path stern;
stern := 
  for i=0 upto 4:
     (50, 0) rotated (i*144) --
  endfor
  cycle;

pickup makepen (
for i=0 upto 4:
(5, 0) rotated (i*72) --
endfor
cycle)

draw stern;

for i=1 upto length stern:
  undraw (subpath(i+1,i+2) of stern) intersectionpoint
         (subpath(i-1,i) of stern); 
endfor;

\stopbuffer

\placefigure[right]{none}{\processMPbuffer[schnpkt]}
\typebuffer[schnpkt]

\subsubject{Beispiel für Nachzeichnen: Flechtwerk}

Wenn sich Linien kreuzen, möchte man vielleicht die obere Linie
nachzeichnen. In diesem Fall hat die Linie ein Äußeres und ein
Inneres. Das wird dadurch erreicht, dass man mit einem dünneren Stift
über einen dickeren malt. Beim Nachzeichnen muss man darauf achten,
dass der dünne Stift in Strichrichtung auch den dicken abdeckt. Dies
ist möglich, indem man \type{linecap:=butt} setzt. 

\startbuffer[flechtwerk]
numeric u, i, p;
pair is;
path f, v, n, sp;
boolean drunter;

drunter := true;
u := 10;
f := (0u,6u){dir -45}..{dir -45}(3u,0u){dir 45}..
     {dir 45}(6u,6u){dir -45}..{dir -45}(7u,4u){dir -135}..
     {dir -135}(5u,0u){dir 135}..{dir 135}(2u,6u){dir -135}..
     {dir -135}(0u,2u){dir -45}..{dir -45}(1u,0u){dir 45}..
     {dir 45}(4u,6u){dir -45}..{dir -45}(7u,0u);

  pickup pencircle scaled 2;
  draw f withcolor .8red;
  
  pickup pencircle scaled 1;
  draw f withcolor .9white;

  for p=0 upto (length f)-3:
    v := subpath (p, p+1) of f;
    n := subpath (p+2, infinity) of f;
    forever:
      is := v intersectiontimes n;
      exitif xpart is=-1;
      if drunter:
        sp := subpath (ypart is -.1, ypart is +.1) of n;
      else:
        sp := subpath (xpart is -.1, xpart is +.1) of v;
      fi

      pickup pencircle scaled 2;
      begingroup interim linecap:=butt;
        draw sp withcolor .8red;
      endgroup;
      
      pickup pencircle scaled 1;
      draw sp withcolor .9white;
      drunter := not drunter;
      v := subpath (xpart is +.1, infinity) of v;
      show v;
    endfor
  endfor

\stopbuffer
\placefigure[right]{none}{\processMPbuffer[flechtwerk]}
\typebuffer[flechtwerk]

\subsubject{Aber wir waren noch bei den Datentypen}

Adleraugen werden gesehen haben, dass im Beispiel eben der Datentyp
\type{boolean} verwendet wurde. Er kann \type{true} und \type{false}
sein und mit \type{and}, \type{or} und \type{not} verknüpft werden.

Ein weiterer Datentyp ist picture, mit dem ganze Bilder gespeichert
werden können. Eine wichtige Variable dieses Typs ist
\type{currentpicture}. Ein Beispiel, wie man sie verwenden kann, ist
eine Ausschnittvergrößerung der Grafik von eben. Es soll demonstriert
werden, wo noch ein Fehler im Flechten liegt, zu dem ich noch keine
befriedigende Lösung gefunden habe. 

\startbuffer[asvg]
picture fl, cl;
pair vp, dp;
numeric vr, vf;
path vkreis, vkreisg;

numeric u, i, p;
pair is;
path f, v, n, sp;
boolean drunter;

drunter := true;
u := 10;
f := (0u,6u){dir -45}..{dir -45}(3u,0u){dir 45}..
     {dir 45}(6u,6u){dir -45}..{dir -45}(7u,4u){dir -135}..
     {dir -135}(5u,0u){dir 135}..{dir 135}(2u,6u){dir -135}..
     {dir -135}(0u,2u){dir -45}..{dir -45}(1u,0u){dir 45}..
     {dir 45}(4u,6u){dir -45}..{dir -45}(7u,0u);

  pickup pencircle scaled 2;
  draw f withcolor .8red;
  
  pickup pencircle scaled 1;
  draw f withcolor .9white;

  for p=0 upto (length f)-3:
    v := subpath (p, p+1) of f;
    n := subpath (p+2, infinity) of f;
    forever:
      is := v intersectiontimes n;
      exitif xpart is=-1;
      if drunter:
        sp := subpath (ypart is -.1, ypart is +.1) of n;
      else:
        sp := subpath (xpart is -.1, xpart is +.1) of v;
      fi

      pickup pencircle scaled 2;
      begingroup interim linecap:=butt;
        draw sp withcolor .8red;
      endgroup;
      
      pickup pencircle scaled 1;
      draw sp withcolor .9white;
      drunter := not drunter;
      v := subpath (xpart is +.1, infinity) of v;
      show v;
    endfor
  endfor

fl := currentpicture;
vp := subpath (4,5) of f 
      intersectionpoint
      subpath (7,8) of f;   
vr := 1u;
vf := 2;

dp := (1u, 3u);

vkreis := fullcircle scaled vr shifted vp ;
vkreisg := vkreis shifted -vp scaled vf shifted (vp+dp); 
clip currentpicture to vkreis;
cl := currentpicture;

draw fl;
draw vkreis;

draw cl shifted -vp scaled vf shifted (vp+dp);
draw vkreisg;
draw vp--(vp+dp) cutbefore vkreis
     cutafter vkreisg;

\stopbuffer
\placefigure[right]{none}{\processMPbuffer[asvg]}
\typebuffer[asvg]

Anmerkung: Der Kreis muss erst wieder auf die Null zentriert werden,
bevor er mit Inhalt vergrößert wird.

\subsubject{Strings}


\startbuffer[nikolaus]
path haus;
numeric u;

u:=25pt;
haus := (0u,0u)--(0u,2u)
      --(1u,3.5u)--(2u,2u)
      --(2u,0u)--(0u,2u)--(2u,2u)
      --(0u,0u)--(2u,0u);

drawarrow haus;

label.lft("Das",  point 0.5 of haus);
label.lft("ist",  point 1.5 of haus);
label.rt("das",   point 2.5 of haus);
label.rt("Haus", point 3.5 of haus);
label.top("vom",  point 4.25 of haus);
label.top("Ni",   point 5.5 of haus);
label.top("ko",   point 6.75 of haus);
label.top("laus", point 7.5 of haus);
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[nikolaus]}
\typebuffer[nikolaus]

%\fi

\subject{Komplexere Konstrukte}

\subsubject{Makros}

Makros können selbst definiert werden. Als Argumente können alle
Datentypen übergeben werden. Ein Beispiel: Reihe Perlen an eine
Schnur. Argumente: Der Radius einer Perle als \type{numeric} und die
Schnur als \type{path}. 

\startbuffer[kette]
def perlenkette(expr r, p) =
path pp;
numeric t;
t := ypart (fullcircle scaled r shifted point 0 of p
            intersectiontimes p); 
pp:=p;
if t>-1:
  forever:
    pp := subpath (t, infinity) of pp;
    fill fullcircle scaled r shifted point 0 of pp
    withcolor .8red+.3green+.9blue;
    t := xpart (pp intersectiontimes
    (fullcircle scaled (2*r) shifted point 0 of pp)); 
    exitif t=-1;
  endfor
fi

enddef;

path faden;
numeric radius, u;

u :=10pt;
radius := 2u;

faden := (0u,0u)..(5u,0u)..(3u,2u)..(7u,4u);

perlenkette(radius,faden);
\stopbuffer
\placefigure[right]{none}{\processMPbuffer[kette]}
\typebuffer[kette]
 


\subsubject{Vorrang: primär, sekundär, tertiär}

Wenn man ein Makro mit \type{def heiopei(expr a)} definiert, wird bei
der Auswertung der Makroaufruf durch den Ersetzungstext
ersetzt. Manchmal möchte man aber auch Makros auf die
Klammerschreibweise verzichten. Dann muss man den Vorrang angeben:
Mit welchem Vorrang bindet das Makro seine Argumente?

Das kann man mit den Definitionen \type{primarydef} und
\type{tertiarydef} einstellen. Im nachfolgenden Beispiel bindet der
definierte binäre Operator \type{squeezed} einmal stärker, einmal
schwächer als das \quotation{Strichziehmakro} \type{--}.

\startbuffer[doppel-prim]
primarydef p squeezed s = 
  p xscaled s yscaled (1/s) enddef;

numeric u;
pair a, b, c, d;

u := 50pt;
a := (1u, -1u);
b := (1u, 1u);
c := (-1u, 1u);
d := (-1u, -1u);
draw a--b--c--d squeezed 2;

pickup pencircle scaled 3;
draw (0, 0);
label.top ("(0,0)", (0,0));

\stopbuffer  

\placefigure[right]{none}{\processMPbuffer[doppel-prim]}
\typebuffer[doppel-prim]


\startbuffer[doppel-tert]
tertiarydef p squeezed s = 
  p xscaled s yscaled (1/s) enddef;

numeric u;
pair a, b, c, d;

u := 50pt;
a := (1u, -1u);
b := (1u, 1u);
c := (-1u, 1u);
d := (-1u, -1u);
draw a--b--c--d squeezed 2;

pickup pencircle scaled 3;
draw (0, 0);
label.top ("(0,0)", (0,0));
\stopbuffer  

\placefigure[right]{none}{\processMPbuffer[doppel-tert]}
\typebuffer[doppel-tert]

\subsubject{Gleichungen}

Der Ausdruck \type{:=} weist zu. Man kann mit \type{=} lineare Beziehungen
zwischen Punkten und Pfaden festlegen. In \METAPOST\ ist \type{a:=a+1}
möglich, \type{a=a+1} hingegen ein Widerspruch.

Dafür sind die Variablennamen
\type{x<zahl>}, \type{y<zahl>} und \type{z<zahl>} praktisch:
\METAPOST\ nimmt automatisch an, dass \type{z4=(x4, y4)} ist.

Beispiel: Finde den Schnittpunkt der Höhen im Dreieck.  

\startbuffer[hoehe]
numeric u;
u=12pt;

z1 = (2u,-4u) ;
z2 = (5u,2u) ;
z3 = (-2u,3u);
 

% Lot von z1 auf z2--z3
z23 = (z2-z3) rotated 90 shifted z1;

% Lot von z3 auf z1--z2
z12 = (z1-z2) rotated 90 shifted z3;

% Lot von z2 auf z1--z3
z13 = (z1-z3) rotated 90 shifted z2;

% Berechne die Schnittpunkte
z10 = whatever[z1,z23] = whatever[z2,z3];
z30 = whatever[z3,z12] = whatever[z1,z2];
z20 = whatever[z2,z13] = whatever[z1,z3];

%  Schnittpunkt der Hoehen
z0 = whatever[z2,z20] = whatever[z1,z10]; 

draw z1--z2--z3--cycle;

draw z1--z10;
draw unitsquare scaled .2u rotated angle(z1-z10) shifted z10;

draw z2--z20;
draw unitsquare scaled .2u rotated angle(z2-z20) shifted z20;

draw z3--z30;
draw unitsquare scaled .2u rotated angle(z3-z30) shifted z30;


show x0, y0;

pickup pencircle scaled 3pt;
draw z0;
\stopbuffer

\placefigure[right]{none}{\processMPbuffer[hoehe]}
\typebuffer[hoehe]

Die Ausgabe von Metapost ist nun: \type{>> 31.88026} und
\type{>> 7.9701 [1]}.

\subject{Fazit}

\METAPOST\ ist ein mächtiges und ausbaufähiges Makropaket zur
Erzeugung von Vektorgrafiken. 

\blank

Literatur und Links:

\startitemize
\item John Hobby, {\it A User's Manual for MetaPost}, 1991.
\item Hans Hagen, {\METAFUN}, 2000, \type{http://www.pragma-ade.com}.
\item Denis Roegels Seite, mit 3D-Grafik: \type{http://www.loria.fr/~roegel/metapost.html}
\item Hans Hagen, Puzzling Graphics with MetaPost, \type{http://www.tug.org/applications/pdftex/metafun.pdf}
\stopitemize

\stoptext
