• Aucun résultat trouvé

2 Les dessinateurs

N/A
N/A
Protected

Academic year: 2022

Partager "2 Les dessinateurs"

Copied!
6
0
0

Texte intégral

(1)

IFT2030 – Travail pratique #1 – 02/02/06

CONSTRUCTION DE DESSINS AVEC SCHEME Marc Feeley

Le TP1 consiste `a ´ecrire une biblioth`eque de fonctions qui offre des primitives graphiques permettant de construire des dessins. Vous n’avez donc pas `a ´ecrire un programme Scheme complet. Il faut supposer que l’utilisateur de votre biblioth`eque est un concepteur graphique qui d´esire produire des dessins en composant les fonctions de votre biblioth`eque, soit interactivement, soit en utilisant Scheme pour ´ecrire des “scripts”

construisant des dessins complexes.

Pour ce travail vous devez utiliser uniquement le sous-ensemble fonctionnel de Scheme (en particulier, vous ne devez pas utiliser la forme-sp´eciale “set!” dans votre programme). Le but du travail ´etant de vous faire pratiquer les concepts de programmation fonctionnelle, n’h´esitez pas `a utiliser des fonctions d’ordre sup´erieur lorsque c’est appropri´e. L’´el´egance de vos fonctions est un facteur important dans l’´evaluation de ce travail.

1 Interface graphique

Pour ce travail, un “dessin” correspond `a un ensemble de segments de droite dans le plan X-Y. Un segment a un point de d´epart et un point d’arriv´ee. Pour repr´esenter les segments nous utiliserons ces d´efinitions:

(define vect cons) (define vect-x car) (define vect-y cdr)

(define segm (lambda (depart arrivee) (list ’segm depart arrivee))) (define segm-depart cadr)

(define segm-arrivee caddr)

La fonction “vect” construit un vecteur 2D, c’est-`a-dire une coordonn´ee sur le plan X-Y. La fonc- tion “segm” construit un segment `a partir de deux vecteurs (le point de d´epart et le point d’arriv´ee).

Ainsi, l’appel (segm (vect 5 7) (vect 0 0)) retourne la repr´esentation du segment de droite entre le point (5,7) et l’origine. Les autres fonctions permettent d’acc´eder aux composantes d’un vecteur et d’un segment. Evitez d’utiliser directement les fonctions “car” et “cdr” pour acc´eder `a ces in-´ formations car cela empˆecherait un changement futur de la repr´esentation. Ces d´efinitions, ainsi que d’autres qui vous seront utiles pour ce travail (comme “foldr” et “foldl”), se trouvent dans le fichier

“~dift2030/tp1/tp1-def.scm”.

Lorsque le fichier “~dift2030/tp1/tp1-def.scm” est charg´e, une fenˆetre carr´ee est cr´e´ee `a l’´ecran pour y afficher les dessins. Pour afficher un dessin dans cette fenˆetre, on peut faire appel `a la fonction

“afficher”. L’argument unique de la fonction “afficher” est la liste des segments `a tracer. La fenˆetre utilise un syst`eme de coordonn´ees qui place (1,1) en haut `a droite et (-1,-1) en bas `a gauche. Ainsi, l’appel

(afficher (list (segm (vect -1/2 1) (vect 1/2 1)) (segm (vect 1/2 1) (vect 0 -1))))

va afficher deux segments qui forment le chiffre 7 dans la fenˆetre comme ceci:

(2)

2 Les dessinateurs

Pour produire un dessin nous utiliserons le principe g´en´eral suivant. Tout dessin est d´ecompos´e logiquement en sous-dessins ind´ependants. Chaque sous-dessin est `a son tour d´ecompos´e jusqu’`a ce qu’on obtienne des dessins suffisamment simples (des dessins “primitifs”).

