Metapost cheatsheet

outputtemplate := "%c.svg";
outputformat   := "svg";

color grey ; grey:= (200/255,200/255,200/255) ;

set up outils

Placer des points

Alt text

beginfig(101);
    % Les points sont des couples de valeurs `x` et `y`. Dans Metapost, ils se nomment `z1`, `z2`, `z3`, etc.
    % le premier chiffre correspond à la valeur pour `x`, le deuxième à `y`.
    z1 = (0, 50);
    z2 = (100, 100);

    % Ici, nous définissons implicitement le point `z3`  en donnant les valeurs en `x` et en `y`.
    x3 := 200;
    y3 := 150;

    % La ligne suivante permet d'afficher nos trois points numérotés. 
    dotlabels.top(1, 2, 3); 
endfig;

Tracer des lignes

Alt text

beginfig(102);
    z1 = (0, 50);
    z2 = (100, 100);
    z3 = (200, 150);

    % La commande `draw` permet de dessiner des chemins.
    % Ici, on demande à metapost de tracer la ligne droite allant de `z1`à `z2`;
    draw z1--z2;

    % On peut choisir une couleur autre que le noir.
    draw z2--z3 withcolor blue;

    % La ligne suivante permet d'afficher nos trois points numérotés. 
      dotlabels.top(1, 2, 3)
endfig;

Utiliser différentes plumes

Alt text

beginfig(103);
    z1 = (25, 25);
    z2 = (25, 50);
    z3 = (100, 75);

    z4 = (25, 75);
    z5 = (25, 100);
    z6 = (100, 125);

    z7 = (25, 125);
    z8 = (25, 150);
    z9 = (100, 175);

    % La commande `pickup` permet de choisir la plume de son choix.
    % La plume `pencircle` est celle par défaut.
    % Le mot clé `scaled` suivi d'une valeur permet d'en préciser l'épaisseur
    pickup pencircle scaled 4; 
    draw z1--z2--z3;

    % La plume `pensquare` est simplement de forme carré
    pickup pensquare scaled 4;
    draw z4--z5--z6;

    % La plume `penrazor` n'a qu'une largeur et pas d'épaisseur. C'est une plume biseautée.
    pickup penrazor scaled 4;
    draw z7--z8--z9;
endfig;

Utiliser différentes terminaisons

voir Métapost raconté piétons, page 21.

Les terminaisons et jonctions des traits sont choisies par l’intermédiaire de deux variables pouvant prendre trois valeurs.

Pour la terminaison, la variable et ses trois valeurs % possibles sont : linecap:=butt; ou squared; ou rounded; (défaut)

Pour la jonction, la variable et ses trois valeurs possibles sont : linejoin:=beveled; ou mitered; ou rounded; (défaut).

Ici un exemple montrant montre un tracé avec des terminaisons en butt et une liaison en beveled :

Alt text

beginfig(104);
    z1 = (25, 25);
    z2 = (25, 50);
    z3 = (100, 75);

    linecap:=butt; 
    linejoin:=beveled;

    draw z1--z2--z3 withpen pencircle scaled 9; 
endfig;

Plume tournante?

cf. Gerrit Nordzij, The stroke

Alt text

beginfig(105);
    z1 = (0,0);
    z2 = (100,0);

    penpos1(10,90);
    penpos2(30,90);

    % Cette fonction s'appuie sur le penrazore dessing produit est un contour.
    penstroke z1e{up}..z2e..cycle;

    dotlabels.top(range 1 thru 2);
endfig;

Définir des unités et dessiner une grille basique pour rendre visible ces unités.

u:=20mm; % On définit ici l'unité de base. 20mm devient le pas de la grille.
width := 9u;
height:=6u;

fonction grille pour générer une grille def glyphe(suffix unicode, visible)= beginfig(unicode); if visible > 0: epaisseurgrille:=u/20; pickup pencircle scaled epaisseurgrille; boucle grille verticale for i=0 upto width/u: draw (iu, 0)--(iu, height) withcolor black; endfor boucle grille horizontale for i=0 upto height/u: draw (0, iu)--(width,iu) withcolor black; endfor enddef;

