boundingbox, currentpicture and Co …

boundingbox

En TeX tout est affaire de boites. J'en ai parlé dans une très vieille fiche que tu trouvera ici.

MetaPost en-capsule le dessin dans une boîte (bounding box en anglais) et c'est les dimensions de cette boite qui sont utilisées par ConTeXt pour placer ton dessin dans la page. Cette boite est définie par son coin en bas à gauche et son point en haut à droite. Tu peux dessiner cette boite avec la macro MetaPost bbox.

\starttext
\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
draw p;
draw bbox p withcolor red;
\stopMPcode
\stoptext

Si tu regarde attentivement (ou en agrandissant) tu te rendras compte que bbox ajoute une petite marge autour du graphique (offset en imprimerie). Cette marge est stockée dans une variable interne de MetaPost apellée bboxmargin MetaFun possède la commande boundingbox qui supprime cette marge.

\starttext
\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
draw p;
draw boundingbox p withcolor red;
\stopMPcode
\stoptext


Attention la boundingbox ne prend pas en compte la taille du stylo :


\starttext
\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
draw p withpen pencircle scaled 1cm;
draw bbox p withcolor red;
\stopMPcode
\stoptext

Chaque chemin possède sa propre boite :

\starttext
\startMPcode
path p,q,r;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
q:=(1cm,1cm)--(5cm,2cm)--(4cm,5cm)--(2cm,3cm)--cycle;
r:=fullcircle scaled 2cm;
draw p;
draw q;
draw r;
draw bbox p withcolor red;
draw bbox q withcolor blue;
draw bbox r withcolor green;
\stopMPcode
\stoptext

currentpicture

L'ensemble des chemins est stocké dans currentpicture qui a sa boite :

\starttext
\startMPcode
path p,q,r;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
q:=(1cm,1cm)--(5cm,2cm)--(4cm,5cm)--(2cm,3cm)--cycle;
r:=fullcircle scaled 2cm;
draw p;
draw q;
draw r;
draw bbox p withcolor red;
draw bbox q withcolor blue;
draw bbox r withcolor green;
draw bbox currentpicture ;
\stopMPcode
\stoptext

On peut effacer le contenu de currentpicture avec currentpicture := nullpicture. En voici le principe en reprenant la figure ci-dessus :

\starttext
\startMPcode
path p,q,r;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
q:=(1cm,1cm)--(5cm,2cm)--(4cm,5cm)--(2cm,3cm)--cycle;
r:=fullcircle scaled 2cm;
draw p withcolor red;
draw q withcolor blue;
draw r withcolor green;
\stopMPcode
\stoptext

Si l'on place currentpicture := nullpicture juste avant de dessiner r

\starttext
\startMPcode
path p,q,r;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
q:=(1cm,1cm)--(5cm,2cm)--(4cm,5cm)--(2cm,3cm)--cycle;
r:=fullcircle scaled 2cm;
draw p withcolor red;
draw q withcolor blue;
currentpicture := nullpicture ;
draw r withcolor green;
\stopMPcode
\stoptext

Seul r est dessiné !

Si l'on a pris soin de stocker p et q dans une variable (appelée ici dessin) on peut les dessiner :

\starttext
\startMPcode
path p,q,r;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
q:=(1cm,1cm)--(5cm,2cm)--(4cm,5cm)--(2cm,3cm)--cycle;
r:=fullcircle scaled 2cm;
draw p withcolor red;
draw q withcolor blue;
picture dessin;
dessin:=currentpicture;
currentpicture := nullpicture ;
draw r withcolor green;
draw dessin shifted (5cm,0);
\stopMPcode
\stoptext

origin

Il n'y a qu'une seule origin car origin désigne le point de coordonnées (0,0)

\starttext
\startMPcode
path p,q,r;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
q:=(1cm,1cm)--(5cm,2cm)--(4cm,5cm)--(2cm,3cm)--cycle;
r:=fullcircle scaled 2cm;
draw p;
draw q;
draw r;
draw bbox p withcolor red;
draw bbox q withcolor blue;
draw bbox r withcolor green;
draw bbox currentpicture ;
draw origin withpen pencircle scaled 2mm withcolor red;
\stopMPcode
\stoptext

