TP3: Transformations Affines Récursives
Le fichier à remplir est ici.
Nous allons calculer un ensemble de points du plan qui sont les termes successifs d'une suite définie au moyen de transformations affines dans \(\mathbb{R}^2\). L'affichage de ces points forme un dessin fractal.
Dans ce TP, on fixe un point \(O\) du plan, l'origine, et on définit des matrice 2x2 et des vecteurs comme suit.
\begin{align*} M &= \left[\begin{matrix} a & b \\ c & d \end{matrix} \right] & \overrightarrow{OP} &= \left[\begin{matrix} x \\ y \end{matrix} \right] \end{align*}Une application linéaire \(f\) est une fonction qui à un vecteur associe un vecteur. Elle est définie par une matrice \(M\) (la matrice associée à \(f\)) de la manière suivante : \(f = \overrightarrow{OP} \mapsto M \times \overrightarrow{OP}\).
Une transformation affine du plan est également une fonction qui associe un vecteur à un vecteur, \(\overrightarrow{OP} \mapsto \overrightarrow{OP_1}\), définie par \(\overrightarrow{OP_1} = f(\overrightarrow{OP}) + \vec V\), où \(f\) une application linéaire et \(\vec V\) un vecteur fixé.
Par conséquent, on peut définir une transformation affine par la combinaison d'une matrice \(M\), définissant l'application linéaire \(f\), et un vecteur \(\vec V\).
1 Choix de représentation
Choisir et définir un type matrix
pour les matrices 2x2 et un type vector
pour les vecteurs de taille 2.
Définir deux fonctions construisant respectivement une matrice et un vecteur.
val mkm : float -> float -> float -> float -> matrix = <fun> val mkv : float -> float -> vector = <fun>
Définir une fonction transformant un vecteur en une liste à deux éléments.
val vtol : vector -> float list = <fun>
Définir une fonction transformant une matrice en une liste de deux listes à deux éléments, chacune des liste étant une ligne.
val mtol : matrix -> float list list = <fun>
2 Définition des données
Définir les 4 matrices et les 4 vecteurs suivants.
(* Evaluate me *) let m1 = mkm 0.0 0.0 0.172 0.496 let m2 = mkm 0.076 0.3122 0.257 0.204 let m3 = mkm 0.821 (-0.028) 0.030 0.845 let m4 = mkm 0.024 (-0.356) 0.323 0.074 let v1 = mkv 0.496 (-0.091) let v2 = mkv 0.494 0.133 let v3 = mkv 0.088 0.176 let v4 = mkv 0.470 0.260
3 La construction des transformations affines
Définir une fonction
mt
qui réalise le produit d'une matrice \(2 \times 2\) par un vecteur.val mt : matrix -> vector -> vector = <fun>
Définir une fonction
sv
qui réalise la somme de 2 vecteurs.val sv : vector -> vector -> vector = <fun>
Définir une fonction
genapplin
qui prend en argument une matrice et retourne l'application linéaire associée.val genapplin : matrix -> vector -> vector = <fun>
Définir une fonction
gentraffine
qui prend en argument une matrice et un vecteur, et qui retourne la transformation affine associée.val gentraffine : matrix -> vector -> vector -> vector = <fun>
Définir les quatre transformations affines associées respectivement à \(m_1\) et \(v_1\), \(m_2\) et \(v_2\), \(m_3\) et \(v_3\), et \(m_4\) et \(v_4\), et les stocker dans le quadruplet
les4tr
. Rappel : ces matrices et vecteurs sont déjà définis dans le fichier.val les4tr : (vector -> vector) * (vector -> vector) * (vector -> vector) * (vector -> vector) = (<fun>, <fun>, <fun>, <fun>)
4 Le choix d'une transformation parmi les 4
Définir une fonction
elemrang
qui retourne un élément choisi au hasard (compris entre \(1\) et \(4\)) d'un quadruplet donné. Utiliser la fonction de la bibliothèqueRandom.int : int -> int
, qui est telle queRandom.int n
retourne un nombre au hasard dans l'intervalle d'entiers \([0..n-1]\).val elemrang : 'a * 'a * 'a * 'a -> 'a = <fun>
Définir une fonction
traff
qui délivre au hasard l'une des 4 transformations affines, en utilisantelemrang
.val traff : unit -> vector -> vector = <fun>
5 La suite des points transformés
Nous nous intéressons maintenant à une suite de points du plan définie par :
\begin{align*} P_0 & = (0.5, 0.0)\\ P_i & = T(P_{i-1}) \end{align*}où \(T\) désigne l'une "au hasard" des 4 transformations affines.
Définir la fonction suite
qui, étant donné une fonction f
et un entier n
, calcule les n
termes de la suite et appelle la fonction f
sur chaque terme. La fonction f
est utilisée pour l'affichage (son type est vector -> unit
), et la suite de points calculée avec la fonction traff
.
val suite : (vector -> unit) -> int -> unit = <fun>
6 L'affichage de la suite des points
Pour démarrer une fenêtre graphique, exécuter ceci:
(* Copiez la ligne suivante (avec le #) dans le toplevel (fenêtre du bas) et tapez Entrée #load "graphics.cma";; *) let res = Graphics.open_graph ""
Attention, si vous fermez directement la fenêtre, cela tue le toplevel. Il vaut mieux utiliser la fonction close_graph
.
let res = Graphics.close_graph ()
Documentation du module Graphics
:
http://caml.inria.fr/pub/docs/manual-ocaml/libgraph.html
http://caml.inria.fr/pub/docs/manual-ocaml/libref/Graphics.html
Pour afficher les points, définissez une fonction run
qui prend en argument le nombre de points à afficher :
- la fonction ouvre une fenêtre graphique;
- elle calcule et affiche le nombre de points demandés;
- elle attend que l'on tape une touche du clavier (en utilisant la fonction
wait_next_event
deGraphics
); - elle ferme la fenêtre et quitte.
val run : int -> unit = <fun>