6 Extensions de Thérion
Thérion est un outil très puissant et flexible qui permet de créer et gérer des topographies de grottes. Il est également ouvert à des extensions pour s’adapter à des besoins particuliers. C’est l’avantage de l’Open Source et d’un design modulaire du code.
Ce chapitre décrit comment modifier therion
- personnaliser
therion
(andxtherion
) a votre langue (français, …); - ajouter des morceaux de code MetaPost et/ou TeX;
- définition des fonts de caractères;
- créer de nouveaux symboles.
6.1 La langue
Thérion est distribué avec une documentation en anglais (en), tchèque (cz), slovaque (sk), et d’autres langues de contributeurs : français (fr), espagnol (sp), polonais (po) et italien (it).
Ajouter une nouvelle langue est très simple car la traduction des textes est contenue dans le sous répertoire thlang de thérion, et il y a un script perl, process.pl, pour générer le fichier de langue a partir de la liste des lignes venant de différentes langues supportées.
Le script cna est également utilise pour créer un fichier vide pour une langue donnée, et inclure dans ce fichier de localisation le contenu nécessaire issu d’un fichier texte remplis via un éditeur de texte.
Comme il s’agit d’un script PERL, vous avez besoin d’un interpréteur perl pour installer votre fichier dans le system. Ceci ne pause pas de problème pour toutes les distributions Linux et MacOS X. Si vous ne l’avez pas (c'est-à-dire si vous avez Windows) vous pouvez downloader PERL sur le site CPAN ((comprehensive PERL archive network), ainsi que les modules additionnels de perl que vous pourriez avoir besoin. L’adresse est http://www.cpan.org.
La dernière chose que vous devez faire est configurer la langue dans le fichier de configuration de xtherion
.
6.1.1 Traduction du programme
Comme exemple, nous allons décrire la traduction en italien (it), ainsi vous vous aurez des topo et atlas avec des légendes en italien, et l’interface de xtherion
sera également en italien.
Allez dans le répertoire therion/thlang et exécutez la commande
perl process.pl export it
.
Pour d’autres langues, utilisez le code respectif, ex : “de” pour l’allemand, et ainsi de suite. Cela générera le fichier texts_it.txt qui contiennent les lignes avec les commandes utilisées par therion
suivit par les lignes débutant par “it:” et ne contenant rien d’autre.
Vous devez ouvrir ce fichier avec un éditeur de texte et écrire les mots (ou phrases) dans la langue (dans notre exemple l’italien), sur les lignes débutant avec “it:”, cad, le code de la langue. Ce sont ces phrases que “therion” écrira quand il générera la topo. Chaque mot ou phrase doit être placé sur une unique ligne. Les libelles sur ou descriptions sur plusieurs lignes ne sont pas supportes. Il n’est pas non plus possible d’utiliser des caractères de continuations de ligne (comme l’antislash) car les scripts perl ne les reconnaissent pas.
Quand vous avez termine avec l’édition du fichier, lancez la commande
perl process.pl update
Cela incluera le contenu du fichier texts_it.txt dans le fichier global texts.txt, et supprimera le fichier texts_it.txt.
En cas d’erreurs, ce script vous les indiquera. Par exemple, si vous oubliez d’insérer le mot ou la phrase sur une ligne et que vous ne laissez que l’entête “it:” il vous le dira et en indiquant la ligne ou il manque la traduction. Apres correction, rééditez le fichier texts_it.txt, comme vous l’avez fait précédemment. Il contiendra tous les textes que vous avez déjà saisi, et vous n’aurez qu’a rajouter la traduction manquante. Puis répétez la commande “update”.
Quand tout est en ordre, lancez le script sans arguments
perl process.pl
Cela génère le fichier source dans le répertoire de therion
:
... updating definitions from ../thsymbolset.cxx ... done updating definitions from ../thexpmap.cxx ... done updating definitions from ../thlocale.cxx ... done updating definitions from ../thmapstat.cxx ... done updating definitions from ../thpdf.cxx ... done
Placez vous dans le répertoire de “therion”, recompilez le et réinstallez le. Maintenant therion
est prêt à générer des topos de grottes avec des légendes en italien.
6.1.2 Configuration
La dernière étape est de spécifier le langage par défaut dans le fichier de configuration de therion
. Au niveau global (du serveur) le fichier est “/etc/therion.ini” (sur Linux et MacOS X). Au niveau local (de la topo), le fichier est “.therion/therion.ini” (sous Linux) dans votre répertoire home. Ouvrez l’un des deux fichiers avec un éditeur de texte et recherchez la chaine “language”. Elle est commentée (il y a un '#' en début de ligne). Faites une copie de la ligne, retirer le commentaire (‘#’) et replacez le “en_UK” avec “it” (le code langue, “fr” pour le français).
Vous pouvez également spécifier la langue avec l’option de layout intitulée “language”. Par exemple “language fr”.
Maintenant essayez de générer des topo avec la légende en différentes langues.
6.1.3 xtherion
xtherion
peut également être traduit comme therion
. Allez dans le répertoire “xtherion/lang”, et répétez la procédure avec le script “process.pl”: exportez le fichier “texts_XX.txt” (remplacez “XX” avec votre code langue), éditez le fichier et écrivez les lignes traduites correspondant a votre langue. Mettez a jour le fichier “texts.txt”. Enfin, exécutez le script sans arguments.
Vous n’avez pas finit. Vous devez ajouter le texte qui sera affiche avec le menu d’aide “Help | Controls”. Allez dans le répertoire de “xtherion” et éditez le fichier “msgusr.tcl”: vous devez ajouter un objet pour le texte affiche (a nouveau, remplacez le “XX” avec votre code langue):
::msgcat::mcset XX "xtherion_help_control" [encoding convertfrom utf-8 { -- write the text here -- }]
Allez dans le répertoire de therion
et lancez la commande “make install” (pour linux).
xtherion
a son fichier n’initialisation, “/etc/xtherion.ini”. Ouvrez-le avec un éditeur de texte et recherchez la chaine “mclocale”. Elle est généralement commentée (la ligne débute par un '#') et avec le code langue “sk”. Faites une copie de la ligne. Supprimez le commentaire de la ligne dupliquée et remplacez le “sk” avec votre code langue (“fr”).
6.1.4 Autres extensions
Therion peut gérer d’autres extensions de présentation de données, de façon modulaire, comme pour la traduction. Les extensions possibles sont :
- encodage
- TeX encodage
- macros pour TeX et MetaPost
Les détails sont fournis dans la doc the Therion book [thbook 62].
6.2 La commande "code"
La commande code
vous permet d’agir sur la façon dont therion
calcul vos données. Elle peut être utilisée avec les arguments suivants
- “metapost”, pour définir code pour MetaPost;
- “tex-map”, pour définir code pour TeX, lors de la génération de cartes;
- “tex-atlas”, pour définir code pour TeX, lors de la génération atlas.
Le contexte de la commande est passé au programme spécifié par la commande.
Vous devriez lire le fichier “thmpost.cxx” des sources de Thérion.
symbols
6.2.1 Remplacer un symbole
Le code suivant indique a therion
d’insérer la commande spécifiée dans le fichier de données de MetaPost. En particulier, cette commande remplace le symbole “p_gradient” avec le symbole UIS pour l’entrée de grotte : pas très utile soit dit en passant):
code metapost let p_gradient = p_entrance_UIS; endcode
lines
6.2.2 Largeur des lignes
Vous pouvez changer l’épaisseur des lignes dans le dessin en redéfinissant l’unité (qui est appelée “u” dans Thérion):
code metapost u:=50pt; endcode
Nous avons vus que therion
a cinq crayons prédéfinis : “PenA” (épais), “PenB”, “PenC”, “PenD”, and “PenE” (fin). Vous ne pouvez redéfinir qu’un seul des crayons utilises par therion
:
code metapost def PenA = pencircle scaled (0.001); enddef; endcode
Vous pouvez redéfinir un symbole. Vous pouvez commencer par le code metapost de Thérion (fichier avec les extensions “.mp” dans le répertoire “mpost”). Par exemple [réponse de S. Mudrak 20060621],
def l_floorstep (expr P) = T:=identity; pickup PenD; % crayon fin len := arclength P; % arclength of the path ds := adjust_step(len, 0.25u); % compute step between ticks for s=0 step ds until len: t := arctime s of P; % path time coordinate mark_ ( P, t, 0.2u ); % draw a tick at "point t of P" endfor; pickup PenC; % crayon normal thdraw P; % draw P enddef; endcode
La fonction “mark_()” peut être définit comme suit :
code metapost def mark_( expr P, t, s ) = pair q[]; q1 := point t of P; % point P[t] q2 := direction t ot P rotated 90; % tangent to P at P[t] rotated 90 deg thdraw q1 -- q2; enddef endcode
centerline (.th command)
6.2.3 Couleur des visées topo (Centerline)
Le code suivant modifie la couleur des visées topo, et utilise une ligne continue au lieu des petites croix aux stations [thexample 2]:
code metapost def l_survey_cave (expr p) = draw p withpen PenD withcolor (1.0, 0.0, 0.0); enddef; endcode
6.3 Fontes de caractères
Cette section provient du wiki [thwiki 12]: elle contient la procédure pour remplacer la taille des fontes de caractères. Il est prévu dans le futur que chacun puisse redéfinir les fontes. Pour l’instant, il est possible d’ajouter des commandes MetaPost, qui redéfinit les font_setup
, dans le layout. Le code standard est le suivant:
code metapost def fonts_setup (expr t,s,m,l,h) = write "\def\updown#1#2{\vbox{" & "\offinterlineskip" & "\setbox100=\hbox{#1}" & "\setbox101=\hbox{#2}" & "\ifnum\wd100>\wd101\hsize=\wd100\else\hsize=\wd101\fi" & "\centerline{\box100}\vskip4pt" & "\centerline{\box101}}}" & "\def\thlabel{\thnormalsize}" & "\def\thremark{\thsmallsize\si}" & "\def\thaltitude{\thsmallsize}" & "\def\thstationname{\thsmallsize}" & "\def\thdate{\thsmallsize}" & "\def\thheight{\thsmallsize}" & "\def\thheightpos{\thsmallsize+\ignorespaces}" & "\def\thheightneg{\thsmallsize-\ignorespaces}" & "\def\thframed{\thsmallsize}" & "\def\thwallaltitude{\thtinysize}" to "mptexpre.tex"; write "\def\thtinysize{\size[" & decimal max(optical_zoom*t,0) & "]}" & "\def\thsmallsize{\size[" & decimal max(optical_zoom*s,0) & "]}" & "\def\thnormalsize{\size[" & decimal max(optical_zoom*m,0) & "]}" & "\def\thlargesize{\size[" & decimal max(optical_zoom*l,0) & "]}" & "\def\thhugesize{\size[" & decimal max(optical_zoom*h,0) & "]}" to "mptexpre.tex"; write EOF to "mptexpre.tex"; enddef; initialize(Scale); endcode
Pour changer la taille, vous avez également besoin d’inclure une commande indiquant la taille avant la ligne “write EOF”. Par exemple,
write "\def\thstationname{\size[4]}" to "mptexpre.tex";
label (point)
Dans les faits, la commande de l’objet “point” de type “label” est suivie par un argument indiquant la taille du texte. C’est pourquoi, pour changer la taille du libellé, vous devez retirer la taille par défaut et insérer la nouvelle taille, comme dans cet exemple :
code metapost def fonts_setup (expr t,s,m,l,h) = write "\def\thlabel#1{\size[32]}" to "mptexpre.tex"; write "\def\threport#1{\size[16]}" to "mptexpre.tex"; write EOF to "mptexpre.tex"; enddef; initialize(Scale); endcode
Ce code redéfinit également le point de type “report”, sinon MetaPost lèverait une erreur lorsqu’il l’utiliserait.
C’est pourquoi (en paraphrasant S. Mudrak):
Dans le futur, changer la taille et le style des fontes doit être plus simple et,
il devrait y avoir des exemples dans le Thérion Book. Enfin, le choix de la
couleur devrait être implémenté rapidement.
remark (point)
A ce jour, il n’y a pas d’option “fonts_setup” au “code metapost” qui permette de définir cinq tailles de fontes, de la plus petite (tiny : petit) à la plus large ( huge : tres large). Les points de type “label” utilisent une troisième taille ( medium : moyen); les points de type “remark” utilise la seconde taille ( small :petit). La définition de la commande “fonts_setup” est dans le fichier thmpost.cxx.
code metapost \fonts_setup( 12, 16, 32, 64, 96 ); endcode
6.4 Les Symboles
symbols
Un symbole est une fonction traçant un dessin. Pour définir un symbole, il suffit d’indiquer ce que la fonction doit faire. Pour tracer un symbole (par exemple quand vous dessinez une topo avec xtherion
) ajoutez le nom de cette fonction dans le fichier, celui avec l’extension “.th2”, lorsque le fichier sera calculé par therion
la fonction du symbole sera appelée.
Un nouveau symbole peut être inséré dans un layout avec la commande“code metapost”, ou il peut être compile dans le programme therion
.
Tout symbole a un nom composé de
- une lettre, 'p' (point), 'l' (ligne), 'a' (area : surface), ou 's' (spécial);
- un type;
- une sous-structure optionnelle;
- un id (identifiant) du symbole (en minuscule).
Le nouveau symbole doit être enregistre avec la commande “initsymbol( nom_symbole )”, sauf si il est compile dans therion
.
pen (MetaPost)
Le langage therion a quatre tailles de crayons différents par leur largeur de trait : “PenA” (épais), “PenB”, “PenC”, et “PenD” (fin). Il y a deux commandes pour dessiner des lignes: “thdraw” et “thfill”. La première dessine un trait. La seconde remplit également la surface entourée par le trait. N’utilisez pas les commandes MetaPost “draw” et “fill”.
points
6.4.1 Les Points
Les symboles points ont généralement quatre paramètres (exceptions: “section”, “label” et “station”):
- P, position
- R, rotation
- S, scaling (mise à l’échelle)
- A, alignement
Ces paramètres définissent la transformation appliquée au dessin du symbole quant il est ajoute à la carte. Le résultat de la fonction symbole (cad, le dessin du symbole) est transforme par
T = identity aligned A scaled S rotated R shifted P
Les Symboles sont dessines dans des coordonnes locales, dans lesquelles le dessin du symbole est références par l’origine (0,0), et l’unité de longueur est u.
Comme exemple, nous avons fait un symbole compose d’un carre, tourne de 45 degrés, avec un point d’exclamation dedans. La figure ci-dessous est le résultat.
code metapost def p_entrance_MY (expr P,R,S,A)= T:=identity aligned A rotated R scaled S shifted P; # attention, le '#' n'est peut etre pas le bon symbole pour debuter un commentaire. # le > de droite thfill (0,-u)--(u,0)--(0,u)--(0,.9u)--(.9u,0)--(0,-.9u)--cycle; # le < de gauche thfill (0,-u)--(-u,0)--(0,u)--(0,.9u)--(-.9u,0)--(0,-.9u)--cycle; # le rond du ! thfill (.1u,-.45u)..(0,-.35u)..(-.1u,-.45u)..(0,-.55u)..cycle; # la barre du ! thfill (0,-.2u)..(.1u,-.1u)--(.2u,.4u)..(0,.6u)..(-.2u,.4u)--(-.1u,-.1u)..cycle; enddef; initsymbol("p_entrance_MY"); let p_entrance = p_entrance_MY; endcode
lines
6.4.2 Lignes
Les symboles de type ligne ont un seul argument, le path (chemin) de la ligne, exprime en coordonnées absolues. C’est pourquoi la transformation T est toujours l’identité.
Par exemple [thbook 59],
def l_wall_bedrock_MY (expr P)= T:=identity; pickup PenB; thdraw P; enddef; initsymbol("l_wall_bedrock_MY");
area
6.4.3 Les Surfaces
Les symboles de surface, comme les symboles de ligne, n’ont qu’un seul argument, le path (chemin) de contour de la surface, définit en coordonnées absolues. Les surfaces sont des zones de dessin et peuvent être remplies de trois façons,
- en le remplissant d’un symbole (uniforme ou aléatoire) une grille dans la limite de la boite (bbox) du path, et en découpant les symboles du dessin sur la limite de la surface (le path) ;
- en colorant la région dans le path avec une couleur uniforme ;
- en remplissant la région dans le path avec un paterne prédéfinit.
Un paterne est définit en utilisant des commandes Metapost. Par exemple [thbook 59],
beginpattern(pattern_water_MY); draw origin--10up withpen pensquare scaled (0.02u); patternxstep( .18u ); patterntransform( identity rotated 45); endpattern; def a_water_MY (expr P)= T:=identity; thclean P; thfill P withpattern pattern_water_MY; enddef; initsymbol("a_water_MY");
Remarque : je vous conseil de vous reporter à la documentation Thérion pour les petites topo qui est très complète et vous livre plusieurs exemples de modification pour différents symboles (surfaces, lignes).
6.4.4 Exemples
Si vous dessinez un symbole en utilisant metapost, vous pouvez débuter avec un symbole existant et l’éditer. Vous avez besoin de vous rappeler quelques points :
- une ligne est une séquence de paires (x,y) séparée par “–” ou par “..”. Dans le premier cas, la ligne est droite, dans la seconde elle est arrondit.
- si la séquence se termine par le mot “cycle” la ligne est refermée (elle reboucle sur elle-même).
- la commande
thdraw
dessine une ligne; - la commande
thfill
remplie la région dans la ligne avec une couleur.
6.4.4.1 Exemple 1
Voici l’exemple d’un symbole.
code metapost def p_gradient_MY (expr P,R,S,A) = U:=(.15u, .4u); T:=identity aligned A rotated R scaled S shifted P; pickup PenC; #Left Hand side thdraw (-.3u, -.2u) -- (-.7u, .1u); thdraw (-.2u, -.1u) -- (-.4u, .6u); #Centerline thdraw (0u, 0u) -- (0u, .9u); #Right side thdraw (.3u, -.2u) -- (.7u, .1u); thdraw (.2u, -.1u) -- (.4u, .6u); enddef; initsymbol ("p_gradient_MY"); endcode
6.4.4.2 Exemple 2
Il est pratique de définir le code pour un symbole (et d’autres chose) dans un fichier de paramètres qui sera incluse dans le fichier de configuration, en utilisant la commande input
. C’est pourquoi le fichier de configuration ressemblera a
input layout.th source main.th export map -layout plan -output ABC.pdf export map -layout print -output ABC_Printable.pdf
Le fichier “layout.th” contient les commandes de layout et la définition des nouveaux symboles. Le code suivant est de Ph. Schuchardt. Notez que
- pour les lignes extérieur de la grotte, il utilise le “PenA”, le plus épais;
- le symbole “gradient” et redéfinit comme dans l’exemple précédent;
- pour les surfaces de sable “sand” la bordure de la zone est remplie de points repartis aléatoirement autour des nœuds d’une grille irrégulière ; le dessin est découpé (sur la région) avant d’être dessinée.
- Pour les “débris” un objet “picture” (image) est définit, il est composé par des petits carrés placés près du nœud d’une grille qui s’étend jusqu’aux limites de la boite (bbox) de chemin “p”. Les carrés sont inclinés d’un angle de valeur aléatoire. L’image est découpée dans la limite de la région “p” et dessinée.
- les nouveaux symboles sont initialisés à la fin;
- et les symboles par défaut sont remplacés par les nouveaux.
layout plan scale 1 200 #PDF DOCUMENTION code tex-map \cavename={nome della grotta} \comment{testo del commento} endcode code metapost def l_wall_bedrock_MY (expr P) = T:=identity; pickup PenA; thdraw P; enddef; def p_gradient_MY (expr P,R,S,A) = U:=(.15u, .4u); T:=identity aligned A rotated R scaled S shifted P; pickup PenC; # thdraw and thfill commands ... enddef; def a_sand_MY (expr p) = T:=identity; % thclean p; pickup PenC; path q; q = bbox p; picture tmp_pic; tmp_pic := image( for i = xpart llcorner q step .3u until xpart urcorner q: for j = ypart llcorner q step .3u until ypart urcorner q: draw origin shifted ((i,j) randomized 0.2u) withpen PenC; endfor; endfor; ); clip tmp_pic to p; draw tmp_pic; enddef; def a_debris_MY (expr p) = T:=identity; pickup PenC; path q, qq; q = bbox p; picture tmp_pic; tmp_pic := image( for i = xpart llcorner q step u until xpart urcorner q: for j = ypart llcorner q step u until ypart urcorner q: qq := punked( ( (-.2u,-.2u)--(.2u,-.2u)--(.2u,.2u)--(-.2u,.2u)--cycle ) randomized (u/2) ) rotated uniformdeviate(360) shifted ((i,j) randomized u); if xpart (p intersectiontimes qq) < 0: thclean qq; thdraw qq; fi; endfor; endfor; ); clip tmp_pic to p; draw tmp_pic; enddef; initsymbol ("a_sand_MY"); initsymbol ("a_debris_MY"); initsymbol ("p_gradient_MY"); initsymbol ("l_wall_bedrock_MY"); endcode symbol-assign area sand MY symbol-assign area debris MY symbol-assign line wall:bedrock MY symbol-assign point gradient MY endlayout
6.4.5 Les nouveaux symboles
Il n'est pas possible d'ajouter de nouveaux symboles dans Thérion pour un utilisateur (version 5.2 Avril 2009 de Thérion). Mais chaque utilisateur peut définir son nouveau symbole avec le langage Meta Post et envoyer le code aux développeurs pour qu'ils enrichissent la bibliothèque de Thérion lors de la prochaine version du logiciel.
Il est également possible de redéfinir un (ou plusieurs) symbole(s) existant(s) pour modifier son dessin. Pour cela il faut écrire le code MétaPost traçant le dessin et l'intégrer à votre topographie. Pour cela se référer aux exemples ci-dessus en suivant les explication de ce même chapitre, ainsi qu'à la documentation Thérion pour les petites topos.
6.5 Documenter (le source de) therion
Pour mieux comprendre therion, vous pouvez regarder le code source, éventuellement. Une façon de parcourir le code est d’ouvrir les fichiers avec un IDE (Environnement de Développement Intégrée), et d’utiliser les outils qu’il fournit. Vous avez besoin d’un environnement de développement pour cela.
Cette section décrit comment générer une documentation du code programme “therion”, que vous pouvez voir dans votre éditeur de texte. Il y a plusieurs programmes qui peuvent générer de la documentation en utilisant les commentaires écrits dans le programme, ainsi que la structure du langage. Même si les sources du programme manquent de commentaires, la documentation est suffisamment riche pour permettre une navigation simple et lire le code.
Therion
est écrit avec des commentaires prévus pour doxygen
. Ce programme peut être téléchargé sur http://www.doxygen.org. Vous devez d’abord créer un fichier de configuration doxygen.
Allez dans le répertoire de therion et tapez
doxygen -g doxy.cfg
Cette commande crée le fichier “doxy.cfg”. Vous devez l’éditer, insérer le nom du projet (“Therion”), le numéro de la version, et le répertoire de résultat pour doxygen (répertoire que vous devez créer). Vérifiez les différentes options : en particulier vous voulez peut être que doxygen intégrer le code (.h and .c/.cxx) dans la documentation, ainsi que les autres informations qui pourraient être utile.
Malheureusement, le code de therion
n’est pas complètement commenté. Actuellement il est mal commenté. C’est pourquoi vous pouvez dire à doxygen
de ne pas reporter les “warnings”.
Quand vous êtes prêt, tapez
doxygen doxy.cfg
Et après quelques secondes (ou dizaines de secondes), vous avez une documentation dans le répertoire de résultat que vous avez spécifiés. Ouvrez votre navigateur internet sur la page “index.html” de ce répertoire.
6.A MetaPost
Cette annexe décrit les principales commandes MetaPost 13 .
Les fichiers MetaPost sont des fichiers texte, comme pour therion ou survex, avec des commandes pour MetaPost
, comme pour therion les fichiers contiennent des commandes pour therion
et les fichiers survex contiennent des commandes pour survex
. Pour travaille avec metapost, il suffit d’écrire des fichiers texte (avec l’extension “.mp” par défaut) et les envoyer a mpost
. Les sorties ressemblent a des fichiers PostScript qui peuvent être visualises avec un viewer PostScript (par exemple, avec ghostscript
).
Toutes les commandes sont terminées par ';'. Le caractère '%' démarre un commentaire. Le commentaire continue jusqu'à la fin de la ligne.
Les commandes metapost
indiquent comment dessiner une figure, c’est pourquoi elles sont très liées au dessin. MetaPost a neuf types de données:
- numeric, valeur numérique;
- pair, paire (x,y) de coordonnées de point dans le plan pour le dessin;
- path, la ligne faisant le dessin;
- color, couleurs utilisées pour dessiner la figure;
- string, texte écrit dans la figure;
- picture, portion de la figure, cad, ce qui est dessine;
- pen, le crayon utilise pour dessin les lignes avant ; avant d’utiliser le crayon, vous devez le prendre (ex : pickup pensquare“);
- transform, transformation affine : elle peu être appliquée a un path, picture, string and pen pour le tourner, le mettre a l’échelle, etc.
- boolean, une variable qui peut être soit “true” (vrai) ou “false” (faut).
En MetaPost vous pouvez définir des tableaux, par exemple “path p[];” et ensuite faire référence a ses éléments comme “p0”, “p1” etc. Les indexes avec une partie décimale sont autorises: “p1.2”. Les éléments d’un tableau peuvent également être indexes avec subscript: “p.a”. Les tableaux multidimensionnels sont aussi supportes: “path p[]q[], rs[][];”. Un élément du premier peut être “p2q3”, celui du second “rs1 5”.
6.A.1 Boolean
Une variable booléenne peut être utilisée en paramètre d’une fonction pour déterminer son comportement. Par exemple
% warning est appelé avec filled=true, p doit être un cercle vardef draw_or_fill(expr p, filled) = if filled: fill p else: draw p fi enddef;
pen (MetaPost)
6.A.2 Pens (crayon)
MetaPost a quelques crayons prédéfinit: “pencircle”, “pensquare”, et “penrazor”. La variable “currentpen” fait référence au crayon en cours d’utilisation. La variable “defaultpen” est le crayon par défaut.
L’opérateur “makepen” prend en paramètre un chemin et fabrique un crayon, dont le contour sera la boucle convexe du chemin. L’opération inverse est “makepath” qui, avec un crayon, produit le chemin de contour du crayon. La composition des deux opérateurs est la boucle convexe du chemin.
color (MetaPost)
6.A.3 Colors (couleurs)
Une color (couleur) est composée des trois nombres (rouge, vert, et bleu) compris entre 0 et 1. Il y a aussi des couleurs prédéfinies qui peuvent être référencées par leur nom: “black” (noir), “white” (blanc), “red” (rouge), “green” (vert) et “blue” (bleu). La couleur grise peut être définit comme une fraction de blanc : “0.4 white”.
Pour avoir un composant d’une couleur, il y a des opérateurs “redpart” (partie rouge), “greenpart” (partie verte) et “bluepart” (partie bleu).
transform (MetaPost)
6.A.4 Transformations
Une transformation a six paramètres
X' = tx + txx X + txy Y Y' = ty + tyx X + tyy Y
Les transformations sont appliquées dans l’ordre de lecture, de la gauche vers la droite. Par exemple p rotated R shifted S; indique que le chemin “p” est d’abord d’une rotation “R” puis translatée de “S”. Les transformations peuvent être composées pour former de nouvelles (et complexes) transformations. Une transformation particulière est “identity” (l’identité). Une roto-translation peut être définie comme
transform T; T = identity rotated 60 shifted (2.0, 3.0);
Il y a quelques opérateurs qui définissent les transformations:
- “shifted (a,b)”: takes (x,y) in (x+a, y+b);
- “rotated t”: takes (x,y) in ( x cos(t) - y sin(t), x sin(t) + y cos(t) );
- “slanted a”: takes (x,y) in (x+ay, y);
- “scaled a”: takes (x,y) in (ax, ay);
- “xscaled a”: takes (x,y) in (ax, y);
- “yscaled a”: takes (x,y) in (x, ay);
- “zscaled (a,b)”: takes (x,y) in (ax - by, bx + ay);
- “reflectedabout (p,q)”: reflects about the p-q line;
- “rotatedaround (p,t)”: rotates by an angle “t” around the point “p”.
Si “T” est une transformation, “inverse T” est sa transformation inverse. Pour avoir les paramètres individuels d’une transformation il y a les opérateurs “xpart”, “xxpart”, “xypart”, etc. Enfin, il est possible de définir une transformation en indiquant comment elle fonctionne pour trois points, cad, avec un système linéaire de trois équations.
6.A.5 Nombres et points
Les points et les lignes doivent êtres définies avec des unités. Si les unités de mesure ne sont pas spécifiées MetaPost utilise le point typographique (1/72 inch). Nous pouvons utiliser le cm, mm, … ou une unité “u” qui peut être définie, comme therion
le fait, et tout peut être exprimée dans l’unité de “u”.
Un point est une paire de coordonnées (x,y). MetaPost a une convention pour faire référence a un point : la paire de coordonnées a un nom préfixe par “z”; les valeurs x et y on un nom préfixe respectivement, par “x” et “y”. Par exemple,
z1:=(1.2u, 0.5u);
Implique que “x1”vaut 1.2u et “y1” vaut 0.5u.
Les nombres et les points peuvent être définis par un système d’équations linéaires. Ceci est pratique pour des dessins géométriques faisant références à l’intersection de lignes. Par exemple
z0 = 1/3[z1,z2];
Définit le point Z0 = (2 Z1 + Z2)/3. Un autre exemple,
a + b = 3; a - b = 1;
Définit “a” et “b” via un système de deux équations linéaires (“a” vaut 2, “b” vaut 1).
Les opérateurs “xpart” et ypart” correspond aux valeurs x et y du point.
Un vecteur 2D est représenté par une paire. L’opérateur “unitvector” applique à une paire produit le vecteur unitaire dans la direction de la paire. Les opérateurs “lft”, “rt”, “top” et “bot” appliques a la paire renvoient respectivement les parties gauche, droite, haut et bas de la paire.
path (MetaPost)
6.A.6 Lines (lignes)
Il y a trois façons de définir une portion de trace entre deux points, “z1” and “z2”,
- un segment en ligne droite, en mettant deux tirets entre les points: z1 – z2
- par un courbe (équation cubique), en mettant deux points entre z1 et z2: z1 .. z2
- par une courbe, avec un point d’inflexion, en mettant trois points (dans la commande) : z1 … z2
De plus, le dernier point du chemin peut être définit avec le mot clé “cycle” qui indique de fermer le chemin (la boucle) en rebouclant sur le premier point. Par exemple, un carre incline a 45 degrés sera,
p := (-u,0) -- (0,u) -- (u,0) -- (0-u) -- cycle;
Différents opérateurs contrôles le rayon de courbure des lignes. On peut définir la “tension” dans un segment (éventuellement de façon asymétrique), la courbure sur le point finale, et la direction (la tangente) sur le point terminal. La meilleure solution est d’utiliser les points de contrôle. Chaque point d’une ligne peut avoir deux points de contrôle, un avant et un après. Thérion utilise cette méthode. La courbe entre Z1 et Z2 dépend des deux points Z1“ (a droite e Z1) et Z2' (a gauche de Z2) comme suit : > Z(t) = t 3> Z1 + 3 t 2> (1-t) Z1” + 3 t (1-t) 2> Z2' + (1-t) 3> Z2 Quand Z1“=Z1 et Z2'=Z2 cette équation devient le segment linéaire Z1-Z2.
Une fois que vous avez définit une ligne, vous pouvez la dessiner en utilisant un de ces opérateurs.
- “draw p” dessine la ligne “p” en utilisant le crayon courant;
- “fill p” colore la surface décrite par “p”;
- “filldraw p”, est la composition des deux opérations précédentes;
- “undraw p” dessine “p” en utilisant la couleur de fond, cad, il efface “p”;
- “unfill p” efface la surface définit par “p”.
- “unfilldraw p” efface la surface définit par “p” plus le tracé de “p”.
Chaque opération draw/fill couvre la surface du trace qui a été définit. Par exemple “undraw” est un effacement réel, comme s’il était dessine avec la couleur de fond du dessin. C’est pourquoi il est important d’écrire les opérations de dessin dans le bon ordre, pour éviter d’avoir une partie du dessin cachée derrière une autre.
La fonction “drawoptions” changes les options générales du dessin:
drawoptions(withcolor o.5[black, white]); % définit la couleur grise (pour le dessin) drawoptions(dashed evenly); drawoptions(with pen pensquare scaled 0.4); % choisit le crayon
Il est possible d’indiquer quel crayon utiliser, “withpen q”, et quelle couleur, “withcolor c”.
Pour dessiner des flèches, nous avons les fonctions “drawarrow” et “drawdblarrow”. La taille de la tête de la flèche est définie par las variables “ahlength” (longueur) et “ahangle” (angle au niveau de la tête de flèche).
Les lignes en pointillées sont dessinées en utilisant les options “dashed” suivies par le type de pointillée,
draw p type pointillé;
Le type de pointille est une image sans texte ni opération “fill”. Il y a deux types (modèles) prédéfinit, “evenly” et “withdots”. En tant qu’image, le modèle peut être transforme (par exemple “mis a l’échelle”). Enfin, la fonction “dashpattern” permet de définir un modèle en indiquant une liste de “on”/“off”.
La variable “linecap” détermine la fin des lignes. Par défaut, elle est “arrondie” mais elle peut être “carrée” ou “butt”. La variable “linejoin” determine comment dessiner les coins des lignes. Par défaut, ils sont “arrondis”, mais ils peuvent être “beveled” (un polygone) ou “mitered” (pointée).
Pour obtenir des informations sur la position d’une ligne, il y a les opérateurs “llcorner, “lrcorner”, etc. (pour les coordonnées des coins de la boite contenant la ligne) et “bbox” pour la zone couvrant la ligne (avec une toute petite marge supplémentaire, “bboxmargin”). Ces opérateurs peuvent être également appliques à picture et pen.
Un opérateur spécial est “buildcycle”. Applique a une série de paths (lignes) il définit une ligne fermée (une boucle) joignant les éléments des paths (lignes) délimités par les intersections du path (ligne) avec les points précédents et suivants. Le résultat dépend du nombre d’intersections du chemin. En gros, MetaPost essaie de trouver l’intersection qui maximise les longueurs de ces pièces ; même si l’algorithme est plus complexe, en cas de multiples intersections, le résultat peut être différent de celui attendu.
Les operateurs “precontrol” et “postcontrol” donne le point de contrôle d’un chemin. Par exemple, “precontrol 2 of p” donne le point de contrôle précédent le troisième point de la ligne (les indices commencent a 0).
Les fonctions de dessin sont implémentée via la fonction “addto” qui ajoute les éléments graphiques (image, lignes ou contours) au dessin.
6.A.7 Texte
Les fonctions suivantes créent des objets de type string ,cad, du texte:
- “label(s, p)” affiche une chaine, avec comme valeur (texte) “s” au point “p”;
- “dotlabel(s, p)“est similaire à la fonction précédente, mais dessine également un point rond en “p”;
- “thelabel(s, p)” crée le trait qui peut être utilise pour dessiner la chaine. Cette fonction est utilisée pour obtenir la zone d’affichage du texte et effacer le dessin (sous le texte) avant d’écrire la chaine de caractères afin que le texte soit plus lisible. Ces operateurs peuvent également avoir comme suffixe, la position du texte par rapport au point : “lft” (gauche), “rt” (droite), “llft” (en bas à gauche), “ulft” (en haut à gauche), “lrt”(bas à droite) et “urt” (en haut à droite). La distance entre le point et le texte est déterminée par la variable “labeloffset”.
Les variables “defaultfont” et “defaultscale” définissent la font du texte. Par exemple,
defaultfont := "Times-Roman"; defaultscale := 10 pt;
L’opérateur “fontsize” renvoie la taille de la fonte.
Si le texte a des commandes de formatage et doit être calcule par TeX, il doit être délimité par “btex” et “etex”. Cela est utile pour écrire des formules mathématiques dans le dessin. Le bloc “btex”/“etex” est une image; il peut être pivoté, etc. Pour inclure un bloc TeX au début du fichier, utilisez “verbatimtex” (termine par “etex”). Par exemple (font cyrillic)
verbatimtex \font\cyr=wncyr10 etex
6.A.8 Picture (image)
La variable “currentpicture” fait référence à l’image courante. Les images prédéfinies sont “fillcircle” (un cercle plein), et “halfcircle” (un demi-cercle vers le haut).
La fonction “clip” découpe une image dans un tracé (de courbe). Par exemple : “clip picture to path;”.
6.A.9 Operations
L’opérateur d’affectation ”:=” affecte la valeur de l’expression à droite dans la variable située à gauche de l’operateur. Par exemple “bboxmargin:=5” fixe la marge de la bounding-box (zone d’affichage) à 5 points. Le signe égal ”=” définie une équation et peut être utilisé pour définir la valeur d’une variable.
MetaPost peut faire des opérations arithmétiques (additions, multiplication, etc. même des exponentielles), des opérations logiques (“and” (et), “or” (ou), des fonctions mathématiques (“sqrt”, “abs”, etc.). En particulier, pour les points ayant un produit scalaire “dotprod”, et pour les nombres nous avons la somme et la différence pytagorienne, “a++b” = (a 2 + b 2) 1/2, “a+-+b” = (a 2 - b 2) 1/2. “angle p” est l’inverse de la tangente (arctan) de la paire (x,y) de “p”.
Les chaines de caractère ont l’opération de concaténation, “s1 & s2”, et l’extraction de sous-chaines, “substring (a,b) of s”. L’opérateur “decimal” applique à un nombre sa représentation sous forme de chaine.
MetaPost utilise les coordonnées curvilinéaires pour décrire les courbes mathématiquement. Celles-ci varies de 0 à N, le nombre de points de la ligne, et sont répétées de façon cycliques si la ligne est fermée (boucle). MetaPost a plusieurs opérations sur les path:
- * “p1 intersection p2” donne le point d’intersection de “p1” et “p2”;
- * “p1 intersectiontimes p2” donne la paire de coordonnées curvilinéaire sur deux paths, qui correspond au point d’intersection (des deux courbes);
- * “point t of p” est le point de coordonnées “t” sur le path “p”;
- * “length p” est la longueur du path “p” (coordonnées curvilinéaires);
- * “subpath(t1,t2) of p” est la portion de “p” entre deux coordonnées;
- * “p1 cutbefore p2” est la portion de “p1” après l’intersection avec “p2”;
- * “p1 cutafter p2” est la portion de “p1” avant l’intersection avec “p2”;
- * “direction t of p” est le vecteur tangent à “p” au point de coordonnées “t”;
- * “directiontime v of p” est la coordonnées de “p” ou la tangente est “v”;
- * “directionpoint v of p” est le point de “p” ou la tangente est “v”;
- * “arclength p” est la longueur d’arc de “p”;
- * “arctime a of p” est les coordonnées de “p” au point ou la longueur d’arc vaut “a”.
Les règles de précédence et la composition des opérateurs sont importants pour comprendre certaines erreurs MetaPost
. MetaPost
possède six catégories d’objets. Elles sont en gros,
- - atom: nombres, variables, expressions entre parenthèses, blocs begingroup/endgroup, blocs btex/etex
- - primary: un atome, le résultat d’une opération unaire appliqué a un primary, le résultat de l’interpolation (crochets), le résultat d’un opérateur avec “of”, les variables “str” et “z” avec un suffixe.
- - secondary: un primary, où le résultat d’un opérateur binaire de primary appliqué sur un secondary et un primary;
- - terziary: un secondary, où le résultat d’un opérateur binaire de secondary appliqué sur un terziary et un secondary ;
- - subexpression: un terziary, ou le résultat de jonction de chemins (“–”, “..”,etc.)
- - expression: une subexpression, ou le résultat d’un opérateur binaire de terziary appliqué sur une expression et un terziary.
Les opérateurs sont subdivisés en catégories:
- - nullari: par exemple, “true”, “false”, “whatever”;
- - unari: avec un argument, comme la fonction mathématique;
- - type operators: qui définit une variable comme le type donnée;
- - binary: avec deux arguments:
- - * primary: *, /, **, and, dotprod, div, mod, infont ;
- - * secondary: +, -, ++, +-+ , et l’opérateur d’intersection;
- - * terziary: &, = , et l’opérateur de cut et comparaison;
- - “of” opérateurs qui a un argument précédé par “of”.
6.A.10 Structures de Contrôle
MetaPost
dispose des principales structures de contrôle des langages de programmation : boucles “for”, et la condition “if”. Elles peuvent être mixées dans la définition d’un path.
La syntaxe d’une boucle “for” est
for i=0 step S until N: ... endfor
Il y a aussi “for i=0 upto N: …” ou “upto” est équivalent a “step 1 until”.
Autres boucles:
- * avec une liste de valeurs: “for i=v1, v2, v3: …”
- * sur le suffixe (liste séparée par une virgule) “forsuffixes $=1, 2, 3: … ”
- * boucle infinie, “forever: …”; pour stopper la boucle infinie, utilisez “exitif” ou “exitunless”. Vous pouvez également utiliser ces fonctions d’arrêt dans d’autres boucles.
Exemples
% define a path using a for-cycle path q; q = for i=0 upto 5: z[i] -- endfor z[6]; draw q withcolor red;
% invoke fun2() on all the args of fun() def fun( text t ) = forsuffixes $=t: fun2($) endfor enddef;
% define a function that returns a path vardef p(text t) = k := 0; forsuffixes $=t: if ($ > k): z[$] -- else: z[$] fi hide( k:=k+1 ) exitif( $ < k ); endfor enddef; draw p(8, 6, 4, 2, 0);
La syntaxe de la commande “if” est
if condition: ... else: ... fi
Il y a également le “elseif:” qui permet de réduire la série des “if”s.
6.A.11 Les Macros
On peut définir de nouvelles fonctions (appelées “macro”). Elles sont importantes pour écrire du code MetaPost destinée à étendre les fonctions de therion. La syntaxe est
Les paramètres d’une macro son généralement des “expr” (expressions). Ils peuvent également être des “suffix” (variables), ou “text” (chaines de caractères). Pour invoquer une macro en lui passant le nom de la variable, il est préférable de déclarer le paramètre comme “suffix”.
La valeur de retour de la macro est le résultat de la dernière commande avant “endgroup”.
Les commandes “begingroup” et “endgroup” définissent un environnement local. De même “beginfig” et “endfig” definissent un environnement local. La commande “save” suivit par le nom d’une ou plusieurs variables, indique a MetaPost de stocker le contenu des variables, et de les remplacer (leur valeur) par celles stockées a la fin du “endgroup”. La commande “interim” affecte a une variable une valeur temporaire et restore le contenu de la variable a la fin du “endgroup”.
Une autre solution pour définir une macro est la commande “vardef”. Cela ressemble beaucoup a une fonction: un bloc “begingroup”/“endgroup” est automatiquement inséré. De plus le nom de la “vardef” peut avoir des suffixes; par exemple, “vardef a[]b (expr p) = …”. Deux variables spéciales sont prédéfinies: “@” est la dernière partie du nom de la “vardef”, “#@” est tout ce qui vient avant la “vardef”.
6.A.12 Un exemple
Vous pouvez trouver facilement des exemples de code metapost sur le web. L’exemple suivant est le dessin du signe “danger” (un point d’exclamation dans un losange).
beginfig(1); s = 20.0; % scale z0 = (200, 200); % offset z1 = z0 + (0,-1)*s; % corners z2 = z0 + (1,0)*s; z3 = z0 + (0,1)*s; z4 = z0 + (-1,0)*s; z5 = 0.2 [ z1, z3 ]; z6 = 0.3 [ z1, z3 ]; z7 = 0.7 [ z1, z3 ]; z8 = 0.8 [ z1, z3 ]; z9 = z7 + (z8-z7) rotated 90; z10 = z7 - (z8-z7) rotated 90; pickup pencircle scaled (s/10); draw z1 -- z2 -- z3 -- z4 -- cycle; pickup pencircle scaled (s/8); draw z5; fill z6 -- z9 .. z8 .. z10 -- cycle; endfig; end
Ce code est plutôt simple. En fait, vous n’avez pas besoin de toutes les commandes sophistiquées de MetaPost pour personnaliser votre dessin therion. Le résultat du code ci-dessus est présenté dans le dessin ci-dessous.
6.A.13 Fichier PostScript
La commande “shipout” génère le fichier PostScript. Il prend en argument une image. Le fichier PostScript a comme extension “.N” ou N est le nombre spécifié dans la commande “beginfig”. La commande “endfig” invoque “shipout currentpicture;”.
A la fin du fichier metapost, vous devez ajouter la commande “end;” qui indique a l’interpréteur mpost
de quitter.
Quand le fichier metapost est prêt, lancez
mpost file.mp
Vous avez une liste de fichiers, “file.1”, “file.2”, …, un pour chaque figure.. Ceux-ci sont presque des fichiers PostScript. Si vous voulez les visualiser (avec ghostview) ou les convertir en pdf (avec ps2pdf) vous aurez peut-être quelques erreurs car quelques éléments sont manquants. En particulier, la définition des fonts et celle de la commande “fshow”. Ouvrez le fichier de la figure avec un éditeur de texte et ajoutez les définitions manquantes au début du fichier,
/cmr10 /CMR10 def /fshow {exch findfont exch scalefont setfont show}bind def
Ceci n’est pas suffisant. La figure sera centrée dans le coin inferieur de la page, et vous n’en verrez qu’une partie. Pour la déplacer au centre de la page, ajoutez la commande PostScript (trouvez les bonnes valeurs pour l’offset x-y)
200 200 translate