27 janvier 2013 Association Philotechnique, Paris Cours de programmation Bertrand Roehner PAW: PRESENTATION EN FRANCAIS *** TABLE DES MATIERES *** Prologue * Caracteristiques de PAW * Mise en route de PAW * Macro de demonstration montrant une animation * Explication d'une macro simple Puis la section 1 decrypte et explique quelques exemples de representation graphique resumes dans la macro ANIM#GRAPHIQUE1 La section 2 propose un modele pratique d'organisation de vos macros PAW. La section 3 explique comment realiser une animation. La section 4 donnent les regles pour appeler une macro de l'interieur d'une macro. La section 5 decrypte la macro ANIM#COULEUR La section 6 decrypte la macro ANIM#FILM La section 7 passe en revue quelques messages d'erreur La section 8 explique comment numeriser un motif de dessin La section 9 explique comment repeter un motif pour obtenir une ``mise en scene'' relativement realiste La section 10 explique comment obtenir des effets ``3d'' par diverses representations en perspective. La section 11 explique comment obtenir un effet de perspective avec point de fuite en plantant des arbres le long d'un canal La section 12 donne des indications sur la transformation des fichiers postscrpt produits par PAW en fichiers jpg La section 13 decrit la realisation d'un film montrant un groupe de cavaliers arrivant vers l'observateur Dans la section 14 on realise une animation montrant le passage d'une troupe de cavaliers sur le pont qui mene a Beaulieu. ********************* PROLOGUE PAW est un langage de programmation developpe au CERN entre 1986 et 2004. Le manuel de l'utilisateur ``PAW, an introductory tutorial, CERN Program Library, Long Writeup Q121'' comporte pres de 500 pages. Comme il est en anglais, nous proposons ici une presentation en francais de quelques commandes choisies. La selection est orientee vers ce qui est l'objectif de ce cours, a savoir la realisation d'un dessin anime historique. On dit que la langue des Eskimos comporte de tres nombreux mots et qualificatifs specialises pour decrire les differentes qualites de neige (poudreuse, soufflee, tolee, etc.). On a quelque chose d'analogue avec PAW en ce sens qu'une grande partie de ce logiciel est destinee a l'analyse des donnees generees par les accelerateurs du CERN. Ainsi, il y a de tres nombreuses commandes relatives au stockage de donnees et a la creation d'histogrammes. Cependant, a cote de ces fonctions specialisees, PAW a aussi des fonctionnalites plus generales pour le calcul numerique et la representation graphique. Les notes qui suivent presentent une partie de ces fonctions. MISE EN ROUTE: Le logiciel est contenu dans un paquet de fichiers ``paw.zip'' qui fait 2.9M. Sur Linux, le paquet s'ouvre par ``unzip paw.zip''. Sur Windows 7 vous trouverez sans mal la procedure adequate par Google. Vous lancez PAW en cliquant sur le fichier pawNT.exe. Cela ouvre une fenetre de commande. Sur cette fenetre vous trouverez la question: ``Workstation type (?=HELP) =1 :'' qui est relative au type de votre ordinateur. Repondez en tapant sur la touche ``Enter'' Incidemment, l'abbreviation CR signifie ``Carriage return'' une expression qui peut se traduire par. ``Retour chariot''. Cette expression tire son origine de l'epoque ou les ordinateurs fontionnaient avec des cartes perforees dont les trous etaient faits par des machines perforatrices. Par la touche CR, la carte une fois perforee etait ejectee et remplacee par une carte neuve; d'ou l'expression ``Retour chariot''. La touche ``Enter'' est souvent aussi appelee touche ``Return'', un mot qui a donc la meme origine. La reponse ``Enter'' ouvre une fenetre graphique. Pour vous assurer que tout marche correctement vous pouvez taper la commande suivante dans la fenetre de commande: NULL 0 10 0 20 Normalement cette commande cree un repere (x,y) avec des axes pour lesquels x va de 0 a 10 et y de 0 a 20. Cet exemple vous montre qu'on peut travailler en mode dit interactif c'est-a-dire en tapant les instructions les unes a la suite des autres. Cependant ce mode est relativement inefficace car il amene a retaper souvent les memes instructions. Dans la suite nous utiliserons le mode ``macro'' dans lequel on soumet d'un bloc tout un ensemble d'instructions contenues dans un fichier qu'on appelle une macro. Un peu plus bas vous trouverez un exemple simple de macro constitue par ANIM#RONDS. Par la suite pour pouvoir travailler correctement il faut que vous ayez sur votre ecran 3 elements: * la zone de commande dans laquelle vous allez par ex. entrer EXEC ANIM * la fenetre graphique dans laquelle va s'afficher le dessin * le fichier anim.kumac, par exemple sous la forme d'une icone en bas de votre ecran. Chaque modification du dessin necessite une modification de la macro. Il vous faudra donc ouvrir ce fichier tres souvent. Autrement dit, il est important de pouvoir y acceder rapidement juste par un clic. MACROS Toutes les macros qui sont expliquees dans ce qui suit se trouvent dans le fichier ``anim.kumac'' que vous trouverez dans un fichier accompagnant celui-ci. Recopiez ce fichier dans le meme repertoire que celui ou se trouvent deja les autres fichiers PAW sur votre ordinateur. MACRO DE DEMONSTRATION Pour presenter un logiciel ou un langage il est d'usage de faire executer une macro de demonstration. Pour cela tapez l'ordre suivant dans la fenetre de commande. EXEC ANIM#FILMDEMO Cet ordre signifie: executez la macro FILMDEMO contenue dans la macro-tiroir (voir ci-dessous la definition d'une macro-tiroir) ANIM. Comme son nom l'indique, cette macro cree un film qui dure environ 50s. De meme qu'un film de cinema ou de video, ce film est constitue d'une succession d'images fixes qui se succedent. Comme il y a en tout 1000 images cela signifie qu'entre deux images successives on a un intervalle de temps de 50/1000=50ms. Pour les film video il y a en general 25 images par seconde ce qui represente un intervalle de 1000/25=40ms, donc sensiblement la meme vitesse que notre film. Nous utiliserons le meme procede pour le film d'animation qui est l'objectif final de ce cours. Si le film doit durer 10mn, cela implique qu'il faudra accumuler 10x60x25=15,000 images. Le decryptage de la macro ANIM#FILMDEMO est donnee plus loin. UNE MACRO SIMPLE Apres la ``demo'' il est d'usage de donner un exemple simple permettant de voir comment fonctionne une macro. Pour cela activez la ligne EXEC ANIM#RONDS et desactivez toutes les autres lignes comportant EXEC. Puis dans la fenetre de commande tapez: EXEC ANIM Vous verrez apparaitre un rond rouge et un rond vert. Il se peut que sur la fenetre graphique de votre ecran ces ronds ne soient pas bien jolis. Cependant si vous pouvez visualiser le fichier paw.ps qui a ete cree par ANIM vous verrez qu'il s'agit vraiment d'un beau rond rouge rappelant la drapeau national du Japon. Pour vous faire une idee plus detaillee de la facon dont se deroule cette macro, rajoutez (ou activez) la ligne suivante ou debut de cette macro: TRACE ON WAIT et a la fin, juste avant RETURN rajoutez (ou activez) la ligne TRACE OFF. Relancez l'execution par: EXEC ANIM Grace a l'instruction TRACE ON WAIT, la macro est executee pas a pas. A chaque pas, le programme demande que vous confirmiez le passage a la ligne suivante par un ``Return'' (=``Enter''). Ce mode pas-a-pas est fort utile lorsqu'il se produit une erreur dans le programme mais qu'on ne sait pas bien a quel endroit elle se situe. EXPLICATION DE ANIM#RONDS Tout d'abord, vous observerez que certaines lignes sont precedees d'un asterisque *. Ce sont des lignes de commentaire qui ne sont pas prises en compte lors de l'execution. En general ces lignes expliquent ce que fait le programme dans les instructions suivant la ligne-commentaire. Ces explications sont non seulement utiles mais meme indispensables pour permettre a une autre personne de comprendre l'organisation d'une macro. De meme, quand on relit une macro des mois apres l'avoir ecrite on est bien content de trouver ces lignes explicatives. L'asterisque sert aussi a desactiver une instruction. En effet, en mettant un asterisque devant une instruction on empeche son execution. Par ce moyen on peut donc desactiver ou activer (en enlevant l'asterisque) une instruction. Dans ANIM#RONDS on peut aussi voir que tous les nombres sont a mettre entre crochets une fois qu'ils ont recu leur valeur. Ainsi si on omet les crochets en ecrivant NULL X1 X2 Y1 Y2 la commande NULL ne verra que des chaines de caracteres et non des nombres. Elle protestera en demandant qu'on lui donne les nombres qui lui font defaut. Vous pouvez essayer. Apres la commande NULL toutes les autres variables sont relatives a la commande KEY qui place le rond. Cette commande a besoin de savoir: * Quoi mettre? La reponse est donnee par TYP=20 qui est le numero de code pour un rond plein. 21 donnerait un carre plein. Vous pourrez trouver les autres numeros de code dans le manuel a la rubrique ``Marker type''. * Ou mettre le rond? La reponse est donnee par les deux variables XP,YP qui definissent les coordonnees de l'endroit ou le centre du rond doit etre place. * Quelle taille donner au rond? Elle est definie par la variable KSIZ (Key Size=taille du marqueur). * Quelle couleur donner au rond? La couleur est definie par la variable PMCI (Poly-Marker Color Index = numero de la couleur du marqueur). Il y a 8 couleurs standard: 0=blanc (donc invisible sauf si le fond n'est pas blanc) 1=noir 2=rouge 3=vert 4=bleu 5=jaune 6=magenta (une sorte de rouge-violet) 7=cyan (une sorte de bleu clair) Dans la macro ANIM#COULEUR on verra comment on peut fabriquer des couleurs a volonte. ============================================ SECTION 1: EXEMPLES DE REPRESENTATIONS GRAPHIQUES On peut faire une remarque preliminaire. Tous les graphiques reposent sur le meme principe. On definit un repere c'est-a-dire deux axes puis on place des points par rapport a ce repere. Implicitement ce schema fait appel a une branche des mathematiques inventee par Rene Descartes (1596-1650) et qui s'appelle la geometrie analytique. C'est une forme de geometrie on on travaille sur les coordonnees des points en lieu des points eux-memes. La geometrie analytique figure aux programmes des classes de lycee (a moins que les programmes n'aient change depuis). Ce serait peut-etre une bonne idee de rafraichir vos connaissances a ce sujet. On pourrait penser qu'Internet offre une bonne introduction a ce sujet mais en explorant quelques sites j'ai constate que la presentation est en general trop compliquee. Durant le cours j'essaierai de faire des rappels au fur et a mesure de nos besoins. Ces rappels figureront dans un fascicule intitule ``Elements de geometrie analytique''. *** Explications et commentaires pour graphique1.kumac 1) Dans ANIM desactivez (en mettant un asterisque) l'ordre EXEC ANIM#PARG puis activez EXEC ANIM#GRAPHIQUE1 et desactivez toutes les autres commandes EXEC du meme type. Enfin lancez le programme par EXEC ANIM 2) .kumac Peut-etre vous demandez-vous d'ou vient l'appelation ``kumac'' pour le type des fichiers contenant les macros de PAW? Une composante essentielle de PAW s'appelle KUIP=Kit for a User Interface Package [=Instructions du module assurant la liaison entre PAW et l'utilisateur]. kumac designe une MACro de KUip. 3) Vecteurs et scalaires En survolant le code vous pouvez remarquer 2 points importants. a) On peut mettre plusieurs commandes sur la meme ligne a condition de les separer par un point-virgule. b) Il y a 2 types de variables: celles qui (a droite d'un signe egal) sont entre crochets et celles qui ne sont jamais entre crochets. Les variables qui ne sont jamais entre crochets sont ce qu'on appelle des vecteurs. En programmation un vecteur est simplement une suite de nombres. C'est donc un objet assez different du vecteur defini en geometrie; en fait le seul point commun est qu'en geometrie analytique on definit les composantes d'un vecteur et que ces composantes sont aussi une suite de nombres. Les variables entre crochets sont ce qu'on appelle des scalaires. Un scalaire est un nombre ordinaire tel que 2. On utilise le terme scalaire quand on veut insister sur la difference avec un vecteur (i.e. plusieurs nombres). PAW aime bien les vecteurs mais n'aime guere les scalaires. La notation un peu malcommode avec les crochets autour incite a utiliser le moins de scalaires possibles. Par exemple rien n'empeche de redefinir un scalaire comme etant un vecteur a 1 dimension. Une fois ceci fait, on n'a plus besoin de mettre des crochets autour. Notez qu'on peut mettre entre crochets non seulement des nombres mais aussi du texte comme il est fait dans la commande TITLE [TT]. Cependant on ne peut pas definir une variable contenant du texte comme etant un vecteur a 1 dimension. Les vecteurs ne peuvent contenir que des nombres. 4) SIZE La commande SIZE definit les dimensions de la page graphique. Ici on a choisit une hauteur superieure a la largeur car on veut mettre 3 graphes verticalement et seulement 2 graphes horizontalement. C'est ce qu'indique la commande ZONE 2 3 5) Valeurs des parametres par defaut. Dans les graphes 1A,2A,3A (colonne de gauche) on laisse a PAW le soin de choisir les parametres. Pour chaque commande il y a des valeurs par defaut et ce sont ces valeurs que PAW va mettre si on ne donne pas d'ordre specifique. Dans les graphes 1B,2B,3B on impose des choix specifiques SET VFON [VF] police (FONT en anglais) des chiffres des axes SET VSIZ [VS] taille (SIZE en anglais) des chiffres des axes IGSET LWID [LW] largeur (WIDTH en anglais) du trait IGSET PLCI [C1] Couleur (Poly Line Color Index) du trait 6) NULL NULL [X1] [X2] [Y1] [Y2] est l'instruction qui cree le repere (x,y) dans lequel on fera le graphe. Dans le graphe 3 on en utilise une variante sous la forme: NULL [X1] [X2] [Y1] [Y2] SB qui permet de redefinir des echelles sur un repere pre-existant 7) SIGMA SIGMA est un sigle signifiant: System for Interactive Graphical Mathematical Applications [=Systeme interactif pour des applications mathematiques et graphiques]. Notons que sigma designe aussi une lettre grecque tres utilisee en mathematiques. En fait, malgre cet intitule SIGMA n'a que peu de rapport avec les graphiques, c'est surtout un systeme de calcul. SIGMA permet en particulier de faire des operations directement sur les vecteurs (comme dans MATLAB). Par exemple, la commande SIGMA YT=XT**2 va mettre au carre tous les N nombres contenus dans XT. SIGMA permet aussi de creer des series de nombres. Ainsi N=100 ; SIGMA XT=ARRAY([N],0#9.5) va creer 100 nombres compris entre les valeurs 0 et 9.5. Comme on l'a deja observe plus haut, PAW n'aime guere les scalaires. Les operations arithmetiques sur les scalaires sont malcommodes. De fait, il y a 3 systemes selon le type d'operation dont il s'agit. * S'il s'agit d'une operation simple (+-*/) portant seulement sur deux nombres on peut faire: A=2.5; B=3.5 ; S=[A]+[B] ; P=[A]*[B] ; Q=[A]/[B] * S'il s'agit d'operations simples (+-*/,INT,ABS) portant sur plus de 2 nombres on fera: A=2.5; B=3.5 ; C=2 ; S=$EVAL([A]+[B]*[C]) * Pour les autres usages il est preferable de definir des vecteurs correspondants aux scalaires et faire l'operation avec SIGMA. Voici un exemple pour elever un nombre a la puissance 3. A=2 ; VE/CR VA(1) R [A] ; SIGMA VB=VA**3 La seconde instruction de cette ligne demande quelques explications. VE/CR signifie VECTOR/CREATION c'est-a-dire qu'un cree une suite de nombres. VA est le nom du vecteur cree. 1 est la dimension du vecteur c'est-a-dire combien de nombres il contient. R est le type du vecteur. R signifie ``nombre reel'' par opposition aux entiers. Par la suite, nous n'utiliserons que ce type. Enfin [A] est la valeur donnee a l'unique composante du vecteur. La commande SIGMA VB=VA**3 va fabriquer un vecteur ayant egalement une seule composante dont la valeur sera 2**3=8. Notez que dans un ordre SIGMA tous les vecteurs doivent avoir la meme dimension, autrement SIGMA proteste et refuse de faire l'operation. Avant d'en finir avec SIGMA notons qu'il y a dans SIGMA des operations particulieres dont le resultat est forcement un scalaire. A titre d'exemple ce type d'operation va s'ecrire de la facon suivante: S=$SIGMA(VSUM(V)) Cette instruction fait la somme des composantes du vecteur V. Ainsi, VE/CR V(3) R 1 1 3 va donner $SIGMA(VSUM(V))=1+1+3=5 Il y a quelques autres operations du meme type que nous verrons au fur et a mesure que nous en aurons besoin. 8) VE/CR et VE/DE Nous venons deja de voir l'instruction pour creer un vecteur. Donnons un second exemple: N=5 ; VE/CR V([N]) R 4*1 2 4*1 signifie que les 4 premieres composantes de V seront egales a 1. La 5e sera egale a 2. Ce vecteur va subsister tant qu'on n'a pas quitte PAW. A moins bien sur qu'on le detruise volontairement. Pour detruire le vecteur V on ecrira: VE/DE V VE/DE signifie VECTOR/DELETE [DELETE=detruire]. On peut detruire plusieurs vecteurs en meme temps en ecrivant: VE/DE U,V,W On peut aussi les detruire tous en ecrivant: VE/DE * Cette instruction devra figurer de facon a peu pres systematique a la fin de toute macro. Pourquoi? Supposons que dans cette macro on cree un vecteur V sans le detruire a la fin. Si on re-execute la macro, au moment de creer ce vecteur, PAW va vous avertir qu'un vecteur de ce nom existe deja. En detruisant V a la fin de la macro on evite ce genre d'avertissement 9) GRAPH [N] XT YT AWL Ceci est une des commandes les plus utiles puisqu'elle permet de tracer une courbe. Puisque XT et YT sont deux suites de nombres, GRAPH va tracer la courbe suivante: x=XT(i) y=YT(i) ou l'indice i prend les valeurs 1,2,...,N (ici N=100). En mathematiques in dit qu'une telle courbe est definie de facon parametrique parce que x et y dependent tous deux du parametre i. Cette definition parametrique s'oppose a la definition ou y est defini comme etant une fonction de x: y=F(x) par exemple y=x**2. D'un point de vue graphique il y a une difference fondamentale entre les deux definitions qui est la suivante. Quand on ecrit y=F(x), a toute valeur de x il ne peut correspondre qu'une seule valeur de y. Autrement dit, avec cette representation on peut dessiner une parabole ou un demi-cercle mais pas un cercle entier car pour un cercle entier a toute valeur de x correspondent 2 valeurs de y. Avec la definition parametrique on n'a pas cette limitation. A une valeur de x peuvent correspondre autant de valeurs de y que l'on veut. Ainsi pour representer un cercle de rayon r on ecrira: x=r*cos(i) y=r*sin(i) Incidemment, vous pouvez remarquer qu'avec cette definition, on a: x**2 + y**2 = r**2 ce qui vous rappelle peut-etre vos souvenirs du lycee. ============================================ SECTION 2: ORGANISATION DE VOS MACROS DANS UNE MACRO-TIROIR Au bout de quelques semaines vous aurez cree quelques dizaines de macros. Pour s'y retrouver il est important de ne pas les laisser de facon disparate parmi vos fichiers. Par ailleurs, il peut etre utile de conserver ces macros dans l'ordre ou vous les avez creees. L'organisation par TIROIRS proposee ci-dessous repond a cet objectif. Elle repond aussi a un autre but qui est le suivant. Certaines de vos macros qui ont une utilite assez generale seront appelees des macros utilitaires. Par exemple, si vous creez une macro dessinant un cavalier sur un cheval c'est un travail asez long et vous serez amene a l'utiliser a de nombreuses reprises. C'est un exemple de macro utilitaire. Il sera bon de faire la liste de vos macros utilitaires au debut de la macro-tiroir definie ci-dessous, ceci afin de les garder presentes a l'esprit et pouvoir s'en servir au moment opportun. Comment utiliser cette macro-tiroir? C'est tres simple. Toutes les commandes EXEC ANIM#FILM, etc seront inactivees par des * sauf une; mettons que ce soit EXEC ANIM#RONDS Ainsi quand on va taper l'instruction EXEC ANIM dans la fenetre de commande, seule MACRO RONDS va etre executee. En fait ce n'est pas tout a fait vrai puisque la macro ANIM#PARG est aussi executee a chaque fois. Mais cette macro ne fait que donner aux parametres graphiques les valeurs qu'on utilise habituellement. Vous pourrez empiler dans cette macro-tiroir toutes les macros qui seront creees par la suite. Y a-t-il une limite a cet empilement? L'experience montre que lorsque le fichier comporte de l'ordre de 50 macros, il commence a devenir trop gros pour qu'on puisse se deplacer a l'interieur aisement. Probablement cela n'arrivera pas avant la fin du semestre. Lorsque cela se produit il suffit de creer une autre macro-tiroir appelee par exemple MACRO BNIM, d'y recopier la liste des macros utilitaires placee au debut de MACRO ANIM et de recommencer l'operation. En ajoutant ainsi un tiroir a un autre tiroir vous creerez ce qu'on pourrait appeler une commode composee d'un certain nombre de tiroirs. Bien sur, de l'interieur de la macro-tiroir BNIM on pourra appeler les macros de la macro-tiroir ANIM et inversement. Tout cela communique. Notez que chacune des macros de la macro-tiroir peut aussi s'executer directement en tapant par exemple dans la fenetre de commande. EXEC ANIM#BONJOUR mais en faisant cette execution directe on n'a pas le benefice de la macro PARG, et on ne cree pas de fichier postscript. ============================================ SECTION 3: COMMENT REALISER UNE ANIMATION? Avant d'aborder la question de l'animation, il nous faut expliquer comment ``modulariser'' un programme par appel a des macros. Cela nous sera indipensable pour faire les animations. Pour etre clair et lisible un programme doit etre organise de facon MODULAIRE. Une tache complexe doit d'abord etre decomposee en une succession de taches plus simples et chacune de ces taches sera effectuee par une macro specifique. Selon les cas ces macros peuvent etre des macros utilitaires (c'est-dire servant plusieurs fois) ou bien des macros a usage unique. Le programme va donc etre une succession d'appel a ces macros. Quelles sont les regles qui gouvernent l'organisation de ces macros? Dans PAW il y a 2 regles de base. * Tout vecteur cree dans une macro va exister egalement dans les autres macros. En fait, il va exister durant toute la session PAW. * Un scalaire (nombre ou texte) n'existe que dans la macro ou il a ete cree. Cependant il existe un moyen de transmettre des scalaires a une macro lorqu'on le desire. Cela est illustre par les exemples ci-dessous. La transmission d'un scalaire est illustree par la macro ANIM#BONJOUR. Dans la fenetre de commande tapez: EXEC ANIM#BONJOUR Bonjour La variable scalaire est ici le texte ``Bonjour''. La macro recupere cette variable par la ligne TX=[1] Le 1 fait reference au fait que c'est le premier argument de la macro. Ici le 1 est mis entre crochet, non parce que c'est un scalaire mais parce que c'est la syntaxe normale pour recuperer des arguments. En effet vous verrez un peu plus loin que meme si 1 est un vecteur on le met quand meme entre crochets. L'utilisation de BONJOUR conduit au dialogue suivant. ---------------------------------- PAW > EXEC ANIM#BONJOUR Bonjour Comment allez-vous? PAW > EXEC ANIM#BONJOUR Bonsoir Pardon, que dites-vous? ---------------------------------- SEQUENCE IF ... ENDIF En examinant le code vous voyez des instructions commencant par IF. la traduction de ce mot anglais est ``si''. Deux autres mots anglais sont utilises dans cette construction: THEN qui signifie: ``alors'', ``dans ce cas'' et END qui signifie ``fin''. ENDIF marque la fin de la sequence commencant par IF. Si vous oubliez ENDIF, PAW protestera. La ligne IF [TX]=[T1] THEN pourra se lire de la facon suivante: Si la variable TX est egale a la variable T1 alors faites ce qui suit jusqu'a la ligne ENDIF. Un second exemple sera fourni par une modification de la macro ANIM#RONDS vue au debut. Nous allons la transformer en une macro utilitaire capable de placer un rond dans des conditions regies de l'exterieur. Voyez la macro ANIM#ROND. Quelles sont les differences entre ANIM#RONDS et ANIM#ROND? Tout d'abord les noms different legerement. on avait mis un S a RONDS car cette macro trace deux ronds, mais on met ROND au singulier dans la macro utilitaire car elle ne trace qu'un seul rond a la fois. Ensuite, vous voyez que ANIM#ROND commence par une ligne de commentaire ``usage: EXEC ANIM#ROND [XP] [YP] [MS] [MC] -> place 1 ROND'' Cette ligne indique comment utiliser cette macro, c'est-a-dire de quelles variables elle a besoin, et ce qu'elle fait. Les lignes de commentaires suivantes indiquent quelle est la signication des variables de la liste de commande. Il est conseille de mettre un chapeau de ce type a toutes les macro utilitaires que l'on cree afin de savoir s'en servir le jour ou on en a besoin. Puis, la premiere ligne d'instructions est: XP=[1] ; YP=[2] ; MS=[3] ; MC=[4] A vrai dire cette ligne est facultative. On pourrait tres bien laisser les variables sous leur forme [1],[2],[3],[4]. Mais cela ne serait guere parlant. Les noms qu'on donne aux variables rappellent du moins leur sens. Les deux lignes suivantes sont identiques a celles de ANIM#RONDS. TEST DE ANIM#ROND Allez dans ANIM#TESTROND; activez la partie 1 en mettant un asterisque devant GOTO 1 (=allez a la ligne 1). Notez que dans la ligne contenant le 1, celui-ci est suivi d'un double point. De la meme facon, desactivez les autres parties en enlevant les asterisques devant les GOTO . Puis, comme d'habitude, arrangez les asterisques de la partie EXEC de ANIM afin que seul TESTROND soit execute. Enfin lancez l'execution par EXEC ANIM dans la fenetre de commande. Vous voyez apparaitre un rond. Vous vous demandez peut-etre quel avantage possede ANIM#ROND par rapport a ANIM#RONDS. Cette derniere macro faisait 2 ronds alors que ANIM#ROND n'en fait qu'un seul. On pourrait a premiere vue penser que ANIM#RONDS etait plus efficace que notre macro utilitaire. La partie 2 de ANIM#TESTROND va vous montrer la difference fondamentale entre les 2 macros. ANIM#RONDS fait toujours les memes deux ronds alors que ANIM#ROND va nous permettre de faire autant de ronds que l'on veut et ou l'on veut. BOUCLE DO ... ENDDO Cette partie comprend ce qu'on appelle une boucle DO. C'est un element capital dans la programmation car elle permet de repeter une sequence donnee autant de fois que l'on souhaite. DO est un mot anglais signifiant ``faire''. L'instruction DO I=1,10 se lit: ``Repetez 10 fois toutes les instructions depuis DO jusqu'a ENDDO (fin de la boucle) en faisant varier le nombre I de 1 a 10''. Notre objectif est de faire une animation ou on voit le rond se deplacer de la gauche vers la droite. Prenez N=10. Ainsi nous ne fabriquerons que 10 images ce qui nous permettra de voir plus clairement ce qui se passe. Prenez soin de desactiver les 2 lignes: MC1=0 ; EXEC ANIM#ROND [XP] [YP] [MS] [MC1] IGSET TXCI 0 ; ITX [XP1] [YP1] [TT] Verifiez aussi que seul le NULL situe avant la boucle DO est actif. Et verifiez que toute la partie TEMPORISATION entre GOTO 21 et 21: est inactivee. Si vous lancez l'execution par EXEC ANIM vous obtiendrez une image avec 10 ronds etages de gauche a droite. Ce n'est pas ce que nous voulions. En fait, il y a bien 10 images successives mais elles se sont succedees trop rapidement si bien qu'on ne voit que la derniere. Comment resoudre ce probleme? Manifestement il faut introduire une temporisation entre les images successives. Il y a deux solutions, une bonne et une moins bonne. Pedagogiquement, les deux ont un interet Nous allons d'abord expliquer la moins bonne. Cette methode consiste a utiliser une commande de PAW qui s'appelle WAIT (=attendre). WAIT a 2 arguments: WAIT [TX] [DELAI] TX est un texte qui sera imprime a l'ecran a chaque fois que WAIT est execute. [DELAI] est un temps exprime en secondes qui donne le temps d'attente impose par WAIT. Nous allons prendre un DELAI de 1s. Pour voir ce que cela donne activez la partie TEMPORISATION en mettant un asterisque devant le GOTO 21. Prenez soin que la ligne: A=1 ; B=2 ; DO K=1,[KM] ; C=[A]+[B] ; ENDDO reste desactivee. Cette fois l'execution fait bien apparaitre 10 images successives, mais nous ne voyons toujours pas le rond se deplacer de la gauche vers la droite. Ou plus exactement, le rond se deplace bien, mais ses anciennes positions restent a l'ecran. Comment faire pour qu'on ne voit qu'un seul rond a la fois sur le graphe? D'une facon ou d'une autre il faut effacer les anciennes positions. La encore, il y a deux solutions, une bonne et une moins bonne et la encore les deux solutions ont un interet pedagogique. Commencons par la moins bonne. Pour effacer les ronds anterieurs il suffit de les recouvrir avec du blanc. C'est ce qui est fait dans la ligne: MC1=0 ; EXEC ANIM#ROND [XP] [YP] [MS] [MC1] Comme 0 est l'indice de couleur correspondant au blanc, la commande va recouvrir le rond magenta avec un rond identique mais blanc donc invisible. Pour voir ce que cela donne, activez la ligne ci-dessus et re-executez. Cette fois vous voyez bien un seul rond et qui se deplace de gauche a droite. Cependant sur le texte en haut du graphique vous voyez que les chiffres se chevauchent. La encore, cela est du au fait que l'ancien texte reste present a l'ecran. Pour resoudre ce probleme pouvons nous utiliser la meme solution que pour les ronds, a savoir mettre du blanc sur les nombres precedents? Assurement. C'est ce que fait la ligne: IGSET TXCI 0 ; ITX [XP1] [YP1] [TT] Par cette commande on re-ecrit exactement le meme texte par dessus mais en blanc. Pour voir le resultat activez cette ligne et re-executez. Cette fois les chiffres ne se superposent plus et sont clairement lisibles. La seconde solution pour effacer les anciens ronds est plus simple et plus radicale. Notez que jusqu'ici nous ne faisions a chaque execution qu'un seul graphique. Si vous pouvez ouvrir le fichier paw.ps qui enregistre les graphiques vous verrez que ce fichier comporte un seul graphique. Si nous faisons 10 graphiques successifs chacun d'entre eux ne contiendra qu'un seul rond. Pour cela, il suffit de faire ouvrir un nouveau graphique a chaque pas de la boucle par l'instruction NULL [X1] [X2] [Y1] [Y2] Autrement dit, il vous faut activez cette ligne situee au debut de la boucle et desactivez la ligne similaire situee avant le debut de la boucle. Vous pouvez aussi desactivez les deux lignes par lesquelles nous faisions du blanc car nous n'en avons plus besoin. Nous voyons le rond se deplacer de gauche a droite. Si vous regardez attentivement les axes vous verrez par moment des legers sauts qui sont dus au fait qu'on superpose 10 systemes d'axes successifs. Si vous pouvez visualiser le fichier paw.ps vous verrez qu'il comprend maintenant 10 graphiques. Si le rond se deplace certes de gauche a droite, l'intervalle de 1 seconde entre les images est trop long pour donner l'illusion d'un mouvement continu. Au lieu de 1s entre deux images il faudrait 1/25s. Malheureusement, la commande WAIT ne donne pas la possibilite d'avoir un temps d'attente plus court que 1s. C'est a cause de cette limitation que nous sommes obliges de trouver une autre solution. Sans WAIT nous avions un defilement trop rapide. Si l'on veut voir quelque chose ressemblant a un film, il faut ralentir le defilement. Cela est realise par la ligne: A=1 ; B=2 ; DO K=1,[KM] ; C=[A]+[B] ; ENDDO La methode consiste, avant le passage a l'image suivante, a faire effectuer une serie d'additions. Bien entendu, on pourrait remplacer les additions par n'importe quelle autre operation. Durant tout le temps ou PAW est occupe a faire ces operations il ne va pas afficher l'image suivante. Pour voir ce que cela donne desactivez la ligne *TW=[I]s ; T=1 ; WAIT [TW] [T] et activez celle avec les additions, Commencez par prendre KM=100000. Vous voyez le rond se deplacer de gauche a droite de la meme facon qu'il le faisait avec la commande WAIT. Dans les essais avec WAIT le CPTIME (CP=Central Processor= Unite centrale, TIME=temps) etait reste quasiment a 0 ce qui montre que le temps d'attente impose par WAIT n'etait pas pris en compte dans ce temps. Par contre, comme les additions sont realisees dans l'unite centrale, ce temps est maintenant comptabilise et vous pouvez voir que le temps CP imprime a l'ecran est presque 10s. Incidemment, la fonction $CPTIME donne le temps ecoule depuis l'appel precedent a cette fonction. Cela est illustre dans la macro ANIM#CPTIME. Pour l'instant nous n'avons fait que reproduire ce qui avait ete obtenu avec WAIT, mais en jouant sur le nombre d'operations (autrement dit sur la valeur de KM) nous pouvons ajuster le temps d'attente a notre gre. Pour passer d'un temps d'attente de 1s a un temps de 1/25s il faut diviser KM par 25 ce qui donne KM=4000. En prenant KM=4000, l'execution ne dure que 0.4s ce qui donne un mouvement bien trop rapide. Pour ralentir le mouvement il suffit d'augmenter le nombre d'images. C'est exactement le meme procede qui est utilise en cinema pour faire du ralenti. Changez N=10 en N=400 et relancez. Le mouvement du rond est maintenant plus agreable mais vous observez un clignotement desagreable au niveau des axes. Il y a un remede simple qui est de supprimer les axes. Pour cela desactivez la ligne NULL [X1] [X2] [Y1] [Y2] et activez la ligne: NULL [X1] [X2] [Y1] [Y2] AB Avec cette option AB, les axes ne sont pas traces. Il subsiste des clignotements dans le rond lui-meme. Nous verrons un peu plus loin comment y remedier. QUELLES VALEURS CHOISIR POUR LA TEMPORISATION ET POUR LE NOMBRE D'IMAGES? Dans ANIM#TESTROND (partie 2) la realisation du film est conditionnee par deux parametres: d'une part N qui est le nombre total d'images et d'autre part KM qui regle la temporisation c'est-a-dire l'intervalle de temps tau entre deux images. Comment faut-il choisir ces parametres? A ce sujet on peut donner les regles suivantes. * Si on choisit une temporisation qui produit un tau nettement superieur a 50ms on verra le rond avancer par bonds, autrement dit le film apparaitra hache. On sait que 25 images par seconde (c'est-a-dire 50ms entre deux images) est la vitesse minimale (compte tenu du temps de persistance des images sur la retine) pour qu'un film nous apparaisse ``fluide''. * Que verra-t-on si on choisit tau nettement plus petit (par exemple tau=10ms) que 50ms sans changer le nombre total d'images? Bien sur, le film sera encore fluide mais sa duree sera si breve que nous aurons a peine le temps de le voir. Si nous augmentons N en meme temps que nous diminuons tau la duree du film restera la meme et le film produira ce qu'on appelle un ralenti comme lorsqu'on voit une balle emerger lentement du canon d'un pistolet. En conclusion, on peut dire que si on souhaite fonctionner a l'economie c'est-a-dire ne pas creer plus d'images qu'il n'est necesaire il faut choisir un tau de l'ordre de 50ms et un nombre d'images qui donne l'apparence du mouvement reel. Evidemment, dans l'exemple du rond allant de gauche a droite il n'y a pas de vitesse ``reelle''. C'est pour cela que le coix de N apparait arbitraire. Au contraire, pour un marcheur on verra par un simple coup d'oeil si la vitesse est en conformite avec le mouvement reel. CREATION D"UN FILM PAR LE LOGICIEL ``convert'' de ImageMagick Le procede de temporisation vu ci-dessus donne un moyen rapide et simple de visualiser un film mais n'est qu'une solution approximative. Lorsque nous voudrons creer un film de meilleure qualite nous ferons appel a ``convert'' qui est un logiciel de la bibliotheque ImageMagick. Cette methode peut se resumer par les etapes suivantes. 1) Par l'execution precedente nous pouvons creer 100 fichiers postscript paw001.ps,...,paw100.ps. 2) Ces fichiers peuvent etre tranformes en un film par l'instruction suivante: convert -delay 50 paw*.ps film.gif Cette commande doit etre tapee non dans la fenetre de commande de PAW, mais dans la fenetre de commande de ``convert'' (qu'il convient de telecharger au prealable s'il n'est pas deja sur votre ordinateur). 3) Le fichier film.gif est cree par convert. C'est un film qui peut etre visualise par n'importe quel logiciel capable d'ouvrir un tel fichier. Voyons maintenant de plus pres la commande ``convert''. Le mot anglais ``delay'' signifie ``delai'. Par la commande precedente les 100 fichiers paw001.ps,...,paw100.ps vont etre mis bout a bout avec un delai de 50 milliseconde entre deux images successives et le film ainsi obtenu sera enregistre sous la forme du fichier film.gif. A la place de ``film'' on peut bien sur mettre n'importe quel autre nom mais le type .gif est imperatif. Notez qu'il est crucial que les fichiers soient numerotes paw001.ps,paw002.ps,...,paw100 et non: paw1.ps,paw2.ps,...,paw100 faute de quoi ils ne seront pas assembles dans l'ordre voulu. Cela resulte du fait que dans la classification alpha-numerique standard xx9yy n'est pas suivi par xx10yy mais par contre xx009yy est suivi par xx010yy. Comme vous le voyez, cette procedure basee sur convert est notablement plus longue que la methode de temporisation. Dans toute la phase de mise au point du film nous utiliserons la methode de temporisation; nous ne ferons appel a la methode par ``convert'' que lorsque nous voudrons obtenir un resultat de meilleure qualite pour le produit final. Notons que ``convert'' a bien d'autres fonctions qui permettent en particulier d'organiser en animation des images recuperees sur Internet. Apres ces explications relatives a la realisation d'animations nous revenons aux regles pour l'utilisation des macros. Dans les exemples qui suivent nous expliquons comment transmettre un vecteur d'une macro a une autre. ===================================================== SECTION 4: TRANSMISSION D'UN VECTEUR A UNE MACRO UTILITAIRE. Nous avons dit precedemment qu'une fois cree, un vecteur subsiste jusqu'a ce qu'il soit volontairement detruit ou bien, si on ne le detruit pas, jusqu'a ce qu'on ferme la session PAW. Tant qu'il survit, ce vecteur peut etre utilise dans toute macro. La question de la transmission d'un vecteur a une macro utilitaire peut donc sembler superflue. En fait pas completement. Pour voir pourquoi examinons l'exemple de la macro ANIM#RONDV. Cette macro est presque identique a la macro ANIM#ROND. La seule difference est qu'on a remplace les coordonnees [XP],[YP] par un vecteur qui a precisement ces deux composantes. Examinez ANIM#TESTROND (no 3) pour voir comment ce vecteur est defini. Vous voyez aussi que dans ANIM#RONDV on utilise ce vecteur sous la forme [1] parce que c'est le 1e argument de la liste. Peut-etre vous demandez-vous pourquoi le vecteur doit apparaitre dans la liste des arguments. N'avons-nous pas dit qu'une fois cree dans ANIM#TESTROND le vecteur VP va etre utilisable dans toutes les macros? Mais si dans ANIM#RONDV a la place de [1] on mettait VP, cela impliquerait qu'a chaque fois qu'on veut utiliser cette macro il faut definir un vecteur portant exclusivement le nom VP. Cela serait une grande contrainte. En fait on veut que ANIM#RONDV puisse fontionner avec n'importe quel vecteur, quel que soit son nom. Un parallele peut nous aider a mieux comprendre ce point. En appelant les renseignements telephoniques vous vous attendez a ce que n'importe quel operateur vous renseigne independemment de son nom. La solution consistant a mettre VP dans ANIM#RONDV reviendrait a ne pouvoir faire appel qu'a un seul operateur portant un nom particulier (par ex Dupont). Passons a l'execution de ANIM#TESTROND (no 3). Il nous faut d'abord mettre et enlever les asterisques voulues pour que ce soit bien la partie 3 qui soit executee. Une fois ceci realise, on peut taper EXEC ANIM Incidemment, on peut d'ailleurs aussi reproduire cette commande en utilisant la touche avec la fleche vers le haut, cela reproduit la commande precedente. Vous voyez apparaitre deux ronds. Pourquoi a-t-il fallu mettre les instructions VE/DE VP? Pour le voir, desactivez ces deux instructions et relancez. Vous voyez que PAW vous averti que vous redefinissez un vecteur qui existe deja. Ce n'est pas un message d'erreur mais plutot un message d'avertissement. Si vous redefinissez un vecteur pre-existant comme etant un vecteur de meme dimension cela ne porte pas a consequence. Mais si la redefinition n'a pas la meme dimension cela peut amener des erreurs. Bref, il vaut mieux faire en sorte qu'il n'y ait pas d'avertissement de cette sorte. SECOND EXEMPLE DE MACRO UTILITAIRE: DISTANCE ENTRE 2 POINTS La macro ANIM#DIST calcule la distance entre deux points du plan. Contrairement a toutes les macros precedentes, ce n'est pas une macro graphique mais une macro de calcul. Elle pourra nous etre fort utile dans la suite. Les difficultes de cette macro sont sans doute les suivantes: * la formule de geometrie analytique utilisee que vous avez certainement vu au lycee mais peut-etre oublie entre-temps. * les instructions de calcul. Ainsi sqrt(.) prend la racine carree du nombre entre parentheses; sqrt est un sigle pour ``square root''=racine carree. En lancant ANIM#TESTDIST vous allez obtenir deux resultats que vous pouvez verifier de facon independante. Le premier est facile a verifier parce que c'est une distance purement horizontale. Le second resultat est egalement facile a verifier car le theoreme de Pythagore nous apprend que la distance cherchee est racine de 1+1. Or on sait que la racine carree de 2 vaut 1.414. ============================================ SECTION 5: EXPLICATION DE LA MACRO ANIM#COULEUR Cette macro comporte 4 parties. * La partie 1 presente les 8 couleurs de base * Dans la partie 2 on montre comment creer des couleurs a volonte par melange de couleurs primaires. * Dans la partie 3 on construit une palette de couleurs * Dans la partie 4 on construit une animation dans laquelle les couleurs changent de facon continue La partie 1 ne comprend que 2 nouveautes. * D'une part l'instruction LINE [XA] [YA] [XB] [YB] ``LINE'' veut dire droite. Cette commande trace un segment de droite allant du point A(xa,ya) au point B(xb,yb). L'epaisseur du trait est reglee par IGSET LWID (line width) et sa couleur par IGSET PLCI (poly-line color index). * La commande RV=$RGBINFO([I1],R) definit une variable donnant la proportion de Red (rouge) dans la couleur correspondant a l'indice [I1]. De meme les deux autres commandes donnent les proportions de vert et de bleu. Vous pouvez voir que le blanc et le noir correspondent respectivement a (1,1,1) et (0,0,0). Le rouge, vert, bleu sont des couleurs primaires en ce sens qu'elles ne comportent qu'une seule sorte de couleur alors que jaune, magenta, cyan sont des couleurs secondaires en ce sens qu'elles sont un melange a parts egales de deux couleurs primaires. Apres l'indice 7 (du moins sur mon systeme) il n'y a plus que du blanc sauf pour 10 qui est cyan. Il se peut que sur votre ordinateur ces indices soient pre-definis et donnent autre chose que du blanc. La seule nouveaute de la partie 2 reside dans la commande COLOR_TABLE 10 0.7 1 0.5 Cette commande cree une couleur correspondant a l'indice 10 (qu'on pourrait remplacer par n'importe quel autre entier) qui a 0.7 de rouge, 1 de vert et 0.5 de bleu. Vous pouvez verifier qu'en remplacant 10 par 1 la couleur reste la meme et n'est pas du noir. Autrement dit, la nouvelle definition s'applique meme si l'indice est celui d'une couleur de base. Notez que la redefinition de la couleur 1 va subsister pour toute la session, c'est-a-dire que tout ce qui etait initialement noir (par ex les axes) va maintenant etre vert pale. Pour revenir a 1=noir il suffit de fermer la session et d'en recommencer une nouvelle. La partie 3 ne fait qu'exploiter la creation de couleurs d'une facon plus systematique. Dans les 3 colonnes on part a chaque fois du blanc (1,1,1), puis on fait diminuer la proportion de l'une des couleurs. Au contraire dans la partie 4 on part a chaque fois du noir (0,0,0), puis on augmente la proportion de 2 des couleurs ce qui va amener aux 3 couleurs secondaires magenta, jaune et cyan. ==================================================== SECTION 6: EXPLICATION DE LA MACRO ANIM#FILM La principale nouveaute (et sans doute difficulte) de cette macro est l'utilisation de la representation parametrique d'un cercle dans les expressions de XV et YV. A ce propos vous pouvez vous reporter au fascicule ``Elements de geometrie analytique''. (quand il sera ecrit). On y montre que les equations d'un cercle sont: X=[r]*cos([omega]*T), Y=[r]*sin([omega]*T) ou [omega] est un parametre fixe et T une variable. Dans la macro ces relations sont ecrites sous forme vectorielle, c'est-a-dire que X,Y et T sont des suites de JM nombres. En fait, ici il ne s'agit pas exactement d'un cercle mais d'un cercle de rayon croissant c'est-a-dire d'une spirale. Cette variation du cercle est produite par le facteur: (T/[TM])**2. Comme la premiere valeur de T est 0 et la derniere TM, le rapport T/[TM] va varier de 0 a 1. Le fait de mettre ce rapport au carre ne change pas les limites qui restent (0,1) mais cela ralentit la croissance du rapport au debut et l'accelere a la fin. A part l'expression de XV,YV il n'y a guere que des commandes standard dans cette macro. Pour commencer on peut de plus oublier (et desactiver) la partie allant de GOTO 11 a 11:. Pour l'instant activez le NULL qui est avant la boucle DO et desactivez le NULL qui est juste au debut de la boucle DO. En executant vous voyez apparaitre une spirale qui se deroule. Mais vous pouvez aussi remarquer que les chiffres en haut du graphique se chevauchent et sont illisibles. Comprenez-vous pourquoi? Si vous ne voyez pas clairement le pourquoi, vous le verrez sans doute mieux en observant ce que l'on obtient en activant la partie entre GOTO 11 et 11:. Ce qu'on obtient est different de l'animation qu'on avait observe par ANIM#FILMDEMO en ce sens que la partie en magenta couvre presque toute la courbe alors qu'anterieurement le trait en magenta etait limite a l'extremite. La raison, vous l'avez surement devine, est qu'ici on superpose toutes les courbes sur le meme graphique. Nous avons deja vu le meme probleme dans la macro du rond mobile. La solution est d'effacer le graphe precedent a chaque pas en ouvrant un nouveau graphe. Pour cela il faut activer le NULL qui est au debut de la boucle DO et desactiver le NULL qui est avant la boucle DO. Avec ce changement on re-obtient la meme spirale que par ANIM#FILMDEMO. ==================================================== SECTION 7: PAW PAS CONTENT! EXPLICATION DE MESSAGES D'ERREUR Lorsqu'on ecrit une macro on fait necessairement des erreurs. Cela peut aller de simples fautes de frappe telles que: GITO 1 ou A=[B[ a des erreurs plus subtiles. Pour la plupart d'entre elles, ces erreurs vont susciter des protestations de la part du compilateur. Bien que la notice de PAW nous apprenne que c'est un langage qui est non pas compile mais ``interprete'', nous ne ferons pas cette distinction qui, de toutes facons, ne change rien a notre niveau. Un compilateur ideal serait cense nous dire a quelle ligne se situe une erreur et en quoi elle consiste. En fait, quel que soit le langage, les compilateurs sont tres loin d'atteindre ce degre de perfection. Un exemple simple va vous en persuader rapidement. Comme terrain de maneuvre pour ce panorama (tres incomplet) des erreurs possibles nous utiliserons la macro ANIM#ERREUR. Bien qu'elle ne comporte que peu de lignes, elle peut etre l'occasion de plusieurs type d'erreurs. Pour commencer, remplacez la ligne: N=10 ; S=0 par la ligne: N=10 ; ; S=0 puis executez par EXEC ANIM (apres avoir desactive toutes les autres commandes EXEC). Vous obtenez le message d'erreur suivant: *** Break *** Segmentation violation Traceq lun = 0, level = 99 TRACEQ. In-line trace-back still not available. Longjump traduction: break=arret. segmentation incorrecte. Le reste est incomprehensible. Ce message d'erreur est desastreux car il est non seulement incomprehensible mais surtout il n'indique pas a quelle ligne se situe l'erreur. Dans le cas present l'exploration est limitee a quelques lignes, mais supposez que par inadvertance vous ayez pace un ; ; quelque part dans un gros programme sans vous souvenir ou. Cela sera une erreur fort difficile a reperer. Heureusement, les messages d'erreur de PAW ne sont pas toujours aussi opaques. Voici un exemple plus clair. Supprimez le ; en exces et remplacez la ligne DO I=1,[N] par la ligne DO I=1,[N[ Cette fois vous obtenez le message d'erreur suivant: *** Invalid arithmetic expression in file ./anim.kumac 1189: DO I=1,[N[ traduction: Expression arithmetique incorrecte dans le fichier anim.kumac Ce diagnostic est bien meilleur car non seulement il est comprehensible et explique assez bien le type d'erreur mais surtout il indique correctement la ligne ou se situe l'erreur. Pourquoi le diagnostic est-il meilleur? Apres =1, PAW attendait un nombre. A la place il a trouve une chaine de 4 caracteres. Ainsi il lui a ete facile de protester a bon escient. Rectifiez le crochet incorrect et re-executez. Vous obtenez le message suivant: *** VECTOR/CREATE V1(10): existing vector V1(10) replaced traduction: le vecteur pre-existant V1(10) a ete remplace par un autre de meme nom. Ceci n'est pas vraiment un message d'erreur mais plutot un avertissement. Que s'est-il passe? Dans la tentative d'execution avec DO I=1,[N[ PAW a trouve une erreur dans cette ligne et n'a donc plus rien execute apres cette ligne, en particulier il n'a pas execute la ligne VE/DE * qui efface les vecteurs crees. Cela signifie que le vecteur V1 est reste actif et lorsque vous relancez le programme apres avoir corrige l'erreur la macro va creer un vecteur identique. Alors PAW vous avertit qu'il en existe deja un qui porte ce nom. Si vous executez une nouvelle fois, cet avertissement n'est plus present car cette fois l'execution de la commande VE/DE * a detruit le vecteur V1 et vous pouvez donc a nouveau en creer un qui porte ce nom. Les deux erreurs qu'on vient de voir ont ete reperees par PAW au niveau de la compilation. Les erreurs qu'on va voir maintenant sont des erreurs d'execution. Remplacez la ligne S=[S]+[I] par la ligne: S=[S]+I Vous obtenez le message suivant: *** VECTOR/CREATE: invalid initializer 0+I+I+I+I+I+I+I+I+I+I for V2(1) traduction: initialisation incorrecte pour V2(1) Que s'est-il passe? En oubliant les crochets autour de I (un oubli assez commun) vous additionnez 10 fois le caractere I. Ce n'est evidemment pas ce que vous vouliez faire, mais a ce niveau PAW ne trouve rien a redire. C'est seulement lorsque vous essayez d'utiliser cette variable comme composante d'un vecteur que PAW proteste car a cet endroit PAW attend un nombre et non du texte. Notez que le numero de ligne n'est pas indique mais comme on a le nom du vecteur il est facile de trouver l'erreur. Voyons maintenant une erreur en apparence similaire mais qui va vous demontrer une des qualites principales de PAW par rapport a certains autres langages (comme FORTRAN par exemple). Supposons qu'avant le debut de la boucle on oublie de definir S. Donc enlevez l'instruction S=0 et re-executez. Cette fois vous notez que PAW se bloque lors de l'execution. A quel endroit se bloque-t-il exactement? Pour le savoir activez les lignes TRACE ON WAIT et TRACE OFF. En executant ainsi pas-a-pas vous voyez que paw se bloque apres: >>>>>> DO:I = 2 2.1192: S=[S]+[I] Pour sortir de ce blocage, faites ``Control c''. vous verrez apparaitre a l'ecran le message suivant: ^C *** Break *** Keyboard interrupt Longjump *** Macro execution stopped traduction: Keyboard=clavier. L'execution de la macro a ete stoppee. Pourquoi ceci est-il un grand avantage? Lorsque FORTRAN rencontre une variable non definie il lui donne la valeur qui est dans le registre de cette variable a cet instant; clairement il y a peu de chance pour que cette valeur se trouve etre egale a celle que la variable aurait normalement du avoir.Le resultat en est qu'on croit que le calcul s'est bien deroule mais qu'en realite le resultat final est FAUX. Incidemment, MATLAB signale aussi les variables non definies. Par exemple: a=1 ; b=b+a donne le message: Undefined function or variable 'b'. traduction: la fonction ou variable 'b' n'est pas definie. CONCLUSION Nous venons de voir qu'il y a 3 phases dans la mise au point d'un programme. * Eliminer les erreurs de syntaxe (souvent des fautes de frappe) qui apparaissent lors de la compilation. * Eliminer les erreurs signalees par le programme lors de l'execution. Nous en avons vus plusieurs examples. * Une fois que le programme ``tourne'' sans afficher de message, il peut neanmoins subsister des erreurs cachees. Si dans une formule vous avez par inadvertance remplace un sinus par un cosinus, le programme ne va assurement pas protester mais le resultat du calcul sera incorrect. Pour des graphiques les anomalies de ce type seront en general plus facile a detecter que pour un programme de calcul purement numerique. ==================================================== SECTION 8: COMMENT NUMERISER UN MOTIF? Toute animation necessite des elements qu'il faut importer de l'exterieur. Pour le type d'animation que nous avons en vue, on peut citer: soldat a pied, cavalier, canon, paysan, moine, visages des principaux protagonistes, noyer, chataigner, et ainsi de suite. Sur Internet il n'est pas difficile de trouver des images correspondants a ces sujets. Cependant, on ne peut guere inclure telle quelle ces images dans l'animation, cela parce que la plupart des elements cites doivent faire l'objet d'une mise en mouvement chose pour laquelle il faut en disposer sous forme numerisee de facon a pouvoir effectuer sur ces elements des contractions, des rotations ou des changements d'expression. Par exemple, si on importe le visage d'un seigneur ou d'un general on voudra pouvoir modifier la forme de sa bouche ou de ses yeux. Nous employerons le terme de ``motif'' pour designer la forme numerisee d'un element importe dans l'animation. La question qui se pose est donc la suivante. Comment generer ces motifs d'une facon a la fois commode et rapide? La methode que nous proposons ci-dessous utilise une commande de PAW appelee VLOCATE. Nous verrons que l'utilisation de cette commande fournit un excellent exercice de programmation car elle fait appel a la fois au mode dit interactif (que nous avons peu vu jusqu'ici) et au mode macro. La methode sera expliquee sur la base d'un exemple concret, a savoir l'importation du portrait de Tintin. L'operation comporte quatre phases: generer les coordonnees des points, enregistrer ces donnees dans des fichiers, faire le graphique representant cette image, et enfin faire l'animation de ce visage. LA METHODE EN RACCOURCI PAR UN EXEMPLE SIMPLE (SEULEMENT 2 LIGNES) Nous commencons par expliquer les operations successives sur l'exemple d'un arbre qui ne comprend que 2 lignes: le tronc et les feuilles. Avec seulement 2 lignes, le plus commode est de faire toutes les operations en interactif. Lorsque le nombre de lignes devient plus important (dans le cas du portrait de Tintin on aura 8 lignes) il devient fastidieux de taper toutes les commandes en interactif. Dans ces cas il est plus commode de passer par la macro ANIM#MOTIF Supposons donc que votre transparent soit fixe sur le repere de la fenetre graphique de votre ordinateur (des indications plus detaillees sont donnees a ce sujet dans la section suivante). On donne ci-dessous les commandes a taper et les reponses de l'ordinateur. Elles sont aussi expliquees plus en detail dans la section suivante. Ici, pour une sorte de raccourci de la methode, nous voulons juste nous assurer que ca marche. Entre crochets ce sont des commentaires. A la place de 37 et 156 mettez les nombres correspondants a votre propre operation de ``clicage''. VLOCATE VX1 VY1 '+L*' 37 points have been hit [pour le tronc] IGSET PLCI 2 ; GRAPH 37 VX1 VY1 L [graphe de verification] IGSET PLCI 1 VE/WRITE VX1,VY1 'arbre1.motif' '2(F10.3)' [ouvrez le fichier arbre1.motif et verifiez qu'il est correct] VLOCATE VX2 VY2 '+L*' 156 points have been hit IGSET PLCI 2 ; GRAPH 156 VX2 VY2 L [graphe de verification] IGSET PLCI 1 VE/WRITE VX2,VY2 'arbre2.motif' '2(F10.3)' [ouvrez le fichier arbre2.motif et verifiez qu'il est correct] VE/CR TX1(37) R ; VE/CR TY1(37) R ; VE/READ TX1,TY1 'arbre1.motif' IGSET FAIS 1 ; IGSET FACI 1 ; FAREA 37 TX1 TY1 [par cette commande le tronc doit se colorer en noir] VE/CR TX2(156) R ; VE/CR TY2(156) R ; VE/READ TX2,TY2 'arbre2.motif' IGSET FACI 3 ; FAREA 156 TX2 TY2 [par cette commande le feuillage doit se colorer en vert] Par cette operation on a donc cree 2 fichiers qui contiennent les coordonnees de points permettant de recreer le motif initial. Autrement dit, on a numerise l'image de l'arbre. PHASE 1: GENERER LES COORDONNEES DES POINTS 1) Tout d'abord il faut trouver une image representant le motif souhaite. Pour trouver un portrait de Tintin nous avons utilise la fonction ``image'' de Google. Bien sur, nous aurions aussi pu utiliser une version papier des albums de Herge. 2) Ensuite, il s'agit de produire une copie papier de cette image ayant le format 21cm x 21cm. Ces dimensions sont celles d'un repere genere par la commande NULL 0 10 0 10 Ces dimensions correspondent a la taille maximum qu'il m'est possible d'obtenir sur mon propre ordinateur en dilatant la fenetre graphique au maximum. Il se peut que sur votre ordinateur ces dimensions ne soient pas les memes car elles sont fonction de la taille de l'ecran. Il y a donc lieu de remplacer ces dimensions par celles correspondant a votre cas. La taille voulue peut etre obtenue soit de facon informatique apres avoir scanne l'image (par exemple en utilisant convert) soit par la fonction reduction/agrandissement d'une photopieuse. C'est cette seconde methode que j'ai utilise avec un rapport d'agrandissement de l'ordre de 3. 3) En recouvrant l'image precedente d'un transparent on va en produire une version stylisee limitee a un certain nombre de lignes principales. Dans le cas du portrait de Tintin on a retenu 8 lignes: le pourtour du visage, les yeux, le nez, la bouche, les oreilles. Ce transparent sera ensuite appose sur l'ecran de l'ordinateur de telle facon que l'image soit contenue a l'interieur du repere. On est maintenant pret a utiliser VLOCATE 4) Avant de nous occuper de l'image, il est bon de se familiariser avec VLOCATE. En premier lieu on va placer deux points et verifier que VLOCATE les enregistre correctement. Pour commencer nous utiliserons la commande sous la forme suivante. VLOCATE VX1 VY1 'L*' Que fait-elle? Vous voyez qu'il y a 2 lignes de mire (cross-hair) perpendiculaires qui vous permettent de placer un point avec les coordonnees desirees. Grace a la souris placez les lignes de mire de facon a ce qu'elles se croisent au point (3,2), puis cliquez. Vous voyez apparaitre un asterisque au point voulu. Faites de meme au point (6,3). Pour indiquer a VLOCATE que vous ne souhaitez enregistrer que ces deux points, cliquez sur le bouton de droite de la souris. En principe les deux abscisses 3 et 6 ont ete enregistrees dans le vecteur VX1 et les deux ordonnees 2 et 3 dans le vecteur VY1. Pour vous en assurer imprimez les contenus de ces deux vecteurs avec la commande ANIM#SPRINT. Cette impression confirme que ces vecteurs sont bien de dimension 2 et contiennent en effet les bonnes valeurs. Le dialogue correspondant est donne ci-dessous. PAW > null 0 10 0 10 PAW > VLOCATE VX1 VY1 'L*' 2 points have been hit PAW > exec anim#sprint VX1 NCO(SVX1 )= 2 SVX1 2.999873 5.998091 PAW > exec anim#sprint Vy1 NCO(SVY1 )= 2 SVY1 2.012578 3.005322 5) Nous pouvons maintenant passer a l'enregistrement des lignes du transparent. Pour commencer il faut fixer le transparent sur l'ecran a l'aide de ruban adhesif. Il faut etre attentif au fait que si vous voulez par la suite remplir certaines zones du visage avec une couleur en utilisant FAREA il faut que le contour correspondant soit ferme. Certes, si le contour n'est pas ferme, FAREA se charge de le fermer en reliant le dernier point au premier. Mais si le dernier point est trop eloigne du premier cela se traduira par un segment de droite inesthetique. Pour eviter cela il est preferable que le dernier point soit relativement proche du premier. Avant de commencer il est bon de numeroter les differentes lignes que vous voulez numeriser. Pour le portrait de Tintin il y a en tout 8 lignes. 1: contour general du visage, 2 et 3: sourcils, 4 et 5: yeux, 6: nez, 7: bouche, 8: oreille droite. Pour numeriser la ligne 1 on fera: IGSET LWID 6 ; VLOCATE VX1 VY1 '+L*' La croix indique que l'on veut une croix pour le positionnement du curseur (et non pas la mire comme precedemment), le ``*'' indique qu'apres chaque clic on veut qu'un asterisque soit place, enfin le ``L'' precise que deux points successifs doivent etre relies par un segment de droite. Lorsque la ligne a ete entierement couverte on arrete l'enregistrement par un clic droit. Le nombre de points enregistres s'affiche dans la zone de commande, mettons que ce soit 108. A ce point, il est souhaitable de faire un test de verification par: IGSET PLCI 2 ; GRAPH 108 VX1 VY1 L En principe cette courbe en rouge doit se superposer au contour du transparent. PHASE 2: ENREGISTREMENT DES VECTEURS CREES SUR DES FICHIERS Un vecteur n'a qu'une existence fort ephemere. Il sera detruit si vous executez la commande VE/DE * Cet ordre vector/delete (delete=enlever, * signifie ``tous'') entraine la destruction de tous les vecteurs. Meme en l'absence d'une telle commande, tous les vecteurs seront detruits lorsque vous fermerez la session en tapant ``quit'' (=quitter). Autrement dit, il est crucial de preserver le contenu de VX1 et VY1 sur un support plus permanent. Pour cela nous allons ecrire le contenu de ces deux vecteurs sur un fichier par la commande suivante: VE/WRITE VX1,VY1 'tintin1.motif' '2(F10.4)' Imaginez VX1,VY1 comme formant un tableau de deux colonnes de nombres. Ce tableau aura 108 lignes. Par cet ordre, chaque ligne de ce tableau sera copiee sur le fichier tintin1.motif. Ce fichier sera un fichier texte, mais on a prefere remplacer l'extension .txt par l'extension .motif afin de pouvoir facilement reconnaitre ces fichiers (sous Linux on en fera la liste par ls *.motif). '2(F14.3)' constitue ce qu'on appelle le format d'ecriture. Ce format indique a PAW comment il doit ecrire les nombres. F10.4 signifie qu'on veut des nombres avec 4 chiffres derriere le point et le 10 signifie qu'au total le nombre occupera 10 espaces; le 2 qui apparait au debut du format dit qu'a chaque ligne on veut ecrire 2 nombres. Une fois cette commande executee vous pouvez verifier que parmi vos fichiers il y en a un qui s'appelle ``tintin1.motif''. En ouvrant ce fichier vous verrez qu'il contient en effet 108 lignes avec 2 nombres a chaque ligne. Vous pouvez maintenant recommencer la meme operation avec la seconde ligne. Pour cela entrez la commande: VLOCATE VX2 VY2 '+L*' En fait, par la suite pour aller plus vite, on pourra se dispenser d'enregistrer chaque paire de vecteurs apres l'avoir creee. Cette operation peut se faire globalement pour l'ensemble des 8 paires de vecteurs que vous allez creer. Pour cet enregistrement utilisez la macro ANIM#MOTIF (partie 1). Cette macro ne figurait pas dans le fichier anim.kumac initial. Il vous faut donc aller sur mon site http://www.lpthe.jussieu.fr/~roehner/teaching.html et telecharger la nouvelle version de anim.kumac. Voici quelques mots d'explication a propos de la partie 1 de ANIM#MOTIF * La commande d'ecriture est contenue dans la ligne suivante: FN=tintin[K].motif ; FMT=2(F10.4) ; VE/WRITE VX,VY [FN] [FMT] De facon generale la syntaxe de l'instruction d'ecriture est: VE/WRITE liste des vecteurs [nom du fichier sur lequel on veut ecrire] [format d'ecriture] Supposons que K=1; dans ce cas le fichier s'appelera tintin1.motif. * Vous pouvez voir qu'en plus des vecteurs VXi,VYi on enregistre aussi un vecteur NT qui contient les dimensions des 8 paires de vecteurs. Ces nombres sont necessaires au moment de lire les nombres sur les fichiers. En effet, il faudra donner a la commande de lecture le nombre de lignes qu'elle doit lire. On pourrait certes ouvrir les fichiers et pour chacun d'eux regarder quel est son nombre de lignes, mais grace a la lecture prealable des nombres contenus dans NT on pourra se dispenser de cette operation fastidieuse. PHASE 3: GRAPHIQUE DU MOTIF CREE Lorsque vous aurez execute la partie 1 de ANIM#MOTIF il sera bon de verifier que les fichiers voulus ont bien ete crees et que leur contenu a un aspect satisfaisant. Cela est fait dans la partie 2 de ANIM#MOTIF. Cette partie a ete decomposee en deux: d'abord la lecture des nombres sur les fichiers puis la realisation du graphique. Notez que les fichiers peuvent etre lus en format libre c'est-a-dire sans qu'il soit necessaire de specifier un format. Bien entendu, on pourrait aussi les lire avec le meme format qu'a l'ecriture. Bien entenu, le vrai test va consister a lire ces fichiers et a tracer les courbes correspondantes pour voir si elles sont bien conformes aux lignes du transparent. Dans les instructions de ANIM#LECM on pourra etre surpris par l'abondance des crochets. Cependant, cela n'a rien de difficile. Il suffit de se rappeler que toute lettre entre crochet est remplacee par sa valeur numerique definie dans les lignes anterieures. A titre d'exemple, pour K=1 ET N1=117: VE/CR X[K]([N[K]]) R -> VE/CR X1([N1]) R -> VE/CR X1(117) R Si les 8 courbes du graphique correspondent bien avec les lignes du transparent, cela confirme le succes de toute l'operation. Pour donner au visage un aspect plus realiste on peut le remplir d'une couleur judicieusement choisie. On peut faire de meme pour les yeux. Ces operations sont faites par la macro ANIM#GRAF dans sa partie M=1. Le graphique realise par cette macro est tout a fait specifique a ce motif. Certes le trace des lignes elles-meme sera identique pour chaque motif mais le travail de finition consistant a mettre une certaine couleur dans telle courbe et une autre dans une autre courbe sera specifique au motif considere. Ainsi pour chaque nouveau motif cree la macro ANIM#GRAF va recevoir une nouvelle partie correspondant a ce motif. Vous pouvez voir qu'en plus du motif tintin il y a deja d'autres motifs: un visage, une fourmi, une gabare. Cette liste est destinee a s'allonger de tous les motifs crees par vous ou par vos collegues. Dans le cours suivant on refera cette serie d'operations en utilisant des motifs que vous aurez choisi vous-memes. PHASE 4: ANIMATION DU VISAGE: STYLISATION DE LA BOUCHE Pour animer un visage on peut en premiere approximation se limiter aux trois elements suivants: * la bouche * les yeux * la couleur du visage De ces trois elements le plus important (mais aussi le plus difficile) est l'animation de la bouche. Dans la suite nous nous limiterons a cet aspect. Cette animation permet en particulier de faire parler le personnage. Si vous examinez differents visages de Tintin sur Internet vous verrez que la forme de la bouche peut en general se representer par deux demies-ellipses. Cela suggere la marche a suivre suivante. * Ecrire une macro creant deux demies-ellipses; ce sera ANIM#BOUCHE * Animer ces demies-ellipses * Integrer cette animation dans le visage de Tintin. Bien entendu cette animation pourra nous servir egalement pour animer les visages d'autres personnages. La principale difficulte qu'il a fallu surmonter dans la macro ANIM#BOUCHE est due au fait qu'il y a (du moins dans les bandes dessinees) deux variantes de forme de bouche: * une forme semi-ronde * une forme en croissant de lune horizontal. A vrai dire, il n'est pas necessaire de regarder de pres comment fonctionne cette macro. L'essentiel est de savoir l'utiliser. Pour cela on appliquera la regle suivante: * bouche semi-ronde -> BH>0 * bouche en croissant de lune -> BH<0 BH est le demi-petit axe de l'ellipse haute. Dans ANIM#TESTBOUCHE (Partie 1) vous pouvez vous familiariser avec l'utilisation de ANIM#BOUCHE. Essayez diverses valeurs de BH et voyez les formes de bouche obtenues. PHASE 5: ANIMATION DU VISAGE: FAIRE BOUGER LA BOUCHE On peut maintenant en venir aux parties 2 a 5 de ANIM#TESTBOUCHE ou on fait bouger la bouche. Pour cela on va faire varier le parametre BH qui controle la position de la levre superieure. Vous pouvez remarquer que les parties 2,3,4 sont presque identiques. Elles ne different que par la ligne ou on specifie comment on fait varier BH. On commence par une methode simple mais peu realiste et on finit par une methode plus compliquee mais plus realiste. Dans la methode simple (partie 2) on augmente BH regulierement, Imaginez quelqu'un qui baille! La seconde methode (partie 3) consiste a faire varier BH de facon periodique. Cela n'est bien sur pas tres realiste sauf a supposer que la personne repete plusieurs fois la meme chose ou baille de facon repetee. Pour obtenir des mouvements de la bouche plus irreguliers et qui correspondent plus a une elocution normale on va introduire des nombres tires au hasard. La cle de cette operation est le generateur de nombres aleatoires RNDM (abreviation de ``random'' qui signifie aleatoire) de PAW. Cette fonction genere des nombres compris dans l'intervalle (0,1). Cependant si on utilisait ces nombres de facon brute, le resultat serait tres peu realiste. En effet, les nombres successifs produits par RNDM ne sont pas lies entre eux. Cela peut etre: 0.147, 0.876, 0.675, 0.045. Or la position de la levre superieure change evidemment de facon continue et non par sauts. Pour remedier a ce probleme on utilise un generateur aleatoire plus elabore. C'est la macro ANIM#PAR1. Nous n'avons pas besoin d'entrer dans le detail de cette macro. La seule chose qu'il est bon de retenir est le role du premier parametre de cette macro. * Tout d'abord il doit etre compris entre 0 et 1. * Ensuite, plus il est proche de 0, plus le mouvement de la levre superieure sera saccade et se rapprochera de ce que donnerait RNDM tout seul. Au contraire, plus ce parametre est proche de 1, plus le mouvement sera regulier et se rapprochera du mouvement periodique vu precedemment. Vous pouvez faire divers essais pour le constater. La derniere etape consiste a re-integrer la bouche dans le visage de Tintin. Pour cela, on va d'abord dessiner le visage par ANIM#GRAFM mais sans la bouche. A cette fin il faut activer la ligne de ANIM#GRAFM qui contient un IF qui va empecher le dessin de la bouche. Si le resultat final ne vous parait pas vraiment satisfaisant il faut se souvenir qu'en general dans une animation on ne voit pas les visages de si pres. A une distance de quelques metres le visage apparaitra plus petit ce qui masquera en meme temps les imperfections. ============================================================== SECTION 9: METTRE EN SCENE UN MOTIF PAR EFFET DE REPETITION Maintenant que nous savons numeriser un motif, il faut se demander comment on peut s'en servir pour monter de facon a peu pres realiste une scene ou ce motif est repete plusieurs fois. Par exemple avec le motif ``arbre'' on peut composer une rangee d'arbres le long d'une route ou d'une riviere. Toutefois, ce genre d'images exige de respecter les regles de la perspective. Cela fera l'objet d'une section ulterieure. Pour l'instant nous voulons juste representer des images repetees d'un meme motif sans avoir a nous preoccuper d'effets de perspective. Pour cela le plus simple est de considerer une vue plongeante verticale. Essayons par exemple de representer une colonne de fourmis telle qu'on peut l'observer par une journee ensoleillee entre le nid et une source de nourriture. Pour cela reportez-vous a la macro ANIM#FOURMIS En partant de la representation d'une seule fourmi nous allons progressivement l'enrichir jusqu'a obtenir une image a peu pres realiste d'une colonne de fourmis. D'un point de vue pedagogique cet exercice va nous apprendre a utiliser et a combiner des macros pre-existantes. Celles-ci sont au nombre de 4: ANIM#LECM, ANIM#GRAFM, ANIM#MOTIFQ, ANIM#UNIAB Ces macros peuvent etre considerees comme des ``briques'', c'est-a-dire en termes plus academiques des modules fonctionnels, dont chacun a sa propre fonction et egalement ses propres regles d'utilisation qu'il nous faudra respecter. L'art de la programmation va consister a les combiner pour obtenir l'effet souhaite. Selon la facon dont ces modules ont ete ecrits, cela sera plus ou moins commode. Nous reviendrons sur ce point a la fin de la section. Quelles sont les fonctions de ces 4 macros? * ANIM#LECM lit les donnees necessaires pour la representation du motif. Pour le motif ``fourmi'' ces donnees sont contenues dans 11 paires de vecteurs Xi,Yi qui definissent le corps, les pattes et les antennes de la fourmi. * ANIM#GRAFM dessine la fourmi en suivant les donnees des Xi,Yi. Notez que ANIM#GRAFM ne founit pas le repere, il faudra donc le definir auparavant. * ANIM#MOTIFQ modifie les vecteurs Xi,Yi pour realiser 3 operations sur la figure initiale: un agrandissement ou une reduction definie par la variable Q, une rotation definie par l'angle TETA exprime en degres. Cet angle peut eventuellement etre negatif au sens du cercle trigonometrique (negatif signifie sens horaire). Enfin la macro transporte le centre du dessin au point defini par les coordonnees XP,YP. * ANIM#UNIAB fabrique une serie de nombres tires au hasard dans un intervalle donne. Dans la nature bien des choses (par exemple l'emplacement des plantes ou des arbres) ne sont pas parfaitement alignees mais presentent une certaine dose de desordre. Les nombres tires au hasard (aussi appeles nombres aleatoires) permettent de simuler ce ``desordre''. La macro se deroule en 6 etapes successives: A1,A2,A3,A4,B1,B2. Chacune de ces etapes est expliquee par les commentaires inseres dans la macro. Il faudra donc lire ces commentaires, puis activer ces 6 parties successivement. Une fois arrive au bout il est possible (et meme conseille) de choisir a votre propre convenance certains des parametres introduits dans la macro. Par exemple, vous pouvez augmenter le nombre de fourmis ou bien changer leur taille. A propos de la taille, il faut attirer l'attention sur le fait que si on diminue la taille il faut aussi diminuer l'epaisseur du trait des pattes et des antennes. Pour cela il faut aller dans la macro ANIM#GRAFM, descendre jusqu'au motif No 4, et changer IGSET LWID ``a la main''. Cela est malcommode et, en principe une macro doit etre ecrite pour ne pas avoir a faire ce genre d'interventions. Dans le cas present cela aurait pu etre evite si on avait mis l'epaisseur du trait comme argument supplementaire de ANIM#GRAFM. On aurait alors pu modifier ce parametre de l'exterieur sans avoir a ouvrir la macro. Pourquoi alors n'ai je pas mis cette largeur de trait en argument? La raison est que cela n'aurait pas resolu le probleme pour d'autres parties de ANIM#GRAFM. Par exemple le motif No 2 (dessin d'un visage) fait intervenir plusieurs epaisseurs de trait differentes. Autrement dit, en rajoutant juste une epaisseur de trait en argument on aurait alourdi l'utilisation de cette macro sans reel benefice puisque cela n'aurait resolu le probleme que pour un des motifs. Une autre solution aurait ete de definir une macro GRAF pour chaque motif. On aurait alors eu ANIM#GRAF1, ANIM#GRAF2, etc. Dans ce cas on aurait pu mettre pour chacune d'entre elles les arguments d'epaisseur de traits voulus. Mais la contrepartie aurait ete une complication du code puisqu'on aurait remplace une macro unique par une multitude de macros, chacune ayant ses propres arguments. J'ai insiste sur la discussion de ce point car il illustre bien les choix et dilemmes auxquels on est confronte lors de l'ecriture d'un code. Souvent au moment de choisir entre plusieurs solutions il n'est pas aise de deviner quelle sera en definitif le meilleur choix. Dans un sens tout depend des applications qui en seront faites par la suite. En somme, a ce niveau c'est plus une question d'intuition que d'analyse raisonnee. ANIMATION Ici nous avons cree une image statique montrant un groupe de fourmis. Que faudrait-il faire si on voulait montrer une seule fourmi en train de se deplacer de gauche a droite? Revenons pour cela a l'etape A4. Que se passera-t-il si au lieu de placer la commande NULL 0 10 0 10 avant la boucle DO on la met a l'interieur de la boucle? Dans ce cas, lors de chaque iteration, un nouveau repere sera trace si bien qu'on ne verra toujours sur l'ecran qu'une seule fourmi et celle-ci donnera l'impression de se deplacer de gauche a droite. Certes, avec seulement 15 images le film sera tres saccade. Pour obtenir un meilleur resultat il faut augmenter le nombre des images (par exemple NF=100) et introduire une temporisation comme on l'a deja fait dans un cours precedent. Cet exemple vous montre que dessiner une foule sur une place ou une seule personne se deplacant sur cette place est au fond presque la meme chose du point de vue du programme qu'il faut ecrire. ============================================================== SECTION 10: EFFETS DE PERSPECTIVE (SANS POINT DE FUITE) La representation en perspective permet a un dessin sur une feuille (donc a 2 dimensions) de donner l'illusion d'une realite a 3 dimensions. Mais une telle representation se fait toujours au prix de deformations. On a une situation similaire pour les representations du globe terrestre par une mappemonde plane: selon le type de representation ce seront les regions polaires ou les regions equatoriales qui seront deformees. Ici on va se limiter a deux exemples: * la perspective (sans point de fuite) fournie par la commande HI/PLOT * une perspective avec point de fuite sous la forme d'une rangee d'arbres qui est traitee dans la section suivante. UTILISATION DE HI/PLOT (p. 368-369 du manuel) Il s'agit d'une commande relativement complexe puisqu'elle comprend pas moins de 40 options differentes. Tout d'abord telechargez depuis mon site la derniere version du fichier ``anim.kumac'' ainsi que les fichiers test0.for et test.for MAISON EN FORME DE CUBE Le principe de l'operation est le suivant. Supposons qu'on veuille dessiner une maison qui a la forme d'un cube de cote 10; de plus on souhaite que la face inferieure de ce cube occupe la zone: 0 TEST0, par exemple: (2,3) -> 10 mais (11,3) -> 0 Le code va donner les regles permettant de calculer TEST0 pour chaque paire (X,Y). Dans le cas present la situation est simple car il n'y a que 2 possibilites: * si (X,Y) n'appartient pas a D, on doit avoir TEST0=0 * si (X,Y) appartient a D, on doir avoir TEST0=10 Donc, il va suffire de tester si oui ou non (X,Y) appartient a D. Pour cela, on utilise une regle de mathematique que vous avez du voir en classe de 3e qui dit que le signe d'une fonction du second y=x**2+b*x+c degre est positif pour x a l'exterieur des deux racines et negatif a l'interieur de cet intervalle. Bien entendu il nous faut faire ce test a la fois pour X et pour Y. TEST0 sera non nul seulement lorsqu'a la fois X ET Y seront contenus dans (0,10). On peut maintenant executer ANIM#TESTPLOT. Le cube qu'on obtient est bien conforme a ce qui etait souhaite. Nous voyons que les aretes du cube sont paralleles ce qui montre qu'il s'agit d'une perspective SANS point de fuite. Nous pouvons changer la direction d'observation. Celle-ci est definie par deux angles: * TET definit l'angle par rapport a l'horizontale: TET=0 correspond a une observation au ras du sol alors que TET=90 correspond a une observation a la verticale. Regardez ce que donnent ces deux choix. * PHI definit l'angle d'observation dans un plan horizontal. Par exemple, pour fixer les idees on peut dire que c'est un angle par rapport a la direction du nord geographique. Essayez par exemple PHI=45 et voyez le resultat. Les parties A2-A6 vont consister a explorer differentes options de la commande HI/PLOT. Tout d'abord executez la partie A2 ou on a remplace LEGO par P. Vous voyez un graphe (x,y) montrant la zone ou la fonction TEST0 est non nulle. Cette option peut etre utile pour s'assurer que la fonction qu'on a ecrite est bien correcte. Lorsqu'on veut utiliser HI/PLOT pour faire du dessin on souhaite se debarrasser des axes. Cela est realise dans A3 par les options choisies. Toutefois, vous voyez que sous le graphe il subsiste le nom TEST0 de la fonction qui definit l'histogramme. Pour s'en debarrasser il suffit de choisir comme couleur pour l'ecriture la couleur blanche. C'est ce qui est fait dans A4 par la commande IGSET TXCI 0 (0 correspond au blanc). Dans A5 on a remplace LEGO par LEGO3. Cela cree un effet de couleur associe a la hauteur. Ici les couleurs sont limitees aux couleurs de base correspondant aux indices allant de 0 a 8. Mais l'ordre dans lequel apparaissent les couleurs est 0,5,7,3,6,2,4,1. Dans l'interpretation ou le cube represente une maison ces couleurs ne sont guere utiles. Cependant il est possible de redefinir les couleurs ce qui permet davantage de se rapprocher de couleurs ``naturelles''. C'est ce qui est fait dans A6. On pourrait remplacer cette gradation de couleurs allant du bleu au rouge par une autre gamme. MAISONS DE FORMES PLUS REALISTES Jusqu'ici nous avons utilise une forme tres simple de maison. En changeant le code qui definit l'histogramme on peut definir des formes de maison plus realistes. C'est ce qui est fait dans la partie B ou on a remplace la fonction TEST0 par la fonction TEST. Dans TEST on a ecrit un code qui doit donner 3 maisons. Tout d'abord pour verifier leur emplacement au sol on utilise l'option TYP=P de B1. On voit qu'on a bien 3 maisons. Puis on peut passer a B2. Lancez d'abord l'execution avec LTYP=LEGO, puis avec LTYP=LEGO1. Vous voyez que LEGO1 rajoute un effet d'ombre qui est cense ameliorer l'effet ``3d''. Pour le cube cela etait moins visible du fait de la simplicite de la forme Puis on peut passer a B3. ====================================================== SECTION 11: EFFET DE PERSPECTIVE (AVEC POINT DE FUITE) Le type de perspective vue dans la section precedente convient pour la representation d'un objet ou d'un edifice. Si l'on veut donner un effet de perspective dans une scene de plus grande etendue comme par exemple un paysage ou la vue d'une ville, il convient d'utiliser une perspective avec ligne de fuite. L'exemple le plus simple de cette perspective est fourni par les rails de chemin de fer qui semblent se rapprocher a mesure qu'on s'eloigne de l'observateur et se rejoignent sur la ligne d'horizon. A titre d'illustration nous considererons un canal borde de deux ranges d'arbres. L'objectif parait simple mais vous allez voir qu'il n'en pose pas moins quelques difficultes non prevues au depart. Avant de commencer, il vous faut telecharger deux fichiers depuis mon site: (i) la derniere version du fichier anim.kumac (ii) le fichier motif.zip qui contient les fichiers de donnees necessaires pour creer les motifs ``arbre'' et ``gabare''. Une fois ce fichier telecharge sur votre ordinateur dans le meme repertoire que PAW, ouvrez le et verifiez que vous avez bien les fichiers arbre.motif, arbre1.motif, arbre2.motif gabare.motif, gabare1.motif,..., gabare4.motif Verifiez aussi que dans la macro ANIM#PERSPECTIVE toutes les parties sont desactivees sauf la partie 1A. CADRE Avant de planter les arbres il faut poser le cadre, c'est-a-dire le canal, le terrain de part et d'autre et le ciel au-dessus de la ligne d'horizon. Comme d'habitude commencez par telecharger depuis mon site, la derniere version du fichier anim.kumac. Puis, executez la partie no 1A de ANIM#PERSPEC. Vous constatez qu'elle fait le canal et le terrain mais pas le ciel. Le ciel est fait dans la partie 1B. Cependant avant de regarder 1B, pourriez-vous a titre d'exercice essayer d'ecrire vous-meme les instructions necessaires? Le ``ciel'' est delimitee par un rectangle et les coordonnees de deux des sommets de ce rectangle ont deja ete donnees dans la partie 1A. Il suffit donc de completer par les deux points qui manquent. PLANTER UN ARBRE Avant de planter plusieurs arbres, essayons de nous rappeler comment on en plante un. Le processus comporte 3 etapes: (i) Nous avons une sorte de bibliotheque de motifs dont les coordonnees sont contenues dans ANIM#LECM. Tout d'abord il faut donc reperer dans la liste donnee au debut de cette macro quel est le no de l'arbre et combien de paires de vecteurs comprend ce motif; ce nombre est egal a KM=2. Si M est le no du motif de l'arbre, en executant EXEC ANIM#LECM [M] on genere des vecteurs X1,Y1 et X2,Y2 qui donnent les coordonnees des points de l'arbre. (ii) Ensuite ANIM#MOTIFQ transforme ces vecteurs pour que l'arbre soit plante la ou vous voulez et avec la taille que vous voulez. (iii) Finalement, ANIM#GRAFM realise le dessin de l'arbre. Avant de commencer, il faut se poser une question cruciale: faut-il planter d'abord les arbres les plus eloignes ou les plus proches? La reponse est qu'il faut commencer par les arbres les plus eloignes. Si vous ne comprenez pas bien pourquoi, faites l'inverse et la raison vous apparaitra de suite. Pour planter un arbre pres de l'horizon, on choisit un point qui a pour abscisse 3 donc qui est bien pres de l'horizon s'il est situe sur le cote gauche du canal. Executez la partie 2A. vous constatez que l'arbre est beaucoup trop grand. Il faut donc le reduire en chosissant un rapport de reduction R approprie. Ceci est fait dans 2B, mais avant de passer a 2B essayez vous-meme par quelques tatonnements de voir quel valeur de R peut convenir. Avec le R de la partie 2B l'arbre a une taille raisonnable mais vous voyez qu'il est plante dans l'eau. Cela est du au fait que c'est le centre de l'arbre qui est place au point que vous avez choisi et non le pied de l'arbre. Cela oblige a faire un ajustement en augmentant legerement l'ordonnee YP; cela peut se faire en donnant a E une valeur positive. La encore, il faut tatonner pour trouver la bonne valeur. Cela est fait dans 2C. DEUX ARBRES Executez la partie 3A dans laquelle on plante 2 arbres. Vous observez que le premier arbre est bien correct mais que le second qui devrait etre plus grand du fait que R=0.10 (au lieu de 0.04 pour le premier), est en fait minuscule. A quoi cela est-il du? Il faut se souvenir que ANIM#MOTIFQ transforme les vecteurs qu'on lui met en entree. Ainsi la seconde instruction ANIM#MOTIFQ recoit en entree des vecteurs X[K],Y[K] qui sont deja reduits. Il va les reduire a nouveau et c'est ce qui donne ce second arbre qui est minuscule. Pour remedier a ce probleme il faut donner au second ANIM#MOTIFQ les vecteurs initiaux. A cet effet, on a eu soin de les stocker sous la forme XX[K],YY[K] apres la commande ANIM#LECM. En faisant preceder le second ANIM#MOTIFQ de DO K=1,[KM] ; SIGMA X[K]=XX[K] ; SIGMA Y[K]=YY[K] ; ENDDO le probleme sera resolu. C'est ce qui est fait dans 3B. TROIS ARBRES Supposons que les arbres soient regulierement espaces. Ou va-t-il falloir placer le 3e arbre? Il faut le placer de telle facon qu'une ligne passant par le sommet des arbres passe par le point de fuite. Cette regle relie donc la taille de l'arbre a sa position. La encore, il faut tatonner pour trouver les bonnes valeurs. Cela est fait dans la partie 4. SIX ARBRES Il est naturel de planter des arbres similaires sur l'autre cote du canal. Heureusement cela peut se faire sans effort car les tailles des arbres ainsi que leurs ordonnees seront les memes. Seule l'abscisse va changer et de plus d'une facon tres simple puisqu'il suffit de prendre le symetrique par rapport au milieu de la figure. Cela est fait dans la partie 5. Enfin on peut apporter deux touches de finition * La premiere consiste a enlever les chiffres des axes. Cela se fera en remplacant tout au debut de ANIM#PERSPECTIVE, l'instruction NULL [X1] [X2] [Y1] [Y2] par NULL [X1] [X2] [Y1] [Y2] AB * La second consiste a rajouter une gabare, c'est-a-dire un bateau a fond plat muni d'une voile et utilise pour le transport de marchandises telles que le bois pour la tonnelerie ou des bariques de vin. C'est ce qui est fait dans la partie 6. Si vous executez 6 tout seul vous n'aurez que la gabare sans les arbres. Pour avoir a la fois les arbres et la gabare il faut executer a la fois 5 et 6. CONCLUSION DE CETTE PARTIE Le travail qui precede a demande des tatonnements et ajustements quelque peu fastidieux. Bien entendu, on souhaiterait en faire l'economie en ``automatisant'' le processus. Ce n'est pas chose facile cependant. Il faut en effet se souvenir que dans le cas general il y a, non pas un seul, mais 3 points de fuite. Par contre, il serait facile de definir une macro ANIM#GRAFMB qui placerait le pied de l'arbre (et non pas son centre) au point considere. Cela eviterait au moins une partie des tatonnements precedents. ======================================================= SECTION 12: FABRICATION D'UN FICHIER jpg LES UNIVERS WINDOWS ET LINUX Pour mieux comprendre la distinction Linux/Windows faite dans cette section, il convient de commencer par une remarque preliminaire a ce propos. Sur l'ensemble de la planete les ordinateurs se partagent entre deux mondes: Windows et Linux. Windows est le systeme d'exploitation propose par la societe americaine Microsoft. Linux (appele egalement Unix) est un langage de programmation (ou plutot une famille de langages) qui a servi a mettre au point des systemes d'exploitation differents de Windows. Ces systemes furent developpes principalement aux Etats-Unis dans la decennie 1970-1980. Ces systems d'exploitation sont specialement aptes a faire communiquer les ordinateurs entre eux. Pour cette raison la plupart des serveurs utilisent Linux. Les differences essentielles entre ces deux mondes peuvent etre resumes comme suit. * Les logiciels Unix et Linux sont ouverts et libres. Ouvert signifie qu'on peut connaitre le code correspondant et qu'on peut aussi le modifier ou le perfectionner. Libre signifie qu'on peut les telecharger gratuitement. * Linux couvre de l'ordre de 5% des ordinateurs alors que Windows couvre les 95% restants. On peut se demander pourquoi un systeme libre et gratuit ne couvre que 5% du marche. Il y a sans doute de multiples raisons a cela mais une raison importante est qu'il y a environ 30 ans installer un systeme Linux demandait une reelle competence informatique. Depuis cette epoque lointaine Linux est devenu plus facile a utiliser mais, une fois que le marche fut partage et les habitudes prises la situation resta en quelque sorte gelee. La version Windows de PAW que vous avez sur vos ordinateurs fonctionne sans accroc. Helas, il n'en est pas toujours ainsi. Des logiciels qui ont ete concus pour un environnement Linux peuvent ne marcher que de facon partielle dans un environnement Windows. C'est malheureusement ce qui a l'air de se produire pour ``convert'' comme on va le voir dans la suite. FICHIERS POSTSCRIPT POUR REPRESENTER DES IMAGES PAW produit des fichiers postscript des graphiques que vous affichez a l'ecran. Postscript est un langage de programmation dedie aux images. Vous pouvez vous faire une idee des instructions de ce langage en ouvrant le fichier paw.ps. Ce langage est en particulier utilise par les imprimantes laser. La visualisation d'un dessin fait en postscript peut se faire par un logiciel appele ``ghostview''. Bien que ce soit un logiciel libre et disponible aussi bien en version Linux qu'en version Windows, il n'est pas souvent installe sur des ordinateurs fonctionnant sous Windows. AUTRES FORMATS POUR REPRESENTER DES IMAGES Autrement dit, si nous voulons pouvoir envoyer les images ou les films que nous realisons ici a des personnes appartenant a l'univers Windows il nous faut convertir nos fichiers en un format lisible sous Windows. Des formats communement utilises sont les format jpeg (ou jpg), gif ou avi. * JPEG qui signifie ``Joint Photographic Experts Group'' est une norme internationale initialement mise au point par la societe americaine IBM. Nous nous en servirons pour les images fixes. * GIF qui signifie ``Graphics Interchange Format''. Par rapport a JPEG, GIF a l'avantage de pouvoir representer des images mobiles c'est-a-dire des animations. * Le format AVI (``Audio Video Interleave'' c'est-a-dire ``Imbrication Audio Video'') a l'avantage, comme son nom l'indique, de pouvoir associer sur un meme fichier son et image. CONVERSIONS Le cheminement que nous souhaitons faire peut se schematiser de la facon suivante: postscript -> jpg -> film gif -> film avi (image + son) Pour realiser ces conversions il existe quantite de logiciels gratuits et telechargeable. Le logiciel ``convert'' que nous nous proposons d'utiliser est l'un d'eux. Cependant, comme nous l'avons deja dit son utilisation sous Windows pose quelques problemes. Si vous avez deja telecharge ``convert'' sur votre ordinateur la commande dont vous avez besoin pour passer de postscript a jpg est tres simple: convert paw.ps paw.jpg Si, pour une raison ou une autre, cela ne marche pas, il existe une autre possibilite qui est de faire la conversion en ligne sur un site offrant ce service. Tel est le cas du site suivant: http://image.online-convert.com/fr/convertir-en-jpg Vous cliquez sur ``browse'' (feuilleter) et vous indiquez le fichier a convertir. Puis il suffit de cliquer sur le bouton ``Convertir le fichier''. Une fois la conversion effectuee on rapatrie le fichier paw.jpg produit. Ce procede peut convenir pour convertir un petit nombre d'images. Il ne peut convenir pour produire les centaines d'images necessaires pour faire une animation. SOLUTIONS POSSIBLES POUR LA CONVERSION ps -> jpg A priori, il y a plusieurs solutions possibles pour la conversion de paquets de fichiers ps. La solution la plus simple consiste a utiliser la commande: convert 'paw%d.ps[1-110]' 'paw%d.jpg[1-110]' Cette commande va convertir les 110 fichiers paw1.ps,...,paw110.ps en fichiers jpg. Helas, pour une raison inconnue, cette commande ne marche pas sur la version Windows de convert que nous avons telechargee. On peut noter qu'elle ne marche pas non plus sur le site du centre de calcul de l'IN2P3. Le fait qu'elle marche sur le site lpthe.jussieu.fr est peut-etre du au fait que la version de convert qui y est disponible est plus recente. Il existe une autre commande de traitement groupee qui, l'experience le montre, marche sur le ``convert'' de Windows; il s'agit de la commande: mogrify -format jpg paw*.ps Cette commande va transformer tous les fichiers paw*.jpg se trouvant dans le repertoire en fichiers jpg portant le meme nom. Le terme anglais ``mogrify'' (aussi ``transmogrify'') signifie changer la forme de quelque chose. Lorsque la commande de traitement groupee ne marche pas la solution de remplacement est de faire une boucle sur la commande de traitement individuelle. Sous LINUX cela ne pose pas de probleme car les commandes de ``convert'' sont compatibles avec les commandes LINUX par exemple sous la forme du langage ``bash'. Remarque: Le terme ``bash'' est un acronyme de ``Bourne Again Shell ''. ``Bourne'' est le nom de Steven Bourne qui a developpe ce type de ``shell'' a la fin des annees 1970s. Un ``shell'' (shell=coquille, mais une traduction plus suggestive serait interpreteur ou encore langage de programmation) est une interface entre les commandes de l'utilisateur et le systeme d'exploitation UNIX. L'expression ``Bourne again shell'' est sans doute un jeu de mot sur ``Born again shell''. http://cygwin.com/packages/bash/ Index of /packages/bash Parent Directory bash-4.1.10-4 bash-4.1.10-4-src Apache Server at cygwin.com Port 80 ======================================================= SECTION 13: REALISATION D'UN FILM: CAVALIERS SE RAPPROCHANT Pour cette section, pour representer un groupe de cavaliers qui se rapprochent de l'observateur, nous utiliserons les principes de la perspective avec point de fuite deja vus dans la section 11. Si les principes sont les memes, leur application pose neanmoins quelques problemes nouveaux comme nous allons le voir. Pour commencer, il faut comme d'habitude telecharger depuis mon site les fichiers anim.kumac et motif.zip. Le premier comprend la macro ANIM#CAVALIERS dont nous allons nous occuper dans cette section. Le second comprend les fichiers qui permettent de dessiner le cavalier utilise dans cette section. Une fois que vous aurez ouvert la boite zip vous trouverez des fichiers dont le nom commence par caval. Il y a d'abord le fichier caval.motif qui contient les dimensions des vecteurs decrivant les lignes composant le motif. Parmi les fichiers caval1.motif, caval2.motif,... seuls les 15 premiers nous serviront. DECOR La premiere etape (partie no 1) consiste a creer le decor de la scene. Cela est fait par la macro ANIM#DECORCAV. Cette macro ne fait que reprendre les elements deja introduits dans la partie 1A+1B de ANIM#PERSPECTIVE avec la difference que ce qui etait un canal devient ici une route en faisant un changement de sa couleur. UN SEUL CAVALIER La 2e etape consiste a verifier que tout se passe bien pour le dessin du cavalier. Rappelons les 3 etapes (i) Lire les coodonnees par la macro ANIM#LECM qui cree les vecteurs Xk,Yk. (ii) Transformation de ces vecteurs par la macro ANIM#MOTIFQ (iii) Dessin du cavalier au lieu choisi. Dans cette partie nous n'avons pas essaye de mettre des couleurs differentes aux differentes parties du cavalier car nous voulons juste verifier qu'il n'y a pas de probleme. UNE RANGEE DE 13 CAVALIERS L'etape 3 consiste a placer 13 cavaliers sur une rangee juste sous la ligne d'horizon c'est-a-dire tres loin de l'observateur. Il faut donc faire une boucle de 1 a 13 pour placer chaque cavalier avec une abscisse legerement decalee par rapport a ses voisins. Cela se fait par l'instruction: SIGMA XC=ARRAY([N],[XA]#[XB]) ou [XA] et [XB] sont les 2 abscisses extremes de la ligne. Ici XA=3.5-0.5=3 et XB=3.5+0.5=4. Observez que nous ecrivons ces valeurs sous une forme qui depend de la largeur ``LA'' de la rangee. De cette facon l'ecriture sera facile a etendre aux cas ulterieurs ou la largeur de la rangee sera variable. Le choix des couleurs est un peu plus difficile. En fait, il s'agit plutot d'un non-choix car nous allons prendre des couleurs au hasard. Le but est d'avoir des cavaliers ayant des couleurs differentes afin de donner une impression de diversite. A ce stade nous ne nous inquieterons pas de ce que certains chevaux soient verts ou rouges. Le principe de ce choix au hasard est simple. Nous tirons un nombre au hasard entre 1 et 7 par la macro ANIM#UNIAB; mettons que ce soit 4.23. Puis nous prenons sa partie entiere, soit 4 ce qui correspond au bleu. Nous faisons cela pour les 15 parties d'un cavalier, puis nous recommencons la meme operation pour les cavaliers suivants. De cette facon tous les cavaliers seront differents. 3 RANGEES DE 13 CAVALIERS Dans la partie 4 nous allons placer 3 rangees de cavaliers. C'est l'etape-cle en ce sens que le passage de cette phase a celle du film ne demandera que peu de changements. Si nous repetons la partie 3 en rajoutant juste une boucle sur permettanr de changer l'ordonnee de chaque rangee on obtient le resultat produit par la partie (4A). On voit que ce n'est pas satisfaisant car changer l'ordonnee signifie rapprocher les cavaliers et donc il faut aussi changer leur taille. Changer la taille signifie non seulement augmenter la taille de chaque cavalier mais aussi augmenter leur espacement ce qui se fera en changeant la largeur de la rangee. Cela est fait dans la partie (4B). La partie (4B) produit certes 3 rangees de tailles raisonnables mais comme elles sont sur le meme graphique elles se chevauchent si bien qu'on ne voit rien de bien net. Le remede est simple. Pour chaque rangee il suffit de recreer un graphique avec le meme decor. Cela se fera en appelant ANIM#DECORCAV non plus selement au debut mais au debut de chaque nouvelle rangee. On cree ainsi dans la partie (4C) une image par rangee. CREATION DES FICHIERS POSTSCRIPT Si nous voulons faire un film il nous faut fabriquer des fichiers correspondants a chaque image. Cela se fait (voir la partie 4D) a l'aide des instructions suivantes: FORTRAN/FILE 66 paw1.ps ; METAFILE 66 -113 .... CLOSE 66 La premiere instruction ouvre un fichier en lui assignant un numero (ici 66) et un nom (ici paw1.ps). Le numero peut etre choisi entre 1 et 128. PAW ne sait creer que des fichiers postscript. L'instruction METAFILE 66 -113 donne des precisions sur l'image a creer. Les 1,1 indiquent qu'il n'y aura qu'un seul graphique par ligne et un seul graphique par colonne. Le 3 donne le type du fichier. Ici un fichier sans bord blanc autour et qui pourra etre introduit dans un autre document car il possede une ``BoundingBox'' (c'est-a-dire une boite donnant les dimensions du dessin). Cette ``BoundingBox'' est indiquee a la seconde ligne du fichier paw.ps. Si on change les dimensions indiquee dans cette instruction cela changera la taille du dessin. Les points avant CLOSE 66 indiquent que dans cet emplacement on trouve les instructions definissant le dessin. Grace a ces instructions on produira les 3 fichiers postscript souhaites. Vous pouvez les regarder en les ouvrant a l'aide d'un editeur de texte. Les imprimantes dites postscript comprennent ce language et c'est cela qui permet d'obtenir un dessin sur une feuille de papier. FILM Avant de pouvoir produire un film, il faut d'abord transformer ces images en format jpg comme cela a ete dit a la fin de la section precedente. Ensuite le film sera obtenu en tapant dans la fenetre de commande du logiciel ``convert'' l'instruction suivante: convert -delay 100 paw*.ps -loop 1 caval.gif C'est le fichier caval.gif qui constitue le film. Ici il ne contient que 3 images. 100 est l'intervalle de temps (exprime en centiemes de seconde) entre deux images. -loop 1 indique qu'on veut repeter le film 1 fois. ========================================================== SECTION 14: ENTREE D'UNE TROUPE DE CAVALIERS A BEAULIEU Tout d'abord je vous montrerai les images obtenues aux differentes etapes et je vous expliquerai le principe de la methode. Une des nouveautes consiste dans le fait que les differents motifs (arbres, chapelle, cavaliers, ...) doivent etre places a des endroits precis. Comment realiser ces placements sans avoir a trop tatonner? La partie pratique comporte les etapes suivantes. ETAPE 1: Telechargez les fichiers anim.kumac et motif.zip et ouvrez ce dernier dans le repertoire ou vous executerez PAW La macro qui nous occupera aujourd'hui est ANIM#ENTREE. ETAPE 2: Verifiez que seule la section 1A de ANIM#ENTREE est activee. Executez en faisant: EXEC ANIM En principe vous devez obtenir un dessin avec riviere, route, colline, soleil mais sans d'autres elements. L'activation de la section 1B va planter des arbres. L'activation de la section 1C va mettre deux gabares sur la riviere. L'activation de la section 1D va faire apparaitre le pont, les deux tourelles et la chapelle qui ont ete numerises par nos camarades Nathalie et Sylvia. ETAPE 3 Avant d'executer la section 2A assurez-vous que le parametre G qui est tout au debut est bien egal a 1 et non a 0. Lorsque ce parametre vaut 0 on execute cette partie mais sans faire le dessin. Vous allez comprendre pourquoi a l'etape suivante. Il s'agit maintenant de placer les 13 cavaliers. Comment a-t-on procede? On a d'abord cree le cavalier de tete et la premiere rangee de 3. Cela a du se faire ``a la main'' en tatonnant un peu. Puis les rangees suivantes ont ete obtenues par translation de la premiere rangee. La section 2B est presque identique a la section 2A. On a simplement translate tout le groupe de l'entree du pont vers sa sortie. ETAPE 4 Pour executer la section 3, faites d'abord G=0 dans 2A et 2B. Comment allons-nous faire mouvoir les cavaliers entre ces deux positions? Au lycee vous avez sans doute appris l'operation mathematique qui s'appelle interpolation. Interpoler entre 2 et 3 signifie qu'on va definir des nombres regulierement repartis entre 2 et 3, comme par exemple: 2.0 2.5 3.0 ou 2.0 2.2 2.4 2.6 2.8 3.0. Nous allons faire de meme avec les positions des cavaliers. C'est pour cette raison que nous avons commence par faire les deux positions extremes. Les positions des cavaliers a l'entree sont enregistrees dans le tableau P1, celles a la sortie dans le tableau P2. C'est pour cette raison qu'il nous faut executer 2A et 2B mais sans faire le dessin des cavaliers puisque celui-ci se fera dans la section 3. C'est la raison d'etre du parametre G que nous mettons maintenant egal a 0. ETAPE 5 Pour executer la partie 4 faire EXEC ANIM#ENTREE (et non EXEC#ANIM) Que faut-il changer pour produire les images pour le film? * Tout d'abord les groupes successifs de cavaliers doivent aller sur des graphiques differents et non sur le meme. Pour cela il faut a chaque image recreer tout le decor. Cela se fait par la macro ANIM#DECORCAV. * Ensuite il faut creer autant de fichiers postscript qu'il y a d'images. Auparavant on ne creait qu'un seul fichier postscript qui etait ouvert tout au debut de ANIM. Ici ces fichiers seront ouverts par la commande: FORTRAN/FILE 66 ent[J].ps ; META 66 -113 Les fichiers postscript crees s'appelleront ent1.ps, ent2.ps, ... ETAPE 6: Realisation du film Une fois les fichiers postscript crees, il faut les transformer en fichiers jpg par la commande: mogrify -format jpg ent*.ps Puis le fichier de l'animation sera cree par: convert -delay 20 ent*.jpg -loop 1 ent.gif ou encore (pour moins de 100 fichiers): convert -delay 20 ent?.jpg ent??.jpg -loop 1 ent.gif REMERCIEMENTS. Mes remerciements vont tout d'abord a l'Association Philotechnique qui a inclus ce cours dans la liste (deja longue) des cours qu'elle propose. Je souhaite aussi exprimer ma gratitude a Mr. Olivier Couet du CERN qui fut un des quatre createurs de PAW. Depuis pres de 20 ans ses conseils m'ont eclaire sur bien des points particuliers de PAW qui me posaient probleme. Je voudrais aussi remercier Mrs. Pascal Calvat de l'IN2P3 et Serge Jacob, administrateur informatique pour l'Association Philotechnique, grace a qui la version Windows de PAW a pu etre installee sur les ordinateurs de l'association. ==================================================== LEXIQUE ANGLAIS-FRANCAIS DES COMMANDES DE PAW ARRAY([N],0#1) -> array signifie ici ``tableau de nombres'' DO I=1,10 -> Faire varier la variable I de 1 a 10. La boucle se termine par: ENDDO -> Fin de la boucle DO FAREA -> fill area -> definit une aire en vue de la remplir de couleur FACI -> fill area color index -> choix de la couleur pour le remplissage d'un domaine FAIS -> fill area interior style -> choix du type de remplissage GOTO 1 -> Aller a la ligne 1 (reperee par 1:) GRAPH [N] XT YT L -> faire le graphe des [N] points (XT,YT) en reliant les points successifs par des segments de droite IF [A]=[B] THEN -> Si [A]=[B] alors faire la suite. Le IF se termine par ENDIF -> fin de la sequence SI LTYP -> line type -> type du trait (plein, pointille, etc) LWID -> line width -> epaisseur du trait N=$SIGMA(NCO(V)) -> number of components -> nombre de composantes de V PMCI -> polymarker color index -> donner une couleur (definie par un nombre) aux marqueurs (rond, carre, etc) PLCI -> polyline color index -> donner une couleur (definie par un nombre) aux lignes (pleine, pointillee, mixte, etc) RETURN -> Revenir a la macro appelante TRACE ON WAIT -> ``trace on'' signifie afficher les commandes successives. ``Wait'' signifie qu'apres chaque affichage de ligne le programme attend une confirmation pour passer a la ligne suivante TRACE OFF -> supprimer l'affichage des commandes successives VE/CR -> Vector/create -> creer un vecteur VE/DE VM -> Vector/delete -> supprimer le vecteur VM VE/READ -> lire un vecteur sur un fichier VE/WRITE -> ecrire un vecteur sur un fichier N=$VLEN(.) -> V length -> longueur effective (sans les 0) de V WAIT -> attendre