# JOG: Jhack's own graphics

##
Jogging is good for your figures !

Ce logiciel est un prologue Postscript qui permet de composer des graphiques de façon simple et automatisable. Il suppose une connaissance élémentaire de la syntaxe Postscript. L'utilisateur dispose de deux systèmes de coordonnées, le premier est le système Postscript par défaut en points ( 1/72e de pouces ) origine en bas à gauche de la page (dénommé coordonnées objets). Une option permet d'utiliser des coordonnées métriques en mm. Le second système de coordonnées est celui qui est défini par les limites du rectangle de tracé ; on parlera de coordonnées utilisateur (ou sujet). Pour définir le second système de coordonnées il faut donner les valeurs des coordonnées sujets correspondant aux limites objets de la fenêtre de tracé (rectangulaire ou triangulaire suivant les cas).

Un petit nombre de commandes permet de reporter des symboles, lignes, polygones et textes en utilisant l'un ou l'autre des 2 systèmes de coordonnées. Le logiciel permet de plus d'insérer des valeurs explicitement ou à partir de commandes arbitraires ( programmes ou commandes externes ). On peut donc réaliser des opérations à l'aide du language Postscript ou de programmes quelconques. Les quelques exemples suivants peuvent servir de modèles pour réaliser des graphes simples sans connaissance approfondies du language Postscript.

On présente une série d'exemples qui donnent les principales fonctions du logiciel. Il faut copier les exemples dans un fichier texte et utiliser la commande g ou ge <le nom du fichier avec/ou sans le suffixe .jog> pour voir la figure avec ghostview et obtenir le fichier Postscript de même nom avec suffixe .ps ou .eps suivant la commande utilisée ( g ou ge ).

En résumé, si la source est `toto.jog` La commande shell `g toto` fabrique le fichier `toto.ps` qui peut être imprimé ne varietur. La visioneuse Postscript montrera la page A4 complète. La commande `ge toto` fabrique le fichier Postscript encapsulé `toto.eps`, qui est une image utilisable dans un document bureautique ou autre et qui est limité à la zone utile du dessin avec une petite marge blanche de 10 points. Ces commandes `g` et `ge` sont des scripts simples de quelques lignes modifiables si besoin.

## Le programme minimum

Des options par défaut limitent au maximum les informations à fournir. La première ligne de l'exemple suivant défini les bornes de la fenêtre rectangulaire dans le système de coordonnées de l'utilisateur et trace cette fenêtre. Les deux instructions suivantes trace les valeur numériques et graduations.

0.png | ./fig/0.jog
    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY

L'exemle suivant ajoute des points à ce graphe. Les coordonnées utilisateur des points sont données à la commande Plot dans un vecteur. Le symbole par défaut (cercle vide) est utilisé.

1.png | ./fig/1.jog
    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY
    [
       10 -0.3
       20  0.15
       30  0.25
       40  0.40
       60  0.65
       80  0.73
    ] Plot

Il est possible de communiquer les coordonnées de point sous la forme de deux vecteurs X et Y comme il est illustré dans l'exemple suivant dans le dernier paragraph où les mêmes points sont reportés avec des croix rouges et des lignes.

2.png | ./fig/2.jog
    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY
    [
       10 -0.3
       20  0.15
       30  0.25
       40  0.40
       60  0.65
       80  0.73
    ] Plot

    [ 10 20 30 40 60 80 ]
    [ -0.3 0.15 0.25  0.40 0.65 0.73 ]
    WithLines Red Cross

Une des caractéristique de ce logiciel est qu'il utilise l'interpréteur Postscript et donc on peut comme illustré ci-dessous nommer des vecteurs pour les utiliser plus loin. Dans une première étape on défini les vecteurs a et b, puis on peut les utiliser en argument des instructions de report de points. On a aussi illustré différents attributs qui permettent de controller le style des graphiques: symboles vides ou pleins, avec ou sans lignes, couleurs nommées...

En fait toute la puissance du language peut être utilisée pour paramétrer les graphiques.

