Pour visualiser des variations de position d’un point au cours du temps, seule la représentation graphique est réellement pertinente et parlante, or la bibliothèque graphique de caml, bien qu’exhaustive, ne permet pas, comme le fait Maple de tracer directement des courbes. Nous avons donc été amenés à considérer le tracé de courbes ou de séries de points en Caml.
Lors du tracé de courbes, nous travaillons généralement sur des flottants. Or la fenêtre graphique de Caml n’accepte que des points dont les coordonnées sont des entiers!! De plus, l’origine du repère graphique de Caml est fixe, il serait pourtant plus aisé de pouvoir définir sa propre représentation d’un repère. Cette caractéristique surprend, surtout lorsqu’on a été habitué à des logiciels tel que Maple où la construction graphique est quasi-automatique. En Caml, tout - ou presque - est à redéfinir.
#open "graphics";;
Ouvre la bibliothéque graphique de Camlopen_graph "highest";;
#- : unit = ()
cleargraph ( ) ;;
#- : unit = ()
En Caml, il existe plusieurs types d’ordres et de fonctions.
"size_x()" renvoie la taille de l’écran en abscisse
"size_y()" renvoie la taille de l’écran en ordonnée
"moveto x y" place le point courant en (x,y)
"lineto x y" trace une ligne entre le point courant et le point de coordonnées (x,y) ; Ce dernier devient à son tour le point courant.
Rappel : Dans toutes ces définitions, x et y sont des entiers
Les points de la fenêtre graphique sont des pixels.
Le nombre de pixels sur la fenêtre graphique en abscisse est size_x, en ordonnée size_y.
Remarque : Travaillant sur des entiers, le nombre maximal de pixels est (size_x)*(size_y).
L’origine (0,0) du repère graphique est situé en bas, à gauche de l’écran.
Notre utilisation des flottants n’est pas compatible avec l’utilisation des entiers par Caml. Afin de rendre exploitable pour Caml une fonction graphique définie exclusivement sur des flottants, nous allons donc être amenés à jongler entre entiers et flottants.
On appellera repére virtuel un repére (O,i,j) du plan R².
Le repère écran est le repère associé à la fenêtre graphique. Son origine se trouve dans le coin en bas à gauche de l’écran. Les coordonnées (qui sont des couples d’entiers ) dans ce repère représentent des pixels.
Le but est de fournir une représentation d’un ensemble de points du plan R² à l’écran.
Il faut donc établir une relation entre les coordonnées d’un point dans le repère virtuel et ses coordonnées dans le repère de la fenêtre graphique.
Cette relation ne peut être une bijection ( R² est indénombrable alors que l’ensemble des pixels de l’écran l’est). Il s’agit en fait d’une surjection: à un pixel correspondent plusieurs points virtuels.