Une repr´esentation fonctionnelle est utilis´ee pour repr´esenter des dessins “normalis´es”. Un “dessina- teur” est une fonction qui, lorsqu’elle est appell´ee, produit un dessin “concret” comme r´esultat (une liste de segments dans le syst`eme de coordonn´ees de la fenˆetre d’affichage). Un dessinateur repr´esente un dessin dans un syst`eme de coordonn´ees normalis´e, c’est-`a-dire un dessin dans un cadre ou les axes X et Y vont de -1 `a 1. Pour convertir ces coordonn´ees normalis´ees en coordonn´ees de la fenˆetre d’affichage, on utilise une fonction de transformation de coordonn´ees. L’argument unique d’un dessinateur est une fonction de trans- formation qui sp´ecifie la correspondance entre le syst`eme normalis´e du dessinateur et la fenˆetre d’affichage.

En quelque sorte, la fonction de transformation indique au dessinateur comment placer et ´etirer son dessin pour le dessiner dans la fenˆetre.

Par exemple, voici quatre dessins normalis´es. Les lignes pointill´ees ne font pas partie du dessin.

(−1,−1)

(1,1)

ell

(−1,−1)

(1,1)

losange

(−1,−1)

(1,1)

triangle

(−1,−1)

(1,1)

vide

Le dessinateur pour le premier dessin normalis´e (le “L”) pourrait ˆetre d´efini comme suit:

(define ell

(lambda (transf)

(list (segm (transf (vect -1/2 -1)) (transf (vect -1/2 1))) (segm (transf (vect -1/2 -1)) (transf (vect 1/2 -1))))))

Ici, chaque point dans le syst`eme normalis´e est transform´e avec un appel `a “transf”, la fonction de transformation.

La d´efinition suivante (qui se trouve dans le fichier “tp1-def.scm”) est utile pour visualiser un dessi- nateur `a l’´ecran:

(3)

(define dessiner

(lambda (dessinateur)

(afficher (dessinateur (lambda (v) v)))))

L’appel(dessiner ell)affiche le dessin du “L” `a l’´ecran. Ici le dessinateur “ell” est appel´e avec une fonction de transformation qui retourne son argument inchang´e.

3 Travail demand´ e

Vous devez ´ecrire les fonctions sp´ecifi´ees dans les sections 3.1, 3.2, et 3.3. Dans tous les cas, vos fonctions doivent se comporter de la mˆeme fa¸con que le mod`ele qui vous est fourni et qui peut ˆetre charg´e en

´evaluant (load "~dift2030/tp1/modele"). Remarquez qu’avant d’utiliser le mod`ele il faut avoir fait (load "~dift2030/tp1/tp1-def"). Par exemple:

% ~dift2030/bin/gsi

Gambit Version 4.0 beta 17

> (load "~dift2030/tp1/tp1-def")

> (load "~dift2030/tp1/modele")

> (dessiner ell)

3.1 Primitives de cr´eation de dessinateurs

Les fonctions dans cette section sont les outils de base pour cr´eer des dessinateurs et les composer. Les sections 3.2 et 3.3 utiliseront ces fonctions pour produire des dessins plus complexes.

3.1.1 (ligne depart arrivee)

Le dessinateur produit par cette fonction repr´esente une ligne qui s’´etend d’un point de d´epart `a un point d’arriv´ee. Plus pr´ecis´ement le dessin est l’ensemble de tous les points (x, y) se trouvant sur la ligne s´eparant les deux coordonn´ees. Puisque la fonction de transformation est possiblement non-lin´eaire (voir la fonction

“loupe”) cet ensemble de points apr`es transformation peut ˆetre une courbe. Pour approximer cette courbe vous devez d´ecomposer la ligne en plusieurs petits segments grˆace `a l’algorithme r´ecursif suivant: soitT la fonction de transformation,D et A les points de d´epart et d’arriv´ee, et M le point sur la ligne D–A qui est ´equidistant de D etA. Si la distance entre T(D) et T(A) est plus petite que 1/10 alors on a un seul segment deT(D) `aT(A), sinon on a l’union des segments de(ligne D M)et(ligne M A).

3.1.2 (parcours->dessinateur parcours)

L’argument unique de cette fonction, “parcours”, est une liste de points normalis´es. Le r´esultat de la fonction est un dessinateur qui repr´esente le dessin normalis´e contenant une ligne (au sens de la fonction

“ligne” ci-dessus) entre chaque point et le suivant dans la liste. `A l’aide de cette fonction on peut d´efinir les dessinateurs “ell” et “vide” avec:

(define ell

(parcours->dessinateur

(list (vect -1/2 1) (vect -1/2 -1) (vect 1/2 -1))))

(4)

(define vide (parcours->dessinateur ’()))

3.1.3 (translation deplacement-x deplacement-y dessinateur) et (rotation theta dessinateur) et (reduction facteur-x facteur-y dessinateur) et (loupe facteur dessinateur)

Ces fonctions retournent un dessinateur qui repr´esente le dessin d’un autre dessinateur transform´e par une translation, rotation, r´eduction, ou d´eformation de “loupe”. Dans le cas de “superposition”, le dessin est d´eplac´e sur l’axe X et Y d’une valeur de “deplacement-x” et “deplacement-y” respectivement. Dans le cas de “rotation”, le dessin subit une rotation d’un angle “theta” (en degr´es) dans le sens horaire (le dessin est pivot´e autour de l’origine). Dans le cas de “reduction”, le dessin est ´etir´e d’un facteur de

“facteur-x” sur l’axe X et “facteur-y” sur l’axe Y (l’origine reste `a sa place). Dans le cas de “loupe”, le dessin est d´eform´e non-lin´eairement pour donner un effet de “loupe”. Voici quelques exemples:

(−1,−1)

(1,1)

(translation 1/2 1/10 ell)

(−1,−1)

(1,1)

(rotation 30 ell)

(−1,−1)

(1,1)

(reduction 1/2 3/4 ell)

(−1,−1)

(1,1)

(loupe 1/2 triangle)

La formule suivante est utile pour faire une rotation de theta (en radians):

x0=x∗cos(theta) +y∗sin(theta) y0 =y∗cos(theta)−x∗sin(theta)

L’effet de loupe s’obtient avec la formulex0 =x∗m ety0 =y∗m, o`u m= 1+f acteur1+f acteur∗(x2+y2).

3.1.4 (superposition dessinateur1 dessinateur2) et (pile prop dessinateur1 dessinateur2) et (cote-a-cote prop dessinateur1 dessinateur2)

Ces fonctions retournent un dessinateur qui repr´esente la combinaison des dessins repr´esent´es par les deux dessinateurs “dessinateur1” et “dessinateur2”. Dans le cas de “superpose”, les deux dessins sont simplement superpos´es. La fonction “pile” accepte trois arguments: un nombre entre 0 et 1, “prop”, et deux dessinateurs. Le r´esultat repr´esente le dessin du deuxi`eme dessinateur plac´e au dessus du dessin du premier dessinateur. La proportion verticale du cadre occup´ee par le premier dessinateur est “prop”. La fonction “cote-a-cote” est l’analogue horizontal de “pile”. Voici quelques exemples:

(−1,−1)

(1,1)

(superposition losange triangle)

(−1,−1)

(1,1)

(pile 3/4 triangle ell)

(−1,−1)

(1,1)

(cote-a-cote 1/2 triangle ell)

(5)

3.2 Mise en page d’entiers

3.2.1 (entier->dessinateur n)

L’argument de cette fonction est un entier non-n´egatif. Le r´esultat de la fonction est un dessinateur qui repr´esente la s´equence de chiffres qui d´enote l’entier. Pour vous simplifier la tˆache, le fichier “tp1-def.scm”

contient une d´efinition du parcours pour chaque chiffre. Dans le dessin produit, tous les chiffres doivent avoir les mˆemes proportions. Par exemple:

(−1,−1)

(1,1)

(entier->dessinateur 140)

Note: il est interdit d’utiliser la fonction pr´ed´efinie “number->string”. R´eutilisez autant que possible les fonctions de la section 3.1.

3.3 Mise en page d’arbres

3.3.1 (arbre->dessinateur x)

L’argument de cette fonction, “x”, est une donn´ee quelconque. Le r´esultat de la fonction est un dessinateur qui repr´esente l’arbre binaire form´e par les doublets (paires) dans “x”. Un noeud interne de l’arbre correspond `a un doublet. La branche gauche d’un noeud correspond au champ “car” et la branche droite au champ “cdr” du doublet. Les feuilles de l’arbre (qui correspondent `a toutes donn´ees qui ne sont pas des doublets) doivent ˆetre ´equidistants par rapport `a l’axe X et la racine de l’arbre doit se trouver au millieu.

Ceci doit ˆetre vrai ´egalement pour tout sous-arbre. La distance verticale entre un noeud et ses fils doit ˆetre la mˆeme pour tout noeud. Voici un exemple:

(−1,−1)

(1,1)

(arbre->dessinateur ’(((1 . 2) . (3 . 4)) . ((5 . 6) . (7 . 8))))

Essayez d’autres exemples avec le mod`ele pour bien comprendre la disposition demand´ee. En particulier, essayez:

(dessiner (arbre->dessinateur ’((1 . 2) . 3))) (dessiner (arbre->dessinateur ’(1 2 3 4 5)))

(dessiner (arbre->dessinateur ’((1 2 3 4 5) . (1 2 3 4 5))))

(6)

4 Rapport

Vous devez r´ediger un rapport qui:

1. Explique le fonctionnement de chaque fonction que nous vous demandons d’´ecrire (1/2 page au maxi- mum pour chaque fonction sauf pour les fonctions “entier->dessinateur” et “arbre->dessinateur”

ou il y a un maximum de une page par fonction).

2. Explique les forces et faiblesses du langage Scheme pour la programmation de cette application (3

`a 5 pages). Quelles difficult´es avez-vous rencontr´ees avec l’utilisation du langage Scheme? Qu’est- ce qui a ´et´e facilit´e par l’utilisation de Scheme? Choisissez des crit`eres d’´evaluation appropri´es et pertinents `a ce travail. Dans votre ´evaluation, utilisez le langage Java comme point de comparaison.

Qu’est-ce qui aurait ´et´e plus difficile ou facile avec le langage Java (pour les parties que vous avez programm´ees)?

3. En un maximum de une page, faites ressortir les avantages et inconv´enients de la repr´esentation fonctionnelle pour les dessins normalis´es.

5 Evaluation ´

• Ce travail compte pour 10 points dans la note finale du cours. Vous DEVEZ le faire par groupes de 2 personnes. Indiquez vos noms clairement au tout d´ebut de votre programme.

• Le programme sera ´evalu´e sur 6 points et le rapport sur 4 points. Un programme qui plante `a l’ex´ecution, mˆeme dans une situation extrˆeme, se verra attribuer z´ero sur 6.

• Vous devez remettre votre rapport `a la d´emonstration du 21 f´evrier. Vous avez jusqu’`a minuit le mˆeme jour pour remettre votre programme. Vous serez p´enalis´es de 3 points sur 10 par jour de retard.

• Vous devez remettre votre programme par remise ´electronique grˆace `a la commande suivante:

remise ift2030 tp1 tp1.scm

Votre fichier ne doit pas charger le fichier “tp1-def.scm”. Nous nous occuperons de le faire lors des tests.

Références

Documents relatifs

possibilit´es (la division par 2! correspond au fait que la d´ecomposition en produit de cycles `a supports disjoints est unique modulo l’ordre des cycles, et pour arranger

(Efracrat22.tex) Soit A un polynˆ ome de degr´ e strictement plus petit que n... Quelle est la partie enti` ere de la d´

Il n’est pas n´ ecessaire de relancer tous les calculs d’estimation des param` etres du mod` ele ` a chaque fois que la base de donn´ ees est compl´ et´ ee par de

La structure de phrase peut devenir plus complexe et les élèves réagissent au texte en résumant les événements en ordre

Exercice 11 : [Bonus sur les clauses] On dit qu’une clause est une clause de Horn ssi elle a au plus une variable positive (au plus une variable ` a droite de = ⇒ ). a- Montrer que

5 Remarque : Il est beaucoup plus facile de prouver ce r´esultat en utilisant une conver- gence normale comme on a pu le faire en

Le code suivant comprend

La différence entre A et B vient probablement du fait que la fonction xx**2 est une fonction software (codée), alors que la multiplication x*x est une fonction hardware (avec une