glyphe(106, 1);
endfig;

%![Fig. 107](figures/107.svg)

Définir des unités et dessiner une grille typographique

u:=20mm; % unité de base
chasse:=5u;
ascendante:=5u;
descendante:=2u;
hauteurx:=3u;
lignebase:=0u;

fonction grille pour générer une grille def glyphe(suffix unicode, visible, chasseunit)= 0 ou 1 comme premier argument pour rendre visble la grille et une valeur comme deuxième argument pour augmenter ou réduire la chasse en relation à l'unité de base beginfig(unicode); chasse:=chasseunitu; if visible > 0: epaisseurgrille:=u/40; pickup pencircle scaled epaisseurgrille; % boucle grille verticale for i=0 upto chasseunit: draw (iu, (ascendante+1u))--(iu, -(descendante+1u)) withcolor grey; endfor % boucle grille horizontale for i=(-descendante/u) upto ((0+ascendante)/u): draw (0, iu)--(chasse,i*u) withcolor grey; endfor

    pickup pencircle scaled (epaisseurgrille*2);
        % ligne de base
        draw (0,0)--(chasse,0) withcolor black;
        % ligne ascendante
        draw (0,ascendante)--(chasse,ascendante) withcolor .8grey;
        % ligne de hauteur d'x
        draw (0,hauteurx)--(chasse,hauteurx) withcolor .8grey;
        % ligne descendante
        draw (0,-descendante)--(chasse,-descendante) withcolor .8grey;
enddef;

glyphe(107, 1, 12);
    z1 = (25, 25);
    z2 = (25, 50);
    z3 = (100, 75);
endfig;

%![Fig. 107](figures/107.svg)

Se tailler sa propre plume

Attention faut pas que ça soit trop compliqué et il faut bien fermer le chemin avec cycle

Alt text

beginfig(108);
    % Il faut tout d'abord définir la forme de notre plume à l'aide d'un chemin.
    path p;
    p := dir(-30)--dir(90)--dir(210)--cycle;

    % On transforme ce chemin en plume.
    pen pentriangle;
    pentriangle := makepen(p);

    % On teste notre plume
    draw (0,0)--(20, 20) withpen pentriangle scaled 3;
endfig;

dessiner

Préciser la direction du tracé

Dessiner un A façon old script en utilisant des directions

Alt text

beginfig(202)
     z1 = (1u,0u);
     z2 = (4u,5u);
     z3 = (5u,0u);
     z4 = (1u,2u);
     z5 = (3u,1u);
     z6 = (6u,2u);

     draw z1--z2--z3{up}..z4..z5..z6;
endfig;

Dessiner une variante du T Lyno de Radim en utilisant des direction

Cf https://radimpesko.com/fonts/lyno

Alt text

beginfig(203);
    z1 = (2u, 2u);
    z2 = (2u, 4u);
    z3 = (1u, 4u);
    z4 = (3u, 4u);

    draw z1--z2{up}..z3{down}..{right}z4;

    % On numérote les points de 1 à 4
    dotlabels.top(range 1 thru 4); 
endfig;

Être plus précis en spécifiant des angles

Alt text

beginfig(204);
    z1 = (2u, 2u);
    z2 = (2u, 4u);
    z3 = (1u, 4u);
    z4 = (3u, 4u);

    draw z1--z2{dir 110}...{dir 260}z3{dir 290}...{dir 20}z4;

    dotlabels.top(range 1 thru 4); 
endfig;

S'y retrouver en dessinant un cadrant d'angles

Alt text

beginfig(205);
    z1 = (2u, 2u);
    z0 = (4u, 2u);
    z90 = (2u, 4u);
    z180 = (0u, 2u);
    z270 = (2u,0u);

    drawarrow z1--z0;

    dotlabels.top(0, 90, 180, 270);
endfig;

relier des points avec des courbes

Alt text

beginfig(206);
    z1 = (0, 50);
    z2 = (100, 100);
    z3 = (50, 0);

    draw z1..z2..z3;

    % On numérote les points de 1 à 3
    dotlabels.top(range 1 thru 3); 