3.png | ./fig/3.jog
    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY
    /a [ 10 20 30 40 60 80 ] def
    /b [ -0.3 0.15 0.25  0.40 0.65 0.73 ] def
    a b Black Circles
    a [ 1.2 0.95 0.6 0.3 -0.1 -0.3 ]
    WithLines Green Filled Diamonds

Quelques points nouveaux:

- les lignes commençant par ? sont des instructions de mise au point qui vérifient la pile et donne le numéro de ligne dans la sortie standard de l'interpréteur postscript.
- Un 3eme mode de communication des coordonnées est illustré (cercles violets). Pour des points d'abscisse régulièrement espacés on donne 3 arguments: abscisse du premier point, décalage d'abscisse de point en point et enfin un vecteur des valeurs d'ordonnées correspondantes.
- Une instruction Label permet de faire des légendes pour les différents styles graphiques.
- Enfin l'instruction GradX permet de définir les titres. Le type de l'argument vecteur ou scalaire permet de réaliser l'opération pertinente ( titre ou graduation ). On peut donc changer le style entre graduation et titre ( couleur taille de caractères etc... ). de chaînes à valeur numérique
- La commande s2o transforme des coordonnées utilisateur en coordonnées papier. Elle est utilisée pour placer les légendes relativement à la fenêtre du graphique. La commande Label travaille en coordonnées papier.

4.png | ./fig/4.jog
    (Times-Roman) 15 Font
    [70 570 70 570][ 0 100 0 100 ] Axe2
    [(25)(50)(75)] GradX
    [(25)(50)(75)] GradY
    25 Font
    (Axe X) GradX
    (Axe Y) GradY
    ?
    0 10 [ 0 10 20 30 40 50 60 ] Violet Filled Circles
    ?
    [0 10 20 30 40 50 60]
    [60 50 40 30 20  10 0 ]
    Blue Cross
    ?
    [
    0 5   10 15   20 25   30 35
    40 45
    50 55
    60 65
    ] WithLines Red Filled Squares
    ?
    Black 15 Font
    10 90 s2o  % paper location to start writing labels
    (NoLines Violet Filled Circles) ( What it is ) Label
    (WithLines Red Filled Squares) ( Another one ) Label
    (NoLines Blue Cross) (and the last one) Label
    ?

## Jogging with style

On peut structurer la présentation d'un fichier jog en paragraphes définissant la présentation, les données, et les instructions de report de points assez facilement comme illustré ci-dessous.

On peut aussi réaliser facilement des calculs élémentaires sur les éléments d'un vecteur: changement d'échelle, translation etc. en utilisant les opérateurs Postscript:

    /Y3 [ Y2 { 1.2 mul } forall ] def

Les éléments du vecteur `Y3` sont ceux de `Y2` multipliés par 1.2.

5.png | ./fig/5.jog
    (Times-Roman) 15 Font
    0.35 mm Pen
    [70 570 70 570][ 0 100 0 100 ] Axe2
    [(25)(50)(75)] GradX
    [(25)(50)(75)] GradY
    25 Font
    (Axe X) GradX
    (Axe Y) GradY
    % Here we define the data vectors to plot
    /X [ 5 15 30 45 50 70 80 ] def
    /Y1 [60 50 40 30 20  10 0 ] def
    /Y2 [ 30 35 40 43 25 22 12 ] def
    % we can do some simple calculation on data
    /Y3 [ Y2 { 1.2 mul } forall ] def
    /XY [ 30 35 60 65 80 85 ] def
    % then use them in plot function call
    0 10 Y1 NoLines Violet Filled Circles
    X Y1 NoLines Orange Filled Squares
    X Y2 NoLines Red Cross
    X Y3 WithLines Blue Empty Diamonds
    gsave XY Red 1 Dash Lines grestore % local dash
    % write some labels for the various plots
    Black 15 Font
    10 90 s2o  % paper location to start writing labels
    % s2o convert from user coordinate to paper coordinats
    % these 2 numbers are used by the first Label call
    % subsequent calls just skip to the next line
    (NoLines Violet Filled Circles) ( 0 10 Y1 ) Label
    (NoLines Orange Filled Squares) ( X Y1 ) Label
    (NoLines Red Cross) ( X Y2 ) Label
    (WithLines Blue Empty Diamonds) ( X Y3 ) Label
    gsave
    (Red 1 Dash Lines) ( XY ) Label
    grestore
    % some more drawing on the graph in user coord
    0.1 mm Pen
    [ 0 20 100 20 ] Black Lines

