~ / RICM4 / IHM / tps / 0-command-line /

TP 0 - Programme en ligne de commande

© 2007—2013 - Renaud Blanch

Le but de ce TP est de se familiariser avec des notions qui seront utiles pour la suite :

Python

Si vous souhaitez travailler sur votre machine personnelle, vous pouvez télécharger une distribution de Python adaptée à votre système. Le but de ce TP n'est pas d'apprendre Python, néanmoins, si cela vous intéresse, vous pouvez consulter cette introduction à Python 2 ou mon cours sur Python 3.

Ligne de commande

Récupérez le programme trace.py. Rendez-le exécutable et testez-le.

mandelbrot:~> chmod a+x trace.py
mandelbrot:~> ./trace.py
Traceback (most recent call last):
  File "./trace.py", line 48, in 
    sys.exit(main())
  File "./trace.py", line 33, in main
    assert len(argv) == 1	
AssertionError
mandelbrot:~> ./trace.py "sin(x)"
x, sin(x)
0.0, 0.0
0.1, 0.0998334166468
0.2, 0.198669330795
0.3, 0.295520206661
0.4, 0.389418342309
0.5, 0.479425538604
0.6, 0.564642473395
0.7, 0.644217687238
0.8, 0.7173560909
0.9, 0.783326909627
1.0, 0.841470984808

En quoi consistent les distances sémantiques à l'exécution et à l'interprétation pour ce programme ?

Réduisez la distance sémantique à l'exécution en gérant mieux les erreurs, et en fournissant un message indiquant comment utiliser le programme.

Enrichissez le programme en permettant le passage d'autres paramètres par la ligne de commande (xmin, xmax, etc.)

Langage graphique 2D

Les interfaces graphiques utilisent un modèle graphique permettant de dessiner à l'écran. En dehors d'usages particuliers, ce modèle est à deux dimensions (2D) et utilise une géométrie affine. Pour nous familiariser avec ce type de modèle, nous allons utiliser le langage PostScript.

S'il est utilisé principalement pour décrire des documents imprimés, PostScript a aussi été utilisé pour l'interface graphique des machines NeXT. La société NeXT Software a été rachetée en 1996 par Apple pour mettre au point Mac OS X (qui de manière similaire utilise PDF, très proche de PostScript, pour son interface graphique).

Premiers pas

Le langage PostScript peut s'expérimenter interactivement grâce à l'interpréteur Ghostscript qui s'invoque par la commande gs tapée dans une console, la page dans laquelle on va dessiner s'affichant alors à l'écran.

mandelbrot:~> gs
GPL Ghostscript 8.54 (2006-05-17)
Copyright (C) 2006 artofcode LLC, Benicia, CA.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
GS>help
Enter PostScript commands.  '(filename) run' runs a file, 'quit' exits.
GS>version ==
(3010)
GS>% ceci est un commentaire et ça ne fait rien
GS>

Le symbole % démarre un commentaire : le reste de la ligne est ignoré de l'interpréteur.

PostScript est un langage à pile, c'est à dire que quand il rencontre une valeur —un nombre ou une chaîne de caractère (délimitée par des parenthèses)—, il l'empile en mémoire. La valeur au sommet de la pile est la dernière empilée et la plus accessible.

GS>(zero) % empile la chaîne "zero"
GS<1>

L'invite (GS<1>) a changée, le nombre qu'elle contient indique le nombre d'éléments sur la pile. Certains opérateurs (nommés par des chaînes de caractères) permettent de manipuler la pile.

GS<1>1 % empile 1
GS<2>pstack % affiche le contenu de la pile
1
(zero)

GS<2>dup % duplique le sommet
GS<3>pstack
1
1
(zero)

GS<3>pop % enlève le sommet de la pile (et le perd)
GS<2>pstack
1
(zero)

GS<2>2 (trois) pstack % 2 empilements et 1 affichage enchaînés
(trois)
2
1
(zero)