Comme tu peux le constater origin n'est pas forcement le point en bas à gauche car tu peux employer des coordonnées négative comme (-1cm,-3.2cm) ou (0,-3cm) et même si tu n'en emploies pas des macros comme fullcircle ou fullsquare qui dessinent respectivement un cercle ou un carré centré sur le point (0,0) ont une partie de leur chemin avec des coordonnées négatives.

les quatre coins de la boite

MetaPost possède également des commandes qui permettent de dessiner les 4 coins et le centre de la boite

Il faut bien entendu préciser le chemin auxquels ils se rapportent par exemple si le chemin (path) est p :
llcorner p, urcorner p

Tu peux dessiner la boite d'un chemin (path) avec
draw llcorner p -- lrcorner p-- urcorner p -- ulcorner p -- cycle
Tu obtiens la boite sans marge comme avec la commande boundingbox

Tu peux dessiner les points :

\starttext
\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
draw p ;
draw bbox p withcolor red;
draw llcorner p withcolor blue withpen pencircle scaled 5mm;
draw center p withcolor blue withpen pencircle scaled 5mm;
draw lrcorner p withcolor blue withpen pencircle scaled 5mm;
draw urcorner p withcolor blue withpen pencircle scaled 5mm;
draw ulcorner p withcolor blue withpen pencircle scaled 5mm;
\stopMPcode
\stoptext

Placement des dessin dans ConTeXt

Maintenant on va voir comment jouer avec ces différents éléments pour faciliter le dessin. Mais auparavant on va examiner comment ConTeXt place les dessins MetaPost. ConTeXt place le coin en bas à gauche sur la ligne de base à la suite du texte. Je t'ai déjà dit que j'avais fait il y a un petit bout de temps une fiche sur les boites et la ligne de base, la relire peut être utile.

\starttext
Un texte avant le dessin sans saut de ligne.
\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
draw p scaled .5;
draw bbox currentpicture withcolor red;
\stopMPcode
Un texte après sans saut de ligne pour voir comment fonctionne la boundingbox.
\stoptext

La même chose avec des sauts de lignes :

\starttext
Un texte avant le dessin avec un saut de ligne.

\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
draw p scaled .5;
draw bbox currentpicture withcolor red;
\stopMPcode

Un texte après avec un saut de ligne pour voir comment fonctionne la boundingbox.
\stoptext

Modifier la taille de la boundingbox

On peut jouer sur la taille de la boundingbox avec la commande setbounds currentpicture to

\starttext
\startMPcode
path p;
p:= fullcircle scaled 2cm;
fill p withcolor .6green;
setbounds currentpicture to unitsquare scaled 1cm;
draw bbox currentpicture ;
\stopMPcode

\stoptext

setbounds p to ne marche pas, il faut obligatoirement employer setbounds currentpicture to

Un autre exemple avec une boite rectangulaire :

\starttext
\startMPcode
path p;
p:= fullcircle scaled 2cm;
fill p withcolor .6green;
setbounds currentpicture to unitsquare xscaled 1cm yscaled 3cm;
draw bbox currentpicture ;
\stopMPcode

\stoptext

La boite est forcement un rectangle et ne peut pas être un cercle :

\starttext
\startMPcode
path p;
p:= fullcircle scaled 2cm;
fill p withcolor .6green;
setbounds currentpicture to unitcircle scaled 1.5cm;
draw bbox currentpicture ;
\stopMPcode

\stoptext

On peut déplacer la boite en utilisant des échelles négatives :

\starttext
\startMPcode
path p;
p:= fullcircle scaled 2cm;
fill p withcolor .6green;
setbounds currentpicture to unitsquare xscaled 1cm yscaled -1cm;
draw bbox currentpicture ;
\stopMPcode

\stoptext