## Clochettes et sifflets

- Gestion des couleurs: `n Color` modifie la couleur courante. `n` peut être un nombre entier dont la valeur modulo 20 désigne une des couleurs illustrées ci-dessous. `n` peut aussi être un nombre réel entre 0.0 et 1.0 dans ce cas la nuance (Hue) peut être choisie de façon continue. Ceci complète les quelques couleurs nommées déja utilisées ( Red, Blue, Violet... ). On peut bien sur utiliser les instructions du language Postscript (setrgbcolor par xemple) pour réaliser d'autres couleurs.
- La commande Titles fait un peu double emploi avec GradX et GradY pour mettre des légendes sur les axes; Trois prototypes sont reconnus:

      (Axe X) (Axe Y) Titles
      (Titre principal) Titles
      (Axe X) (Axe Y)(Titre principal)Titles

- Caractères grecs, indices exposants: les caractères ` ^ _ modifient le caractère qui suit immédiatement pour donner respectivement un caractère grec correspondant, un indice ou un exposant. Ce mécanisme très rustique est un compromis qui permet quelques enrichissements sans trop alourdir les codes Postscript. Il est bien sur hors de question de cloner LaTeX en Postscript en moins de 1000 lignes de code !
- L'instruction Size modifie la taille des symboles, Pen l'épaisseur de la ligne et Dash le style de la ligne ( tiretés... ). Les effets de ces instructions peuvent être limités à la zone encadrée par les instructions Postscript gsave grestore.
- L'instruction `Surface` dessine une surface fermée de la couleur courante

6.png | ./fig/6.jog
    ?
    [ 0 100 -0.6 1.6 ] Axe2
    [ (0) (25) (50) (75) (100) ] GradX
    [ (-0.50) (0) (0.50) (1.00) (1.50) ] GradY
    ?
    % axes titles can also be provided in GradX and GradY functions
    18 Font (Axe X) (Axe Y) Titles
    25 Font (Labels and colors) Titles
    18 Font Blue 2 Pen
    ?
    % Test for clipping within a given area default the plot window
    % this is not recommanded because export software may not handle clipping properly
    gsave
    ?
    Clip % by default Fobj Clip
    ?
    [ -20 0.9 40 0.2 120 -0.4 ] Lines
    grestore % returns to unclipped
    % clip is off after restore so circles are drawn across border line
    20 Size % change symbol size
    [0 0 50 0 100 0] Green Plot
    10 Size
    % Draw in reverse depth so background first...
    0.9 setgray
    [
      5 -0.15
     20 0.2
     35 0.45
     50 0.23
     60 -0.11
    ] Surface
    10 Size Red WithLines Diamonds
    ?
    [
     30 0.123
     50 0.456
     70 0.895
    ] Plot
    % the plot statement is the last one Order of other is unimportant
    % They can be placed even before the data vector
    [ 80 1.21 85 0.85 ] Violet 6 Size NoLines Filled Circles
    % or Lines : here same thing if called before symbol
    [ 85 1.0 95 0.90 ] Red WithLines Empty Squares
    ?
    15 Size NoLines Black % color for text of legends while symbols
    % will have their own color as given in first arg.
    /x 150 def /y 700 def % we need variables to
    % layout our table of symbols and labels
    ?
    x y
    ( 0 Color Filled Circles ) (Color 0) Label
    ( 1 Color Filled Circles ) (Color 1) Label
    ( 2 Color Filled Circles ) (Color 2) Label
    ( 3 Color Filled Circles ) (Color 3) Label
    ( 4 Color Filled Circles ) (Color 4) Label

    x 100 add y
    ( 5 Color Filled Circles ) (Color 5) Label
    ( 6 Color Filled Circles ) (Color 6) Label
    ( 7 Color Filled Circles ) (Color 7) Label
    ( 8 Color Filled Circles ) (Color 8) Label
    ( 9 Color Filled Circles ) (Color 9) Label

    x 200 add y
    ( 10 Color Filled Circles ) (Color 10) Label
    ( 11 Color Filled Circles ) (Color 11) Label
    ( 12 Color Filled Circles ) (Color 12) Label
    ( 13 Color Filled Circles ) (Color 13) Label
    ( 14 Color Filled Circles ) (Color 14) Label
    ?
    x 320 add y
    ( 15 Color Filled Circles ) ( Color 15 )  Label
    ( 16 Color Filled Circles ) ( Color 16 )  Label
    ( 17 Color Filled Circles ) ( Color 17 )  Label
    ( 18 Color Filled Circles ) ( Color 18 )  Label
    ( 19 Color Filled Circles ) ( Color 19 )  Label
    % example of strings with index/exponents and greek letters
    % Only on modifier for the next char ( NO greek index/exponent though ! )
    Black
    30 Font
    200 385 moveto (`m_1 `u_a `b `G) Show
    200 350 moveto (H_2O f_H_2 `DG_r) Show