endfig;

Pour explorer les différents chemins possibles visiter aussi Metafont guide pratique de Bernard Desgraupes pages 34, 35

cycle

Un exemple Metapost classique: comment contraindre le chemin d'une courbe à l'aide de direction.

Alt text

beginfig(207);
    z1 = (0,0);
    z2 = (100,0);

    draw z1..z2..cycle; 
    draw z1{up}..z2..cycle withcolor red;

    dotlabels.top(range 1 thru 2);
endfig;

scale D de Radim https://radimpesko.com/fonts/boymans

Alt text

beginfig(208);
    z1 = (1u, 1u);
    z2 = (1u, 6u);
    z3 = (2u, 6u);
    x4 = (3u);
    y4 = .5[y1,y2];
    z5 = (2u, 1u);
    path D;
    D := z1--z2--z3{dir 0}..z4..{dir 180}z5--cycle;
    draw D;
    draw D scaled 1.2 shifted (-0.4u, -0.5u);
        dotlabels.top(range 1 thru 5);
endfig;

Random

Alt text

beginfig(209);
endfig;

stocker

miroiter

Alt text

beginfig(301);
endfig;

dévier

Alt text

beginfig(302);
endfig;

Définir un chemin et un sous-chemin

Ici le tracé du C est basé sur celui d'un O qu'il ne reprend que partiellement.

Alt text

beginfig(303);
    z1=(3u, 5u);
    z2=(1u, 2.5u);
    z3=(3u, 0u);
    z4=(5u, 2.5u);

    path p;
    p := z1..z2..z3..z4..cycle;

    draw subpath(-0.5, 2.5) of p withpen penrazor scaled 9 withcolor blue;
    draw p dashed evenly;

    % pour plus de détails sur les pointillés voir *Métapost raconté aux piétons* page 22

    dotlabels.top(range 1 thru 4);
endfig;

image functions

Alt text

beginfig(304);
endfig;

repeat

Alt text

beginfig(305);
endfig;

Points relatifs et déduction de points

Trouver un point situé entre deux autres points

Alt text

beginfig(401);
    z1 = (0u,0u);
    z2 = (0u,5u);
    z3 = .5[z1,z2];  % z3 est le point à mi-distance de z1 et z2;

    draw z1..{left}z3..z2;

    dotlabels.top(range 1 thru 3);
endfig;

Variable de largeur

définir une variable qui va étendre (extanded) de la lettre, modifier les proportions

Alt text

beginfig(402);
endfig;

Whatever: trouver un point appartenant à une droite

Alt text

beginfig(403);
    chasse := 7u;
    hauteur := 5u;
    transversale := 2u;

    x1 = 0;
    x3 = chasse;
    x2 = .5[x1,x3];

    y1 = y3 = 0;
    y2 = hauteur;
    y4 = y5 = transversale;

    z4 = whatever[z1,z2];
    z5 = whatever[z2,z3];

    pickup pencircle scaled 5;

    draw z1 -- z2 -- z3;
    draw z4 -- z5;
endfig;

Points d'intersection

Alt text

beginfig(404);
        path p, pp;

        p := (0,100) -- (50,0) -- (100,100);
        pp := p shifted (25, 0);

        pair i;        
        i = p intersectionpoint pp;

        pickup pencircle scaled 20;

        draw point 0 of p -- point 1 of p -- i -- point 1 of pp -- point 2 of pp;
endfig;

Alt text

beginfig(12);
    z1 = (0,0);
    z2 = (100,100);

    % plutot que de dessiner directement le chemin, on l'enregistre dans une variable p

    path p;
    p := z1..z2..cycle; % boucle; loop, to close the path %% TODO: faire un exemple ave le cycle

    drawarrow p;


    % trouve les points qui sont au milieu d'un tracé

    % trouver un point appartenant à un cheminhttp://cahiers.gutenberg.eu.org/legal.html

    % décomposer cet exemple avec trois points irréguliers juste une ligne

    % *-X-*--------X--------*

    z3 = point .5 of p;
    z4 = point 1.5 of p;

    drawarrow z1--z2--z3--z4--cycle;

    dotlabels.top(range 1 thru 4);