\starttext
\startMPcode
path p;
p:= fullcircle scaled 2cm;
fill p withcolor .6green;
setbounds currentpicture to unitsquare xscaled -1cm yscaled -1cm;
draw bbox currentpicture ;
\stopMPcode

\stoptext

\starttext
\startMPcode
path p;
p:= fullcircle scaled 2cm;
fill p withcolor .6green;
setbounds currentpicture to unitsquare xscaled -1cm yscaled 1cm;
draw bbox currentpicture ;
\stopMPcode

\stoptext

La même chose avec du texte pour voir le comportement de la nouvelle boite :

\starttext
\startMPcode
Un texte avant le dessin sans saut de ligne.
path p;
p:= fullcircle scaled 2cm;
fill p withcolor .6green;
setbounds currentpicture to unitsquare scaled 1cm;
draw bbox currentpicture ;
\stopMPcode

Un texte après sans saut de ligne pour voir comment fonctionne la boundingbox.
\stoptext

Le texte placé avant est recouvert par le dessin !

\starttext
\startMPcode
Un texte avant le dessin sans saut de ligne.
path p;
p:= fullcircle scaled 2cm;
draw p withcolor .6green;
setbounds currentpicture to unitsquare scaled 1cm;
draw bbox currentpicture ;
\stopMPcode

Un texte après sans saut de ligne pour voir comment fonctionne la boundingbox.
\stoptext

Tu peux utiliser shifted pour placer la boite à l'endroit souhaité. slanted n'a pas d'utilité et rotated ne marche pas.

\starttext
\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
fill p withcolor .625yellow ;
setbounds currentpicture to unitsquare xscaled 2cm yscaled 3cm shifted (2cm,1.2cm);
draw bbox currentpicture ;
\stopMPcode
\stoptext

Tu peux augmenter la taille de la boundingbox

\starttext
\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
fill p withcolor .625yellow ;
setbounds currentpicture to unitsquare scaled 6cm;
draw bbox currentpicture ;
\stopMPcode
\stoptext

La commande setbounds currentpicture n'est pas très pratique d'utilisation car pour l'utiliser il faut connaître la talle de ton dessin et faire attention s'il déborde ou pas.

MetaFun possède une commande beaucoup plus facile et efficace : enlarged qui élargi laboundingbox :

\starttext
\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
fill p withcolor .625yellow ;
setbounds currentpicture to unitsquare scaled 6cm;
draw bbox currentpicture ;
\stopMPcode
\stoptext

Afficher qu'une partie du dessin

On peut afficher qu'une partie du graphique avec la commande clip currentpicture to. Le fonctionnement est le même que setbounds currentpicture to. Si on reprend le dessin ci-dessus avec clip au lieu de setbounds :

\starttext
\startMPcode
path p;
p:= (0,0) .. (3cm,2cm) -- (3cm,4cm) -- (0,4cm)..cycle;
fill p withcolor .625yellow ;
clip currentpicture to unitsquare xscaled 2cm yscaled 3cm shifted (2cm,1.2cm);
\stopMPcode
\stoptext

Jouer avec currentpicture

Je reprend ici l'exemple du manuel de MetaFun. Le jeu consiste à créer une croix :

\starttext
\startMPcode
draw (0cm,0cm)--(1cm,1cm) ;
draw (1cm,0cm)--(0cm,1cm) ;
\stopMPcode
\stoptext

On va multiplier les croix :

\starttext
\startMPcode
draw (0cm,0cm)--(1cm,1cm) ;
draw (1cm,0cm)--(0cm,1cm) ;
picture croix ;
croix := currentpicture ;
draw croix shifted (3cm,0cm) ;
draw croix shifted (6cm,0cm) ;
\stopMPcode
\stoptext

Et encore :

\starttext
\startMPcode
draw (0cm,0cm)--(1cm,1cm) ;
draw (1cm,0cm)--(0cm,1cm) ;
picture croix ;
croix := currentpicture ;
draw croix shifted (3cm,0cm) ;
draw croix shifted (6cm,0cm) ;
croix := currentpicture ;
draw croix shifted (0cm,2cm) ;
\stopMPcode
\stoptext