## Données calculées

Une ligne commençant par ! est remplacée par la sortie de la commande shell qui suit le !. Cette méthode permet de faire des figures dynamiques, qui ne contiennent que la mise en page et dont les données sont calculées par un programme externe quelconque. L'exemple suivant montre comment dessiner des fonctions avec des shell script simples:

sinx.awk

    #! /bin/awk -f
    BEGIN {
    for ( x=0.02; x<30.0; x+=0.05 ) {
        printf("%10.3f %10.5f\n",x,sin(x)/x)
      }
    }

sinx2.awk

    #! /bin/awk -f
    BEGIN {
    for ( x=0.02; x<30; x+=0.05 ) {
        printf("%10.3f %10.5f\n",
            x,
            sin(x)/sqrt(x)+0.1)
      }
    }

J'ai choisi des exemples simples et courts avec awk mais on peut utiliser n'importe quel commande externe pour générer les couples x y ad hoc.

7.png | ./fig/7.jog
    (Times-RomanF) 25 Font
    0.5 mm Pen
    [ 50 550 50 800][ 0 30 -0.5 1 ] Axe2
    [ (0) (10) (20) (30) ] GradX
    [ (-0.4) (-0.2) (0) (0.2) (0.4) (0.6) (0.8) (1.0) ] GradY

    gsave   % save current color pen etc...
        0.15 mm Pen
    	[ Xmin 0 Xmax 0 ] Black 1 Dash Lines
    grestore % restore color pen dash...
    ?
    gsave
    [
    % LC_NUMERIC=C to make sure that "." is the decimal separator
    ! LC_NUMERIC=C ./sinx.awk
    ] Blue Lines
    grestore
    ?
    gsave
    [
    ! LC_NUMERIC=C ./sinx2.awk
    ] 1 Dash Red Lines
    grestore
    300 720
    % beware to escape ( in a postscript string
    ( Blue ) ( sin\(x\)/x ) Label
    ( Red 1 Dash Lines ) ( sin\(x\)/sqrt\(x\) )  Label
    ?

## Plusieurs figures

Cet exemple illustre la réalisation de plusieurs figures sur la même page et comment reporter des données dans l'une ou l'autre avec la fonction Win

Les positions des fenêtres sur la page peuvent être celles par défaut, ou communiquées ( voir exemples précédants ) par un vecteur donnant en coordonnées papier les bornes du rectangle : [ Gauche Droite Bas Haut ]. Ces informations peuvent aussi être fournies par des valeurs de variables /Bas /Gauche /Largeur et /Hauteur. Dans ce cas les variables /Droite et /Haut sont calculées par Axe2 et utilisables dans le graphique.

La fonction `Win` utilise un argument qui peut être une variable Postscript ( nom précédé de /) ou une valeur (un nom). Dans le premier cas les informations qui définissent la fenêtre courante de dessin ( calculée par Axe2 ) sont mémorisées, dans l'autre ces données sont modifiées à partir de celle de la variable

8.png | ./fig/8.jog
    % kludge to move and scale the fig on the page without
    % modification to the code
    % 0.7 0.7 scale
    % 130 320 translate
    (Times-Roman) 12 Font
    /Data [ 15 10 20 20 50 50 75 25 12 18 ] def
    /Largeur 250 def
    /Hauteur 250 def
    /Bas 60 def
    /Gauche 50 def
    /Xshift { Largeur 10 add } def
    /Yshift { Hauteur 10 add } def
    % same values for all windows
    [ 0 100 0 100 ] Axe2
    /gr [(20)(40)(60)(80)] def
    gr (Titre X_1) GradX
    gr (Y_1 axis title) GradY
    /W1 Win % save user window 1
    %
    /Gauche Gauche Xshift add def
    [ 0 100 0 100 ] Axe2
    (Titre X_2) gr GradX
    gr false GradY
    /W2 Win % save user window 2
    %
    /Gauche Gauche Xshift sub def % order
    /Bas Bas Yshift add def       % is
    [ 0 100 0 100 ] Axe2
    gr false GradX
    (Y_3 axis title) gr GradY
    /W3 Win % save user window 3
    %
    /Gauche Gauche Xshift add def
    [ 0 100 0 100 ] Axe2
    gr false GradX
    gr false GradY
    /W4 Win % save user window 4
    %
    W1 Win %=== recall W1 user window
    Data Filled Red Circles
    %
    W2 Win % now in the 2d window and so on...
    Data Empty Blue Circles
    ?
    W3 Win
    Data Filled Green Circles
    ?
    W4 Win
    Data Filled Black Squares
    ?
    W1 Win
    [-5 -10 120 110 ] 1 Dash 0.5 setgray Lines
    gsave
    Fobj Clip % Clip plot in current window
    [-5 -10 120 110 ] Red Lines
    grestore % revert to unclipped plot mode

## Diagramme triangulaire

9.png | ./fig/9.jog
    #include Axe3
    (Na_2O) (SiO_2) (K_2O) Axe3
    /Tbl [
      20.0  25.0
      35.0  15.0
      50.0  16.5
      60.0  5.33
    ] def
    % here I scale to 0..1 instead of 0..100
    [ Tbl { 100 div } forall ] Plot

La même chose avec plusieurs graphiques sur la même page.

a.png | ./fig/a.jog
    #include Axe3
    % TODO ? change Xa Ya -> Gauche Bas or Left Bottom
    % and Cote should be Largeur / Width...

    /Cote 70 mm def
    8 Font
    0.5 Pen
    2 Size

    /Xa 30 def
    /Ya 30 def
    (Na_2O) (SiO_2) (K_2O) Axe3
    /T1 Win

    /Ya Yc 30 add def
    (K_2O) (SiO_2) (K_2O) Axe3
    /T2 Win

    /Ya Yc 30 add def
    (Al_2O_3) (SiO_2) (FeO) Axe3
    /T3 Win

    /Xa Xb 50 add def
    /Ya 30 def
    (Na_2O) (SiO_2) (K_2O) Axe3
    /T4 Win

    /Ya Yc 30 add def
    (K_2O) (SiO_2) (K_2O) Axe3
    /T5 Win

    /Ya Yc 30 add def
    (Al_2O_3) (SiO_2) (FeO) Axe3
    /T6 Win

    % the data table
    /Tbl [
      20.0  25.0
      35.0  15.0
      50.0  16.5
      60.0  5.33
    ] def

    Filled % all symbols filled

    T1 Win
    [ Tbl { 100 div } forall ] Blue Circles

    T5 Win
    [ Tbl { 100 div } forall ] Red Squares

    T2 Win
    4 Size
    [ 0.3 0.2  0.154 0.233 ] Olive WithLines Squares