L’origine du repère écran se trouve en (0,0) en bas à gauche de l’écran graphique. On place l’origine du repère virtuel où on désire. On peut en effet travailler sur des flottants négatifs. Il convient donc de définir un nouveau type repère qui permettra de référencer l’origine (0,0) comme on le souhaitera.
Pour passer des flottants aux entiers, nous allons être amenés à faire des arrondis et des approximations. Une partie de l’information, ou tout au moins de la précision, risque d’être perdue.
Certains problèmes peuvent donc apparaître lorsque l’échelle des valeurs que l’on a à traiter est très petite. Ces problèmes sont facilement évitables (il suffit de multiplier les valeurs par une constante afin d’accroître l’échelle des valeurs), mais l’utilisateur doit être prévenu et être conscient de ce problème.
Il faut redéfinir le type point écran.
type p_écran={X:int;Y:int}
#Le type p_ecran est défini.
Ensuite on définit le type point repère (qui correspond au point du repère virtuel de R²).
type p_repere={x :float ;y :float} ;;
#Le type p_repere est défini.
Enfin on définit un type repère, contenant les paramètres de la représentation du repère(O,i,j) à l’écran.
type repere={O:point_écran ;I:int;J:int};;
#Le type repere est défini.
O : point écran correspondant au centre du repére virtuel à l’ écran
I : vecteur unitaire des abscisses
J : vecteur unitaire des ordonnées
let rep_to_ecr pt_rep rep =
{X=(rep.O.X)+( int_of_float((pt_rep.x)*.float_of_int(rep.I)) );
Y=(rep.O.Y)+( int_of_float((pt_rep.y)*.float_of_int(rep.J)) )};;
#rep_to_ecr : p_repere -> repere -> p_ecran = <fun>
Moveto et lineto sont préexistants en Caml. Il suffit de redéfinir en type point_écran.
Ainsi:
let move_ecr pt_ecr = moveto (pt_ecr.X) (pt_ecr.Y) ;;
#move_ecr : p_ecran -> unit = <fun>
let line_ecr pt_ecr = lineto (pt_ecr.X) (pt_ecr.Y) ;;
#line_ecr : p_ecran -> unit = <fun>
move_ecr et line_ecr prennent en argument un point écran. Move_ecr déplace le curseur graphique au point_écran pris en argument.
Line_ecr trace un segment entre le point_écran courant et le point_écran reçu en argument.
let segment_ecr pt_ecr1 pt_ecr2 =
moveto (pt_ecr1.X) (pt_ecr1.Y);
lineto (pt_ecr2.X) (pt_ecr2.Y);;
#segment_ecr : p_ecran -> p_ecran -> unit = <fun>
Segment_ecr prend en argument deux points écran et trace le segment qui les lie.
let point_ecr pt_ecr =
segment_ecr {X=((pt_ecr.X)-2) ; Y=pt_ecr.Y} {X=((pt_ecr.X)+2) ; Y=(pt_ecr.Y)} ;
segment_ecr {X=(pt_ecr.X) ; Y=((pt_ecr.Y)+2)} {X=(pt_ecr.X) ; Y=((pt_ecr.Y)-2)} ;;
#point_ecr : p_ecran -> unit = <fun>
Un point, compte-tenu de la résolution graphique de l’écran de l’ordinateur, ne serait pas très visible. Par conséquent, un point sera représenté par une petite croix.
Point_écr prend en argument un point écran et trace le point à l’écran sous forme d’une petite croix.
let move_rep pt_rep rep = move_ecr (rep_to_ecr pt_rep rep) ;;
#move_rep : p_repere -> repere -> unit = <fun>
Move_rep prend en argument un point repère et un repère et place le point écran correspondant sous forme de point courant (pas d’affichage à l’écran).
let line_rep pt_rep rep = line_ecr (rep_to_ecr pt_rep rep) ;;
#line_rep : p_repere -> repere -> unit = <fun>
Line_rep prend en argument un point repère et trace le segment entre le point repère courant et le point repère pris en argument.
let point_rep pt_rep rep = point_ecr (rep_to_ecr pt_rep rep) ;;
#point_rep : p_repere -> repere -> unit = <fun>
Point_rep prend en argument un point repère et un repère, et affiche le point correspondant à l’écran sous forme d’une petite croix.
let segment_rep pt_rep1 pt_rep2 rep =
move_rep pt_rep1 rep;
line_rep pt_rep2 rep;;
#segment_rep : p_repere -> p_repere -> repere -> unit = <fun>
Segment_rep prend en argument deux points repère et un repère, et trace le segment correspondant à l’écran.
let fenetre xmin xmax ymin ymax=
let II=int_of_float((float_of_int(size_x()))/.(xmax-.xmin))
and JJ=int_of_float((float_of_int(size_y()))/.(ymax-.ymin)) in
{O={X=int_of_float((-.xmin)*.float_of_int(II));Y=int_of_float((-.ymin)*.float_of_int(JJ))} ; I=II ; J=JJ};;
#fenetre : float -> float -> float -> float -> repere = <fun>
fenetre reçoit en argument quatre flottants qui correspondent aux valeurs extrêmes que prennent x et y, soit dans l’ordre xmin, xmax, ymin, ymax.
La fenêtre est ainsi centrée et renvoie un repère qui lui correspond.(Le repére renvoyé par fenetre est orthonormal, mais pas forcément orthonormé.)
let vision centre largeur=
let (a,b)=centre and hauteur=(largeur*.(float_of_int (size_y()))/.(float_of_int (size_x()))) in
fenetre (a-.(largeur/.2.)) (a+.(largeur/.2.)) (b-.(hauteur/.2.)) (b+.(hauteur/.2.));;
#vision : float * float -> float -> repere = <fun>
vision quant à lui renvoi un repère orthonormé. On ne peut donc plus choisir la hauteur de la fenêtre qui est définie automatiquement. vision reçoit donc en argument la position à l’écran du centre du repère (il s’agit d’un couple de flottants) ainsi que la largeur de l’écran.
Si l’on choisit par exemple de positionner le centre du repère au centre de l’écran, on prend (0. ,0.) pour centre du repère.
let trace_rep rep n couleur=
set_color couleur;
moveto 0 (rep.O.Y);
lineto (size_x()) (rep.O.Y);
moveto (rep.O.X) 0;
lineto (rep.O.X) (size_y());
let XM=int_of_float( float_of_int( abs(size_x()-(rep.O.X)) ) /. float_of_int(rep.I) )
and Xm=int_of_float( float_of_int( abs(rep.O.X) ) /. float_of_int(rep.I) )
and YM=int_of_float( float_of_int( abs(size_y()-(rep.O.Y)) ) /. float_of_int(rep.J) )
and Ym=int_of_float( float_of_int( abs(rep.O.Y) ) /. float_of_int(rep.J) ) in
let sX= float_of_int(rep.I)/.float_of_int(n)
and sY= float_of_int(rep.J)/.float_of_int(n) in
move_ecr { X=((rep.O.X)+(rep.I)) ; Y=(rep.O.Y) } ;
line_ecr { X=(((rep.O.X)+(rep.I))-7); Y=((rep.O.Y)+7) };
move_ecr { X=((rep.O.X)+(rep.I)) ; Y=(rep.O.Y) } ;
line_ecr { X=(((rep.O.X)+(rep.I))-7); Y=((rep.O.Y)-7) };
move_ecr { X=(rep.O.X) ; Y=(rep.O.Y)+(rep.J) } ;
line_ecr { X=((rep.O.X)-7); Y=(rep.O.Y)+(rep.J)-7 };
move_ecr { X=(rep.O.X) ; Y=(rep.O.Y)+(rep.J) } ;
line_ecr { X=((rep.O.X)+7); Y=(rep.O.Y)+(rep.J)-7 };
for i=0 to (XM+1) do
move_ecr { X= ((rep.O.X)+i*(rep.I)) ; Y= ((rep.O.Y)+5) };
line_ecr { X= ((rep.O.X)+i*(rep.I)) ; Y= ((rep.O.Y)-5) };
for j=1 to (n) do
move_ecr { X= ((rep.O.X)+i*(rep.I)) + int_of_float(float_of_int(j)*.sX) ; Y=((rep.O.Y)+2) };
line_ecr { X= ((rep.O.X)+i*(rep.I)) + int_of_float(float_of_int(j)*.sX) ; Y=((rep.O.Y)-2) };
done;
done;
for i=0 downto (-Xm-1) do
move_ecr { X= ((rep.O.X)+i*(rep.I)) ; Y= ((rep.O.Y)+5) };
line_ecr { X= ((rep.O.X)+i*(rep.I)) ; Y= ((rep.O.Y)-5) };
for j=(-1) downto (-n) do
move_ecr { X= ((rep.O.X)+i*(rep.I)) + int_of_float(float_of_int(j)*.sX) ; Y=((rep.O.Y)+2) };
line_ecr { X= ((rep.O.X)+i*(rep.I)) + int_of_float(float_of_int(j)*.sX) ; Y=((rep.O.Y)-2) }
done;
done;
for i=0 to (YM+1) do
move_ecr { X= ((rep.O.X)+5) ; Y= ((rep.O.Y)+i*(rep.J)) };
line_ecr { X= ((rep.O.X)-5) ; Y= ((rep.O.Y)+i*(rep.J)) };
for j=1 to (n) do
move_ecr { X=((rep.O.X)+2) ; Y= ((rep.O.Y)+i*(rep.J)) + int_of_float(float_of_int(j)*.sY) };
line_ecr { X=((rep.O.X)-2) ; Y= ((rep.O.Y)+i*(rep.J)) + int_of_float(float_of_int(j)*.sY) };
done;
done;
for i=0 downto (-Ym-1) do
move_ecr { X=((rep.O.X)+5) ; Y=((rep.O.Y)+i*(rep.J)) };
line_ecr { X=((rep.O.X)-5) ; Y=((rep.O.Y)+i*(rep.J)) };
for j=(-1) downto (-n) do
move_ecr { X=((rep.O.X)+2) ; Y= ((rep.O.Y)+i*(rep.J)) + int_of_float(float_of_int(j)*.sY) };
line_ecr { X=((rep.O.X)-2) ; Y= ((rep.O.Y)+i*(rep.J)) + int_of_float(float_of_int(j)*.sY) };
done;
done;
set_color black;;
#trace_rep : repere -> int -> color -> unit = <fun>
Trace_rep reçoit en argument un repère, le nombre de subdivisions qui doivent être tracées sur les axes ainsi que la couleur du tracé. Cette fonction trace les axes et ses graduations en fonctions des vecteurs unitaires ( I et J définis dans le type repère).
let axes rep =moveto 0 (rep.O.Y);
lineto (size_x()) (rep.O.Y);
moveto (rep.O.X) 0;
lineto (rep.O.X) (size_y());;
#axes : repere -> unit = <fun>
axes reçoit en argument un repère et trace les axes (sans les graduations).
Le tracé de fonctions du type y=f(x) se fait à l’aide de la fonction trace_fun.
let trace_fun f xmin xmax n rep=
let h=(xmax-.xmin)/.(float_of_int n) in
move_rep { x=xmin ; y= (f xmin) } rep;
for i=1 to n-1 do
line_rep { x=xmin+.((float_of_int i)*.h) ; y= f (xmin+.((float_of_int i)*.h)) } rep;
move_rep { x=xmin+.((float_of_int i)*.h) ; y=f (xmin+.((float_of_int i)*.h))} rep;
done;;
#trace_fun : (float -> float) -> float -> float -> int -> repere -> unit = <fun>
Elle reçoit en argument :
Remarque : Plus n est grand, plus la précision à l’écran de la fonction sera élevée.
Toutefois plus n est grand, plus le temps de réponse est élevé. Une résolution correcte existe pour 500 points (temps de réponse instantané). Pour 5000 points, bonne résolution, temps de réponse 3-4 s. Pour 50000 points, excellente résolution, temps de réponse 15 s. Lorsque des points ne sont pas définis (exemple: x->sqrt(x) pour x<0), l’opérateur graphique en Caml trace une droite grisée. Il n’y a donc pas besoin d’une exception lorsque des points ne sont pas définis.
Exemple :
![]() |
Procédure du tracé :
let rep=fenetre (-.10.) (10.) (-.10.) 10.;; (* On définit un repère. *)
rep : repere = {O = {X = 400; Y = 300}; I = 40; J = 30}
let f1 x=sqrt x;; (* On définit deux fonctions. *)
let f2 x=x*.x;;
f1 : float -> float = <fun>
f2 : float -> float = <fun>
clear_graph();; (* Efface la fenêtre graphique. *)
- : unit = ()
trace_rep rep 5 blue ;; (* Trace le repère (avec les graduations et 5 subdivisions) *)
- : unit = ()
trace_fun f1 (-.10.) (10.) 5000 rep ;; (* Trace la première fonction (en noir). *)
- : unit = ()
set_color red;;
trace_fun f2 (-.10.) (10.) 5000 rep ;; (* Trace la deuxième fonction (en rouge). *)
#- : unit = ()
#- : unit = ()
On peut utiliser les fonctions nuage_points et polygone.
let nuage_pts pliste rep =
let pliste2 = ref (pliste) in
while (!pliste2)<>[] do
point_rep (hd !pliste2) rep;
pliste2 := tl (!pliste2);
done;;
#nuage_pts : p_repere list -> repere -> unit = <fun>
Nuage_pts pose un point pour chaque point de la liste. Cela peut être intéressant si l’on veut étudier, en même temps que la trajectoire, la cinématique (vitesse) qui lui est associée (plus les points sont rapprochés, plus la vitesse est faible, et réciproquement).
let polygone pliste rep =
let pliste2 = ref (pliste) in
move_rep (hd !pliste2) rep;
pliste2 := (tl !pliste2);
while (!pliste2)<>[] do
line_rep (hd !pliste2) rep;
pliste2 := tl (!pliste2);
done;set_color black;;
#polygone : p_repere list -> repere -> unit = <fun>
Polygone trace les droites entre les points. On a ainsi la trajectoire « pleine » du point. On perd cependant en précision (ce qui est toutefois négligeable si le nombre de points est assez élevé).
Remarque : Ces deux fonctions reçoivent en argument une liste de points repère et un repère.
Pour tracer une fonction à l’aide de ces deux applications, on crée une liste de point à l’aide de la fonction l_pts_fun qui reçoit en argument :
let l_pts_fun f xmin xmax n =
let liste=ref([]) and h=(xmax-.xmin)/.(float_of_int n) in
for i=n-1 downto 1 do
liste:={ x=xmin+.((float_of_int i)*.h) ; y= f (xmin+.((float_of_int i)*.h)) }:: (!liste);
done;
(!liste);;
#l_pts_fun : (float -> float) -> float -> float -> int -> p_repere list =<fun>
de même pour les courbes paramétrées on utilise l_pts_para où f et g sont deux fonctions de t.
let l_pts_para (f,g) tmin tmax n=
let liste=ref([]) and h=((tmax-.tmin)/.(float_of_int(n))) in
for i=n-1 downto 1 do
liste:={x=(f(tmin+.((float_of_int i)*.h)));y=(g(tmin+.((float_of_int i)*.h)))}::(!liste);
done;
(!liste);;
#l_pts_para : (float -> float) * (float -> float) -> float -> float -> int -> p_repere list = <fun>
Le repère se définit automatiquement à partir de la liste de points (on utilise pour cela les fonctions intermédiaires minx, miny, maxx, maxy qui recherchent les valeurs minimales et maximales de x et y dans une liste de points, et fenêtre).
let minx pliste =
let pliste2 = ref (pliste) and mx =ref(((hd (pliste)).x)) in
while (!pliste2)<>[] do
if ((hd (!pliste2)).x) <= (!mx) then mx:=((hd (!pliste2)).x);
pliste2 := tl (!pliste2);
done;
(!mx);;
#minx : p_repere list -> float = <fun>
let miny pliste =
let pliste2 = ref (pliste) and my =ref(((hd (pliste)).y)) in
while (!pliste2)<>[] do
if ((hd (!pliste2)).y) <= (!my) then my:=((hd (!pliste2)).y);
pliste2 := tl (!pliste2);
done;
(!my);;
#miny : p_repere list -> float = <fun>
let maxx pliste =
let pliste2 = ref (pliste) and Mx =ref(((hd (pliste)).x)) in
while (!pliste2)<>[] do
if ((hd (!pliste2)).x) >= (!Mx) then Mx:=((hd (!pliste2)).x);
pliste2 := tl (!pliste2);
done;
(!Mx);;
#maxx : p_repere list -> float = <fun>
let maxy pliste =
let pliste2 = ref (pliste) and My =ref(((hd (pliste)).y)) in
while (!pliste2)<>[] do
if ((hd (!pliste2)).y) >= (!My) then My:=((hd (!pliste2)).y);
pliste2 := tl (!pliste2);
done;
(!My);;
#maxy : p_repere list -> float = <fun>
Remarque : ces fonctions vont permettre de cadrer automatiquement la fenêtre graphique.
On redéfinit ainsi les fonctions plot_polygones et plot_nuage qui ne reçoivent plus en argument qu’une liste de points et qui globalement, effectuent les mêmes opérations nuage_pts et polygone tout en choisissant eux même leur repére.
let plot_nuage pliste=
let xmin=(minx pliste)
and xMax=(maxx pliste)
and ymin=(miny pliste)
and yMax=(maxy pliste) in
let xm=xmin-.(0.1)*.(xMax-.xmin)
and xM=xMax+.(0.1)*.(xMax-.xmin)
and ym=ymin-.(0.1)*.(yMax-.ymin)
and yM=yMax+.(0.1)*.(yMax-.ymin) in
let (rx,ry)=
if (yM-.ym)>(100.*.(xM-.xm)) then
((0.),(( (float_of_int(size_y())) *. (xM-.xm) /.(float_of_int(size_x())) )+.(ym-.yM) )/.(2.))
else
if (xM-.xm)>(100.*.(yM-.ym)) then
((( (float_of_int(size_x())) *. (yM-.ym) /.(float_of_int(size_y())) )+.(xm-.xM) )/.(2.),0.)
else
if ((float_of_int(size_x())) *. (yM-.ym) /.(float_of_int(size_y())))>=xM-.xm
then ((( (float_of_int(size_x())) *. (yM-.ym) /.(float_of_int(size_y())) )+.(xm-.xM) )/.(2.),0.)
else ((0.),(( (float_of_int(size_y())) *. (xM-.xm) /.(float_of_int(size_x())) )+.(ym-.yM) )/.(2.)); in
let rep=fenetre (xm-.rx) (xM+.rx) (ym-.ry) (yM+.ry) in
trace_rep rep 10 black;
nuage_pts pliste rep;;
#plot_nuage : p_repere list -> unit = <fun>
let plot_polygone pliste=
let xmin=(minx pliste)
and xMax=(maxx pliste)
and ymin=(miny pliste)
and yMax=(maxy pliste) in
let xm=xmin-.(0.1)*.(xMax-.xmin)
and xM=xMax+.(0.1)*.(xMax-.xmin)
and ym=ymin-.(0.1)*.(yMax-.ymin)
and yM=yMax+.(0.1)*.(yMax-.ymin) in
let (rx,ry)=
if (yM-.ym)>(100.*.(xM-.xm)) then
((0.),(( (float_of_int(size_y())) *. (xM-.xm) /.(float_of_int(size_x())) )+.(ym-.yM) )/.(2.))
else
if (xM-.xm)>(100.*.(yM-.ym)) then
((( (float_of_int(size_x())) *. (yM-.ym) /.(float_of_int(size_y())) )+.(xm-.xM) )/.(2.),0.)
else
if ((float_of_int(size_x())) *. (yM-.ym) /.(float_of_int(size_y())))>=xM-.xm
then ((( (float_of_int(size_x())) *. (yM-.ym) /.(float_of_int(size_y())) )+.(xm-.xM) )/.(2.),0.)
else ((0.),(( (float_of_int(size_y())) *. (xM-.xm) /.(float_of_int(size_x())) )+.(ym-.yM) )/.(2.)); in
let rep=fenetre (xm-.rx) (xM+.rx) (ym-.ry) (yM+.ry) in
trace_rep rep 10 black;
polygone pliste rep;;
#plot_polygone : p_repere list -> unit = <fun>
Attention: Ces deux fonctions peuvent donner des résultats peu agréables, voir pas de résultat du tout, si la liste de point n’est pas très pertinente, c'est à dire s’il y a certaines disproportions (de grandes valeurs en côtoient des petites) ou si certains points ne sont carrément pas définis. (ex : tracer une exponentielle entre (-10) et 10 donne un résultat extrêmement mauvais alors qu’au contraire, entre (-10) et 2 le résultat et assez agréable). Par conséquent, les fonctions qui vont suivre ne pourront être utilisées si la fonction n’est pas définie (comme pour
quand x<0 ). Quand le nombre de valeurs indéfinies est fini ont peu cependant tracer la courbe (comme pour tan x où les asymptotes seront alors visualisées (cf exemples)), si l’on a pas de résultat, on peu essayer de faire varier le nombre de valeurs calculées car il se peut que l’on soit tombé précisément sur une indéterminée (cas extrêmement rare).
Pour les fonctions classiques, on utilise plot_fun qui reçoit en argument :
let plot_fun f xm xM n=
let pliste= (l_pts_fun f xm xM n) in
plot_polygone pliste;;
#plot_fun : (float -> float) -> float -> float -> int -> unit = <fun>
Pour les fonctions trigonométriques, on utilise plot_para qui reçoit en argument :
let plot_para (f,g) tmin tmax n=
let pliste= (l_pts_para (f,g) tmin tmax n) in
plot_polygone pliste;;
plot_para : (float -> float) * (float -> float) -> float -> float -> int -> unit = <fun>
Pour les fonctions polaires, on utilise plot_polaire qui reçoit en argument :
let plot_polaire f amin amax n=
let pliste= (l_pts_para ((fun x->cos(x)*.f(x)),(fun x->sin(x)*.f(x))) amin amax n) in
plot_polygone pliste;;
plot_polaire : (float -> float) -> float -> float -> int -> unit = <fun>
Les listes de points peuvent nous être données sans être typées en type point_repère. Trois routines existent donc pour effectuer la conversion.
let convert_vect t =
let n=vect_length t and r=ref[ ] in
for i=(n-1) downto 0 do
let (m,n)=t.(i) in r :=[{x=m ;y=n}]@( !r)
done ;
( !r);;
#convert_vect : (float * float) vect -> p_repere list = <fun>
convert_vect convertit un tableau de coordonnées (x,y) en une liste de point_repère.
let rec convert_list l = match l with
|[ ] -> [ ]
|[(a,b)] -> [{x=a ;y=b}]
|r::ll -> (convert_list [r])@(convert_list ll);;
#convert_list : (float * float) list -> p_repere list = <fun>
convert_list convertit une liste de coordonnées (x,y) en une liste de point_repère.
let rec projection l a b = match l with
|[ ] -> []
|[(t)] -> [{x=t.(a-1);y=t.(b-1)}]
|r::ll -> (projection [r] a b)@(projection ll a b);;
#projection : float vect list -> int -> int -> p_repere list = <fun>
projection reçoit en argument une liste de liste de coordonnées et deux entiers qui correspondent aux deux positions des coordonnées qu’on prend dans chaque liste.
Procédures :(précédées de clear_graph() pour effacer les précédents graphiques)
a-1)
plot_fun (fun x->5.*.cos x) (-.8.) (8.) 5000;;
#- : unit = ()

a-2)
plot_fun (fun x->tan x) (-.8.) (8.) 5000;;
#- : unit = ()

b)
plot_para ((fun t->cos (3.*.t)),(fun t->sin (2.*.t))) (0.) (6.29) 5000 ;;
#- : unit = ()

c)
plot_polaire (fun t->log t) (0.) (30.) 5000;;
#- : unit = ()