endfig;

Alt text

beginfig(15);
    z1 = (0,0);
    z2 = (0,200);
    z3 = .25[z1,z2];
    z4 = (100,0);

    path p;
    p := z2{right}..{left}z3;
    draw p;

    path pp;
    pp := z4--z2;

    z5 = p intersectionpoint pp; % Trouver le point à l'intersection de deux chemins

    draw z1--z2;
    draw z5 -- z4;

    draw (-10, -10);



    dotlabels.top(range 1 thru 5);
endfig;

Alt text

beginfig(16);
    pickup pencircle scaled 1bp;
    path p [];
    z0 = (100,100);
    z1 - z0 = 3cm * right; % Determiner un point (ici z1) par une longeur et une direction, relativement à un autre point (ici z0)
    z2 - z0 = 2.7cm * dir(40);
    p0 = z0--z1--z2--cycle;
    p1 = .5[z0,z1]--z2;
    p2 = .5[z1,z2]--z0;
    p3 = .5[z2,z0]--z1;
    draw p1 withcolor blue ;
    draw p2 withcolor blue ;
    draw p3 withcolor blue ;
    draw p1 intersectionpoint p2 withcolor red withpen pencircle scaled 3bp;
    draw p0;

        dotlabels.top(range 0 thru 2);

endfig;

Full random using uniformdeviate

Alt text

beginfig(17);
    z6=(0,0);
    z7=(0,100);
    z8=(0,200);

    for i=0 upto 1000:
        path chimen;
        chimen := z6{dir uniformdeviate 360}..{dir uniformdeviate 360}z7..{dir uniformdeviate 360}z8;

        draw chimen scaled uniformdeviate 0.10 rotated uniformdeviate 360 shifted (uniformdeviate 100, uniformdeviate 100);
    endfor


    % dotlabels.lft(6,7,8);
endfig;

Alt text

beginfig(19);
    pen monstylo; monstylo = makepen((0,0)..(1,1)..(2,0));
    draw (0,0)--(100,0) withpen monstylo scaled 5;
endfig;

intéressant pour le whatever et subpath mais illustrer par un exemple plus simple

Alt text

beginfig(20);
    numeric pensize, width, height;
    pensize := 5;
    width := 70;
    height := 100;

    pickup pencircle scaled pensize;

    % V
    y1 = y3 := height;
    y2 = 0;
    x1 := 0;
    x2 = .5[x1, x3];
    x3 = width;

    draw z1--z2--z3;

    % barre sous le V
    z4 = origin;
    z5 = (width, 0);

    draw z4--z5;

    % barre au milieu
    z7 = whatever[z1, z2];
    z8 = whatever[z2, z3]; % faire une exemple plus simple, mais whatever dis qu'un point quelque part sur un chemin, meiux illustré avec la lettre A
    y7 = y8 = (height / 2);

    dotlabels.top(1, 2, 3, 4);

    path p;
    p := z7--z8;

    draw subpath(.3, .7) of p; % Bien illustré avec la lettre C

    picture dessin ;
    dessin := currentpicture;
    currentpicture := nullpicture;

    % etoile
    z9 = origin;
    z10 = origin + (10, 0);

    for i=0 step 45 until 360:
        draw z9--z10 rotated i;
    endfor;

    picture etoile ;
    etoile := currentpicture;
    currentpicture := nullpicture;

    draw dessin shifted (200, 0);
    draw etoile shifted (100, 0);
endfig;

ne pas dessiner directement mais enregistrer dans des variables des morceaux de dessin Illustrer avec typo modulaire?

Alt text

beginfig(21);
    picture wheel; % declarer une variable de type picture

    wheel := image(
        draw fullcircle scaled 2 xscaled .8 rotated 30;
        draw fullcircle scaled .15 xscaled .8 rotated 30;
    );

    draw wheel scaled 90;

endfig;

end;