GS<4>clear % vide la pile (noter l'invite à la ligne suivante)
GS>

Certains opérateurs permettent de faire les calculs usuels. Ils vont chercher leurs arguments sur la pile et les remplacent par le résultat du calcul. Il s'agit d'une notation post-fixée (les arguments d'abord, puis les opérateurs) qui ne nécessite donc pas de parenthèses. Cette notation est aussi connue sous le nom de notation polonaise inverse, prisée des possesseur de calculatrices Hewlett-Packard.

GS>1 2 add % empile 1 puis 2 puis les utilise pour une addition et empile le résultat
GS<1>pstack % qui est confirmé par l'examen de la pile
3
GS<1>4 5 add mul % (4+5)*3, le 3 étant récupéré sur la pile
GS<1>== % dépile et affiche la valeur dépilée
27
GS>

Les opérateurs permettant les calculs sont : add, mul, div, sub, neg.

Pour dessiner, on définit des chemins reliant des points spécifiés dans un repère ayant initialement son origine en bas à gauche, et dont l'unité est le point, soit 1/72ème de pouce (environ 2.835 point pour 1 mm). Une fois un chemin défini, on peut le tracer ou le remplir.

GS>newpath
GS>100 100 moveto % aller en x=100, y=100
GS>200 150 lineto % relier ce point à x=200, y=150
GS>100 200 lineto % relier à ce nouveau point
GS>stroke         % trace

Le résultat s'affiche alors :

GS>newpath
GS>150 50 moveto
GS>150 0 rlineto  % mouvement relatif
GS>0 50 rlineto   % idem
GS>-100 0 rlineto % idem
GS>closepath      % retour au 1er point
GS>.5 setgray
GS>fill           % remplit

On peut écrire du texte :

GS>/Times-Roman findfont % trouve une police et l'empile
GS<1>20 scalefont        % la passe en taille 20 point
GS<1>setfont             % la choisit pour le texte à venir
GS>newpath      % du texte, c'est aussi un chemin
GS>10 10 moveto % dont il faut placer l'origine,
GS>(Hello) show % choisir le contenu, et l'afficher

On peut définir donner un nom à des morceaux de code pour les réutiliser plus tard.

GS>/cm {
    28.3464567 mul
} def             % définit cm comme "28.3464567 mul"
GS>2 cm ==        % calcule 2*28.3464567 (le nombre de points dans 2 centimètres)
56.6929131
GS>/repere {
    /Arial findfont
    .5 cm scalefont
    setfont
    newpath
    0 0 moveto
    1 cm 0 lineto
    (x) show
    0 0 moveto
    0 1 cm lineto
    (y) show
    stroke    
} def
GS>repere % trace un repère à l'origine

On peut remarquer que dans le cas de la définition de cm, il manque un opérande à mul. Celui-ci sera donc pris sur la pile, et nous avons en fait ainsi défini une nouvelle fonction qui convertit les centimètres en points.

On peut modifier le repère par des translations, des rotations et des homothéties.

GS>repere
GS>5 cm 2 cm translate
GS>repere
GS>45 rotate
GS>2 2 scale
GS>repere
GS>0 2 cm translate
GS>repere

On peut faire des boucles :

GS>0 2 10 {  % de 0 à 10 inclus, par pas de 2, la valeur est empilée,
    ==       % le code est exécuté (ici, dépiler et afficher)
} for        % c'est parti !
0
2
4
6
8
10
GS>

Enfin, on peut mettre les commandes dans un fichier texte avec une extension .ps, et en ajoutant au début une ligne avec %! et à la fin showpage, et ça donne un fichier qui peut s'ouvrir dans la plupart des logiciels permettant d'afficher des fichiers graphiques. Par exemple, repere.ps :

%!
/cm { 28.3464567 mul } def
/repere {
    /Arial findfont
    .5 cm scalefont
    setfont
    newpath
    0 0 moveto
    1 cm 0 lineto
    (x) show
    0 0 moveto
    0 1 cm lineto
    (y) show
    stroke    
} def

repere
5 cm 2 cm translate
repere
45 rotate
2 2 scale
repere
0 2 cm translate
repere

showpage

Plus loin

Pour aller plus loin, vous pourrez consulter ce tutorial (pdf en anglais), cette référence (pdf en anglais) ou encore ce guide (html en anglais).

Questions

Réduisez la distance sémantique d'évaluation de notre programme initial en le faisant produire un graphe de la fonction en PostScript plutôt qu'un tableau de données.

Ajoutez un cadre et des axes au graphe pour obtenir un résultat de ce type :

Question bonus

Écrire un programme PostScript qui affiche la fractale de von Koch.

mise à jour : 4 mars 2013