par:
Nicola Grenon GREN30077303
et
Jean-François Delisle DELJ02057809
mardi vingt-et-un février deux mille six
I Le fonctionnement des fonctions.
ligne:
(define ligne
(lambda (depart arrivee)
(lambda (transf)
(map (lambda (segment)
(segm (transf (segm-depart segment))
(transf (segm-arrivee segment))))
(decoupe depart arrivee 1/10)))))
La fonction ligne reçoit les deux vecteurs qui sont en fait chacun une paire représentant les
coordonnées cartésiennes d'un point (normalisé). La sous fonction «decoupe» s'occupe de calculer
l'ensemble des points nécessaires pour séparer le segment allant du premier vecteur au second en
une liste de segments de longueurs équivalentes d'au maximum 1/10. Cette dernière effectue
l'opération en divisant récursivement la longueur de chaque sous segment en deux un nombre
suffisant de fois pour que chaque sous segment ne dépasse pas cette limite. Une fois que la liste des
segments a été déterminée, on bâti le corps de la fonction qu'est un «dessinateur» en insérant la liste
dans une lambda qui se chargera d'appliquer la transformation «transf» à chacun des vecteurs ci
avant déterminés.
parcours->dessinateur:
(define parcours->dessinateur
(lambda (parcours)
(lambda (transf)
(concat
(map (lambda (segment)
((ligne (segm-depart segment) (segm-arrivee segment)) transf))
(liste-vect->liste-segm parcours))))))
La fonction parcours->dessinateur reçoit une liste de vecteur. On va d'abord transformer cette
liste de vecteur en une liste de segments au moyen de la sous fonction liste-vect->liste-segm. Pour
appliquer les transformations du transformateur que recevra le dessinateur que l'on veut produire, on
va traiter au moyen de celui-ci chaque segment obtenu pour notre parcours au moyen de la fonction
ligne. Le résultat de cette opération nous donnant la liste complète des segments (de taille 1/10
maximum) qu'on va inclure dans une lambda qui sera prête à leur appliquer le transformateur dont
nous nous sommes servis et qu'elle recevra en paramètre lorsqu'elle jouera son rôle de dessinateur.
Les fonctions de transformation:
Les fonctions de transformation ont été implémentées de façon modulaire. Ainsi, dans un premier
temps on voit ici les fonctions de calcul des coordonnées. Elles seront appliquées à chaque
coordonnée de chaque vecteur reçu pour chaque segment représentant le dessin du dessinateur. À
noter ici que le paramètre «signe» n'est utiliser que dans le cas de la rotation, car avec cette fonction
on doit utiliser une opération légèrement différente pour chacune des coordonnées. Toutes les autres
fonctions de transformation appliquent la même formule aux deux coordonnées, mais on a quand
même accolé le paramètre signe à toutes les fonctions dans un esprit de modularité.
(define f-translation
(lambda (a b amplitude signe)
(+ a amplitude)))
(define f-reduction
(lambda (a b amplitude signe)
(* a amplitude)))
(define f-loupe
(lambda (a b amplitude signe)
(* a (/ (+ 1 amplitude) (+ 1 (* amplitude (+ (* a a) (* b b))))))))
(define f-rotation
(lambda (a b amplitude signe)
(signe (* a (cos amplitude)) (* b (sin amplitude)))))
Chacune de ces fonctions de transformation est, donc, appelée par une fonction principale qui
applique les changements de ladite fonction de transformation à tous les vecteurs du dessinateur.
Elle reçoit donc en paramètre la fonction à appliquer «f» et la transmet à une sous fonction qui
l'appliquera elle sur chacun des vecteurs, coordonnée par coordonnée.
(define mod-dessinateur
(lambda (f mod-x mod-y dessinateur)
(lambda (transf)
(map (lambda (segment)
(segm (mod-vect f (segm-depart segment) mod-x mod-y)
(mod-vect f (segm-arrivee segment) mod-x mod-y)))
(dessinateur transf)))))
(define mod-vect
(lambda (f vecteur mod-x mod-y)
(vect (f (vect-x vecteur) (vect-y vecteur) mod-x +)
(f (vect-y vecteur) (vect-x vecteur) mod-y -))))
On a finalement ici les fonctions d'appel de départ qui ne servent qu'à mettre en paire les bonnes
fonctions de transformation, l'amplitude de la modification à apporter et le dessinateur à transformer
avant de le retourner.
(define translation
(lambda (deplacement-x deplacement-y dessinateur)
(mod-dessinateur f-translation deplacement-x deplacement-y dessinateur)))
(define reduction
(lambda (facteur-x facteur-y dessinateur)
(mod-dessinateur f-reduction facteur-x facteur-y dessinateur)))
(define loupe
(lambda (facteur dessinateur)
(mod-dessinateur f-loupe facteur facteur dessinateur)))
(define rotation
(lambda (thetadeg dessinateur)
(let ((theta (* (/ thetadeg 360) 2 3.141596539)))
(mod-dessinateur f-rotation theta theta dessinateur))))
La superposition:
(define superposition
(lambda (dessinateur1 dessinateur2)
(lambda (transf)
(append (dessinateur1 transf) (dessinateur2 transf)))))
La superposition est effectuée très simplement en extrayant de chacun des deux dessinateurs la
liste des segments auxquels on aura appliqué la transformation reçue en paramètre par notre
dessinateur résultant et qu'on aura ensuite juxtaposés avec un append.
L'empilage:
(define pile
(lambda (prop dessinateur1 dessinateur2)
(lambda (transf)
(append
((translation 0 (- prop 1) (reduction 1 prop dessinateur1)) transf)
((translation 0 prop (reduction 1 (- 1 prop) dessinateur2)) transf)))))
On combine ici deux transformations de base. Pour chacun des deux dessinateurs reçus, on
réduit d'abord du facteur voulu (l'un étant le complément de l'autre) et il ne reste plus qu'à déplacer
(translation) les deux dessins à leur position finale. Comme on applique au passage à chaque
dessinateur les transformations que devra subir le dessinateur final, on obtient deux listes de
segments qu'il ne nous reste plus qu'à combiner et à remettre dans un lambda qui leur passera le
«transf» précité. On a d'ailleurs déjà utilisé cette technique pour la superposition.
La mise en côte-à-côte:
(define cote-a-cote
(lambda (prop dessinateur1 dessinateur2)
(lambda (transf)
(append
((translation (- prop 1) 0 (reduction prop 1 dessinateur1)) transf)
((translation prop 0 (reduction (- 1 prop) 1 dessinateur2)) transf)))))
La stratégie est ici calquée sur l'empilage. La fonction se comporte exactement comme la
précédente, mais selon l'autre axe. Il aurait toutefois été plus compliqué de vouloir mettre en commun
les opérations similaires. Il aurait fallu soit jouer avec une série de rotation (coûteux), soit ajouter
plusieurs paramètres spécifiques, tuant ainsi l'espoir d'une généralisation utile. Il eut aussi été
possible de déduire à partir des paramètres déjà existant laquelle des deux fonctions appelait une
fonction commune, mais il aurait alors fallu effectuer une lourde série d'opération mathématiques à
chaque itération, ce qui, somme toute, n'était pas intéressant.
1 / 12 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !