Autre > a

Titrea
Postée le05-12-2008
Affichée717
Mini-lien
Description

a

EtatNe contient pas d'erreurs. Ne contient pas d'erreurs.
Code d'insertion
Options
Afficher les numéros de lignes  Mettre la source en plein ecran  Selectionner la source  Partager sur Facebook 
Téléchargement Telecharger en format txt  Telecharger en format pdf
Plein ecran
let verification1 t =
        let lg_t = (vect_length t) - 2 in
        for i = 0 to lg_t do
                let (p,a,b) = t.(i) and (q,c,d) = t.(i+1) in
                if p = q then
                        if a = c & b = d then failwith "MEMES POINTS, MEMES DONNEES"
                        else failwith "MEMES POINTS,DONNEES DIFFERENTES"
        done ;;
       
let verification2 s =
        let lg_s = (vect_length s) - 1 in
        for i = 0 to lg_s do verification1 (s.(i)) done ;;

(* On considerera l'orthographe et la grammaire comme des notions superflues. *)

(*On travaille dans le plan positif d'origine (0, 0) *)
(*Un point (-1, -1) n'existe donc pas et correspond a une absence d'intersecion, ou autre cas d'exception (absence de minimum...)*)
(*Un point est un couple (X, Y). Un polygone de n points est representer par un tableau de n+1 points, avec egalite entre le 1e et le dernier ; deux points successifs etant relies*)
(*Une droite ax + by = c est un triplet (a, b, c))*)
(*Un segment est un couple de points*)

(*****************************************************************************************************)
(*****************************************************************************************************)
(********************************     --->  Acquisition  <---     ************************************)
(*****************************************************************************************************)

(* On notera L la distance de visibilitE maximale (celle au dela de laquelle les mesures ne seront plus prises en compte). *)
(* On utilisera aussi la distance L', inferieure a L mais proche de L pour remplacer le test " =L " par " >= L' ", car les arrondis rendront des points a une distance legerement differente de L. *)
(* Plus generalement, on remplacera les tests d'egalite strictes par des tests d'egalite a epsilon pres (donc par des comparaisons). *)
(* On definit aussi une distance delta caracteristique de l'environement (distance minimale entre 2 coins de l'environement. *)

let L = 99. ;;
let L' = 98.8 ;;
let L'2 = L' *. L' ;;
let epsilon = 0.001 ;;
let epsilon2 = epsilon *. epsilon ;;
let delta = 10. ;;
let delta2 = delta *. delta ;;


(* make_droite : (x1,y1) (x2,y2) -> (a,b,c)         avec ax+by=c l'equation de la droite passant par (x1,y1) et (x2,y2) *)

let make_droite (x1,y1) (x2,y2) =
   if x1 = x2 then (1.,0.,x1) else
      ((y2 -. y1),(x1 -. x2),((y2 *. x1) -. (x2 *. y1)))  ;;


(* inter_drt_drt calcule l'intersection de 2 droites *)

let inter_drt_drt (a,b,c) (a',b',c') =
   if a *. b' = a' *. b then (-1.,-1.) else
   let d = (a *. b') -. (a' *. b) in  
   (((b' *. c) -. (b *. c')) /. d) , (((a *. c') -. (a' *. c)) /. d) ;;


(* inter_sg_drt renvoie le point d'intersection entre le segment (x1, y1) (x2, y2) et la droite d si il y en a un, le point exception (-1,-1) sinon *)

let inter_sg_drt (x1, y1) (x2, y2) d =
   let (x, y) = inter_drt_drt d (make_droite (x1, y1) (x2, y2)) in
   if ((x1 -. x) *. (x2 -. x) < 0. || (y1 -. y) *. (y2 -. y) < 0.) then (x, y) else (-1., -1.) ;;




(* sol_poly a b c : solutions de ax2+bx+c=0 *)

let sol_poly a b c = ((( 0. -. b +. sqrt ( (b *. b) -. (4. *. a *. c) ) ) /. (2. *. a) ),(( 0. -. b -. sqrt ( (b *. b) -. (4. *. a *. c) ) ) /. (2. *. a) )) ;;


(* pt_lim (x,y) d : donne les points de visibilite maximum a droite et a gauche, pour une droite de mesure d *)

let pt_lim (x,y) (a,b,c) =
        let (x1,x2) = sol_poly ( ((a *. a) /. (b *. b)) +. 1.) ((0. -. 2.) *. (x +. a *. ((c /. b) -. y) /. b)) ((x *. x) +. (((c /. b) -. y) *. ((c /. b) -. y)) -. (L *. L) ) in
        ((x1,(c -. (a *. x1)) /. b ),(x2,(c -. (a *. x2)) /. b ));;


(* list_inter renvoie pour l'environnement e, les intersections a droites et a gauche du robot en (x,y), pour une droite de mesure d, ainsi que les points correspondant au maximum de visibilite *)

let list_inter e d (x,y) =
   let (p1,p2) = pt_lim (x,y) d in
   let l1 = ref [p2] and l2 = ref [p1] in
   let N = (vect_length e) - 1 in
   for i = 0 to N do
      let p = e.(i) in
      let M = (vect_length p) - 1 in
      for j = 1 to M do
         let (x',y') = inter_sg_drt (p.(j-1)) (p.(j)) d in
         if not ( (x',y') = (-1.,-1.) ) then
            if x' < x then l1 := (x',y')::(!l1) else  l2 := (x',y')::(!l2)
      done
   done ;
   (!l1,!l2) ;;



(* pt_proche renvoie le point le plus proche d'une liste de points *)

let rec pt_proche (x,y) l =
   match l with
   | [] -> (-1.,-1.)
   | [a] -> a
   | (x1,y1)::Q -> let (x2,y2) = pt_proche (x,y) Q in
                     if ((x1 -. x) *. (x1 -. x)) +. ((y1 -. y) *. (y1 -. y))
                                      < ((x2 -. x) *. (x2 -. x)) +. ((y2 -. y) *. (y2 -. y))
                     then (x1,y1) else (x2,y2) ;;


let acquisition n e (x,y) =
   let pi = acos (-1.) and pi2 = acos (0.) in
   let n' = float_of_int n in
   let l = ref [] and l' = ref [] in
   for k = 1 to n do
      let angle = ((((float_of_int k) *. pi ) -. pi2) /. n') in
      let a = cos angle and b = sin angle in
      let c = (a *. x) +. (b *. y) in
      let (l1,l2) = list_inter e (a,b,c) (x,y) in
      let p1 = pt_proche (x,y) l1 and p2 = pt_proche (x,y) l2 in
      l := (p1::(!l)) ; l' := (p2::(!l'))
   done ;
   (!l)@(!l') ;;

(* Caml travail en radian, mais n'a pas "pi". On le recalcule donc avec prEcision ici (pi), et on note au passage pi2 pour pi/2. *)





(*****************************************************************************************************)
(*****************************************************************************************************)
(*******************************     ---> Cartographie  <---     *************************************)
(*****************************************************************************************************)


       
(* Etant dans la cas d'un deplacement et de mesures parfaits, on choisit de memoriser les limites de l'environnement deja decouvert sous la forme [(P1,V1);(P2,V2);....].
La liste des Pi est la liste, dans le sens antitrigonometrique, des points du polygone en question. On boucle : Le dernier point est le premier.
Vi vaut 1 si le segment (Pi;P(i+1)) correspond a un mur ; et vaut 0 sinon. *)
(* On retiendra en fait une liste de telles listes : il y a toujours une limite exterieure, mais il y aura aussi des limites interieures (ex.: autours d'un obstacle). *)

(* Lors du regroupement de la zone acquise et de la zone connue, on opperera :
- Pour les points a une distance inferieure a la distance maximale de visibilite :
        - l'elargissement des murs connus et/ou l'ajout de nouveaux murs
        - des tests de proximite des extremites des murs modifies ou ajoutes (accompagnes s'il y a lieu de reconnaissances de coins)
- Pour les points a la limite de visibilite :
        - l'elargissement des limites de la zone connue *)

(* L'elargissement des murs connus et/ou l'ajout de nouveaux murs se fera de la maniere suivante :
        - si le point traite P est sur un mur connu : on ne fait rien
        - si le point traite P est dans le prolongement d'un mur connu, et a une distance d'une de ses extremites P' inferieure a delta : on remplace dans la carte P' par P
        - sinon : . si les points successifs P, P', P'' de l'acquisition sont alignes, a une distance inferieure a la distance maximale de visibilite, et separes d'au plus delta : (P,P'') est un mur, on l'ajoute donc a la carte.
                . sinon : on ne peut rien faire de P, qui n'interviendra que dans l'elargissement de la zone connue.
                        Remarque : on pourra, si P est a une distance inferieure a la distance maximale de visibilite, l'indique dans les limites de la zone connue sous la forme (P,2).
                                   (l'indice 2 signifiant alors la presence d'un mur au point P, mais ne liant pas (necessairement) P au point suivant sur la carte)   *)

(* Lors du regroupement de la zone acquise et de la zone connue, il est possible que la nouvelle zone connue contienne en son sein un "trou" (correspondant a un bloc dans l'environnement).
Il faudra alors considerer comme limite de la nouvelle zone connue la limite exterieure de celle-ci ; et traiter la limite interieure afin de calculer le polygone correspondant (et l'ajouter aux polygones acquis).
Le calcule du polygone acquis se fait comme la reconnaissance de coins, mais sans verification de la proximite des extremites des murs connus. *)

(* L'analyse des donnees acquises devra reconnaitre d'abord les droites, puis leurs intersection :
- Reconnaissance de droites :
        Il s'agit (dans le cadre du robot parfait) de remplacer les suites de points alignes (et a une distance inferieure a la distance maximale de visibilite) par les deux points extremaux de cette liste.
        Ces points correspondent en effet a des "murs", dont on ne retiendra que les bornes extremes connues.
        Il faudra de plus transformer la liste des points acquis de sorte a ajouter l'information correspondant au s'il s'agit ou non d'un "mur".
- Reconnaissance de coins :
        Lorsque deux "murs connus" ont leurs extremites a une distance inferieure a delta, on sait alors qu'il sont en realite secants.
        On a alors dans les donnees [.....;(P1,1);(P2,0);(P3,1);(P4,_);.....] avec (dist P2 P3) < delta (les murs en question etant (P1,P2) et (P3,P4).
        On doit alors calculer le point P' d'intersection des murs, et remplacer dans les donnees "(P1,1);(P2,0);(P3,1);(P4,_)" par "(P1,1);(P',1);(P4,_)".   *)

(* Si la limite exterieure de la zone connue est definie dans le sens antitrigonometrique, alors les limites interieures / polygones connus seront definis deans le sens trigonometriques.
Ainsi, la zone connue sera toujours du cote droit de la frontiere. *)


(**********************************************************************************************)
(* --> Algorithme d'obtention de la nouvelle carte, a partir des mesures et de l'ancienne <-- *)
(**********************************************************************************************)

(* R designe la position du robot. *)

(* Rappels :
L'acquisition est sous la forme A=[P(1);P(2);...;P(N)].
La carte initiale est sous la forme C=[|[|(Q(1,1),V(1,1));(Q(1,2),V(1,2));...;(Q(1,M),V(1,M))|];[|(Q(2,1),V(2,1));(Q(2,2),V(2,2));...|];...|] (avec : V(i)=1 <=> (Q(i),Q(i+1)) correspond a un mur.
(L'interet des tableaux est de pouvoir, lorsque l'on obtient une intersection I avec un segment (Q(k),Q(k+1)), memoriser le segment en question en memorisant l'indice k) *)

(* Tout d'abord, on transformera A en le mettant sous la forme A = [(P(1),V(1));(P(2),V(2));...;(P(N),V(N))], ou V(i) vaut 1 si (P(i),P(i+1)) est un mur et vaut 0 sinon ; et ou les points superflus auront ete supprimes. *)

(* Ensuite, on effectuera les remplacements suivants :
- Si dans C on a un mur (Q(i,j),Q(i,j+1)) tel que Q(i,j-1) (resp. Q(i,j+2)) soit se l'autre cote du mur / vers l'exterieur,
        et si on a dans A un point P dans le prolongement direct du mur (Q(i,j),Q(i,j+1)) et avant Q(i,j) (resp. apres Q(i,j+1)),
        alors on remplace dans C Q(i,j) (resp. Q(i,j+1)) par P.
- Idem dans A.
- Si un point P de A est proche a epsilon pres d'un point Q de C, on remplace, dans A, P par A. *)
       
(* Enfin, on mettera parallelement A sous la forme [|(P'(1),P''(1),P'''(1));(P'(2),P''(2),P'''(2));...;(P'(M'),P''(M'),P'''(M'))|] et C sous la forme [|[|(Q'(1,1),Q''(1,1),Q'''(1,1));(Q'(1,2),Q''(1,2),Q'''(1,2));...;(Q'(1,M),Q''(1,M),Q'''(1,M))|];[|(Q'(2,1),Q''(2,1),Q'''(2,1));(Q'(2,2),Q''(2,2),Q'''(2,2));...|];...|].
A et les tableaux de C bouclent, et contiennent dans l'ordre les points initialement dans le tableaux / la liste correspondant(e).
Pour A (resp. pour un tableau de C), on ajoute dans l'ordre et entre ces points les intersections avec les segments de C (resp. A) ainsi que les points de C (resp. A) sur le segment considere. Les nouveaux points sont notes P'(.) (resp. Q'(.)).
Definition de P''(k) et de P'''(k) :
        Si P'(k) est un point de base dans A et n'est pas sur un segment de C :
                Si (P'(k),P'(k+1)) correspond a un mur : P''(k) = 1 et P'''(k) = (-1,-1).
                Sinon : P''(k) = 0 et P'''(k) = (-1,-1).
        Si P'(k) = Q'(i,j) :
                Si (P'(k),P'(k+1)) correspond a un mur : P''(k) = 3 et P'''(k) = (i,j).
                Sinon : P''(k) = 2 et P'''(k) = (i,j).
        Si P'(k) est un point de base dans A et est sur le segment (Q'(i,j),Q'(i,j+1)) de C :
                Si (P'(k),P'(k+1)) correspond a un mur : P''(k) = 5 et P'''(k) = (i,j).
                Sinon : P''(k) = 4 et P'''(k) = (i,j). 
        Si P'(k) est un point de base Q'(i,j) dans C et est sur le segment considere de A initial :
                Si (P'(k),P'(k+1)) correspond a un mur : P''(k) = 7 et P'''(k) = (i,j).
                Sinon : P''(k) = 6 et P'''(k) = (i,j).
        Si P'(k) est un point d'intersection de A avec le segment (Q'(0i,j),Q'(i,j+1)) de C :
                Si (P'(k),P'(k+1)) correspond a un mur : P''(k) = 9 et P'''(k) = (i,j).
                Sinon : P''(k) = 8 et P'''(k) = (i,j).
Definition de Q''(k,h) et de Q'''(k,h) :
        Si Q'(k,h) est un point de base dans C et n'est pas sur un segment de A :
                Si (Q'(k,h),Q'(k,h+1)) correspond a un mur : Q''(k,h) = 1 et Q'''(k,h) = -1.
                Sinon : Q''(k,h) = 0 et Q'''(k,h) = -1.
        Si Q'(k,h) = P'(i) :
                Si (Q'(k,h),Q'(k,h+1)) correspond a un mur : Q''(k,h) = 3 et Q'''(k,h) = i.
                Sinon : Q''(k,h) = 2 et Q'''(k,h) = i. 
        Si Q'(k,h) est un point de base dans C et est sur le segment (P'(i),P'(i+1)) de A :
                Si (Q'(k,h),Q'(k,h+1)) correspond a un mur : Q''(k,h) = 5 et Q'''(k,h) = i.
                Sinon : Q''(k,h) = 4 et Q'''(k,h) = i. 
        Si Q'(k,h) est un point de base P'(i) dans A et est sur le segment considere de C initial :
                Si (Q'(k,h),Q'(k,h+1)) correspond a un mur : Q''(k,h) = 7 et Q'''(k,h) = i.
                Sinon : Q''(k,h) = 6 et Q'''(k,h) = i.
        Si Q'(k,h) est un point d'intersection de C avec le segment (P'(i),P'(i+1)) de A :
                Si (Q'(k,h),Q'(k,h+1)) correspond a un mur : Q''(k,h) = 9 et Q'''(k,h) = i.
                Sinon : Q''(k,h) = 8 et Q'''(k,h) = i.
(!Il y a peut-etre des cas inutils!)    *)

(* On cree en plus la liste LI listant les indices k des intersections et points communs dans A. *)

(* On part de l'intersection / point commun correspondant au premier element de LI.
        On part vers l'exterieur.
        A chaque intersection (hors mur donc) on change de tableau.
        Pour un point commun :
                Tant qu'il y a un mur, on le suit.
                Sinon on part vers l'exterieur.
        Au passage, on otera de LI les intersections / points communs traites. On retiendra aussi les indices des tableaux de C utilises.
        Quand on est retourne au point de depart, on ajoute le tableau ainsi obtenu a la nouvelle carte.
        Si LI n'est pas vide, on recommence.
On ajoute enfin a la nouvelle carte les tableaux de C non utilises. *)







(****************************************************************************************)
(******* --> Fonctions annexes : "C'est bon gueule pas je suis a 2 metres !" <-- ********)
(****************************************************************************************)



(* distance carree entre deux points *)

let dist2 (x, y) (a, b) = (a -. x) *. (a -. x) +. (b -. y) *. (b -. y);;


(* distance entre deux points *)

let dist a b = sqrt (dist2 a b);;



(* distance carree d'un point a une droite *)

let dist_drt2 (a,b,c) (x,y) =
        (a *. x +. b *. y -. c) *. (a *. x +. b *. y -. c) /. (a *. a +. b *. b) ;;


(* distance d'un point a une droite *)

let dist_drt D P = sqrt (dist_drt2 D P) ;;



(****************************************************************************************)
(** --> Fonctions annexes : "OUT !" ; "Mais qu'est-ce que tu fais derriere moi ?!" <-- **)
(****************************************************************************************)
       
(* Rappel : Si la limite exterieure de la zone connue est definie dans le sens antitrigonometrique, alors les limites interieures / polygones connus seront definis deans le sens trigonometriques.
Ainsi, la zone connue sera toujours du cote droit de la frontiere. *)

(* "test_ext A B C" renvoie "true" si et seulement si C est a gauche de (A,B) (donc a l'exterieur d'une frontiere dont (A,B) est segment, si (A,C) n'intersecte pas cette frontiere) *)

let test_ext (xa,ya) (xb,yb) (xc,yc) =
        ((ya -. yc) *. (xb -. xa)) +. ((xc -. xa) *. (yb -. ya)) < 0. ;;

(* "test_sur_seg A B C" teste si C est sur le segment (A,B) *)
       
let test_sur_seg (xa,ya) (xb,yb) (xc,yc) =
        ((dist_drt2 (make_droite (xa,ya) (xb,yb)) (xc,yc)) < epsilon2) & ((xa -. xc) *. (xb -. xc) < 0. || (ya -. yc) *. (yb -. yc) < 0.) ;;

(* "test_prolongement_apres A B C" teste si C est dans le prolongement direct du segment (A,B), et apres B *)   
       
let test_prolongement_apres A B C =
        ((dist2 B C) < delta2) & (test_sur_seg A C B) ;;

(* "test_prolongement_avant A B C" teste si C est dans le prolongement direct du segment (A,B), et avant A *)   
       
let test_prolongement_avant A B C =
        ((dist2 A C) < delta2) & (test_sur_seg C B A) ;;

       
       
       

(*****************************************************************************************)
(********** --> Traitement preliminaire de l'acquisition : "Tiens un mur !" <-- **********)
(*****************************************************************************************)



(* Pour considerer une suite de points successifs comme un mur, il faut qu'ils soient tous alignes et dans la zone visible, et que deux points successifs soient ecartes d'au plus delta. *)
(* Pour l'instant, l'acquisition est donnee sous forme de liste de point. *)

let rec recon_parpins robot acquis =
        match acquis with
        | [] -> []
        | [a] -> [(a,0)]
        | [a;b] -> [(a,0);(b,0)]
        | a::b::c::suite -> let mur = make_droite a c in
                        if (dist_drt2 mur b) > epsilon2
                        then (a,0)::(recon_parpins robot (b::c::suite))
                        else
                        begin
                                let S = ref suite in
                                let bout = ref c in
                                let test = ref true in
                                while (not (!S = [])) & !test do
                                        let p = hd (!S) in
                                        if ( (dist2 p (!bout)) < delta2 ) & ( (dist_drt2 mur p) < epsilon2 ) & ((dist2 p robot) < L'2 )
                                                then begin bout := p ; S := tl (!S) end
                                                else test := false
                                done ;
                                (a,1)::(!bout,0)::(recon_parpins robot !S)
                        end ;;

(* Cette fonction doit etre appliquee sur une permutation cyclique de l'acquisition commencant par un point tel que l'on soit sur qu'il n'est pas sur un mur reperable. *)
(* Les fonctions suivantes permettent donc de remplacer (avec "ordonne acquis robot_pos") la liste de points acquis par une transposition circulaire de ces points (de sorte qu'ils demeurrent tries dans le sens antitrigonometrique (?) par rapport a la position du robot) debutant par un point a la distance maximale de visibilite.
On est ainsi assure que la raconnaissance de droites ne debutera pas sur un point situe au milieu d'un "mur".
Dans le cas ou il n'y a pas de point a la distance maximale de visibilite, l'environnement est alors totalement connu. On s'occupera plus tard de gerer ce cas particulier. *)

let rec cherche_pivot acquis robot_pos =
        match acquis with
                [] -> failwith "Oh c'est un vrai !"
                |a::b when (dist2 a robot_pos > L'2) -> 0
                |a::b::c::d when not (test_sur_seg a c b) -> if d = [] then 2 else
                                                                                        if test_sur_seg b c (hd d) then 1 else 2
                |a::b -> 1 + (cherche_pivot b robot_pos);;

let rec degage n l =
                match (n, l) with
                        (0, a) -> a
                        |(x, []) -> []
                        |(x, a::b) -> degage (x - 1) b ;;

let rec extrait n l =
                match (n, l) with
                        (0, a) -> []
                        |(x, []) -> failwith "Faut pas respirer la compote, ca fait tousser"
                        |(x, a::b) -> a :: (extrait (x - 1) b) ;;
                               
let permut acquis n =
        (degage n acquis)@(extrait n acquis);;         

let ordonne acquis robot_pos = permut acquis (cherche_pivot acquis robot_pos);;

(* Le traitement prealable de l'acquisition se fera don avec recon_mur *)

let recon_mur robot acquis =
        recon_parpins robot (ordonne acquis robot) ;;


(* A partir de la, on utilisera A sous forme de tableau. On cree donc "list_in_vect", qui pour une liste renvoie le tableau des elements de cette liste et bouclant. *)

let list_in_vect liste =
        let n = list_length liste in
        let tableau = make_vect (n+1) (hd liste) in
        let liste2 = ref (tl liste) in
        for i = 1 to (n-1) do
                tableau.(i) <- (hd (!liste2)) ; liste2 := tl (!liste2)
        done ;
        tableau ;;

       
       
       

(****************************************************************************************)
(******* --> Remplacements : "Tu depasses les bornes des limites (Maurice) !" <-- *******)
(****************************************************************************************)
       
let remplacements robot acquis carte =
        let lg_acquis = (vect_length acquis) - 2  and lg_carte = (vect_length carte) - 1 in
        for k = 0 to lg_acquis do
                let (Pi,V) = acquis.(k) in
                let (Pi',V') = acquis.(k+1) in
                let P = ref Pi and P' = ref Pi' in
                for i = 0 to lg_carte do
                        let frontiere = carte.(i) in
                        let lg_frontiere = (vect_length frontiere) - 2 in
                        for j = 0 to lg_frontiere do
                                let (Qi,W) = frontiere.(j) in
                                let (Qi',W') = frontiere.(j+1) in
                                let Q = ref Qi and Q' = ref Qi' in
                                if (W = 1) & (test_ext (!Q) (!Q') (!P')) & (test_sur_seg (!Q) (!Q') (!P)) then
                                        begin acquis.(k) <- ((!Q'),V) ; P := !Q' end ;
                                if (V=1) & ((dist2 (!P) robot) < L'2) & (test_ext (!P) (!P') (!Q')) & (test_sur_seg (!P) (!P') (!Q)) then
                                        begin frontiere.(j) <- ((!P'),W) ; Q := !P' end ;
                                if W = 1 then
                                        begin
                                        if j > 0 then
                                                begin
                                                let (Q1,W1) = frontiere.(j-1) in
                                                if (test_ext (!Q) (!Q') Q1) & (test_prolongement_avant (!Q) (!Q') (!P)) then frontiere.(j) <- ((!P),W)
                                                end ;
                                        if j < lg_frontiere then
                                                begin
                                                let (Q2,W2) = frontiere.(j+2) in
                                                if (test_ext (!Q) (!Q') Q2) & (test_prolongement_apres (!Q) (!Q') (!P)) then frontiere.(j+1) <- ((!P),W')
                                                end
                                        end ;
                                if (V = 1) & ((dist2 (!P) robot) < L'2) then
                                        begin
                                        if k > 0 then
                                                begin
                                                let (P1,V1) = acquis.(k-1) in
                                                if (test_ext (!P) (!P') P1) & (test_prolongement_avant (!P) (!P') (!Q)) then acquis.(k) <- ((!Q),V)
                                                end ;
                                        if k < lg_acquis then
                                                begin
                                                let (P2,V2) = acquis.(k+2) in
                                                if (test_ext (!P) (!P') P2) & (test_prolongement_apres (!P) (!P') (!Q)) then acquis.(k+1) <- ((!Q),V')
                                                end
                                        end ;
                                if (dist2 (!P) (!Q)) < epsilon2 then
                                        begin
                                        acquis.(k) <- ((!Q),V) ;
                                        if k = 0 then acquis.(lg_acquis + 1) <- ((!Q),0)
                                        end
                        done
                done
        done ;;

(* let remplacements robot acquis carte =
        let lg_acquis = (vect_length acquis) - 2  and lg_carte = (vect_length carte) - 1 in
        for k = 0 to lg_acquis do
                let (P,V) = acquis.(k) in
                for i = 0 to lg_carte do
                        let frontiere = carte.(i) in
                        let lg_frontiere = (vect_length frontiere) - 2 in
                        for j = 0 to lg_frontiere do
                                let (Q,W) = frontiere.(j) in
                                if W = 1 then
                                        begin
                                        let (Q',W') = frontiere.(j+1) in
                                        if j > 0 then
                                                begin
                                                let (Q1,W1) = frontiere.(j-1) in
                                                if (test_ext Q Q' Q1) & (test_prolongement_avant Q Q' P) then frontiere.(j) <- (P,W)
                                                end ;
                                        if j < lg_frontiere then
                                                begin
                                                let (Q2,W2) = frontiere.(j+2) in
                                                if (test_ext Q Q' Q2) & (test_prolongement_apres Q Q' P) then frontiere.(j+1) <- (P,W')
                                                end
                                        end ;
                                if (V = 1) & ((dist2 P robot) < L'2) then
                                        begin
                                        let (P',V') = acquis.(k+1) in
                                        if k > 0 then
                                                begin
                                                let (P1,V1) = acquis.(k-1) in
                                                if (test_ext P P' P1) & (test_prolongement_avant P P' Q) then acquis.(k) <- (Q,V)
                                                end ;
                                        if k < lg_acquis then
                                                begin
                                                let (P2,V2) = acquis.(k+2) in
                                                if (test_ext P P' P2) & (test_prolongement_apres P P' Q) then acquis.(k+1) <- (Q,V')
                                                end
                                        end ;
                                if (dist2 P Q) < epsilon2 then
                                        begin
                                        acquis.(k) <- (Q,V) ;
                                        if k = 0 then acquis.(lg_acquis + 1) <- (Q,0)
                                        end
                        done
                done
        done ;; *)
       
       
(* Cette fonction "remplacements" effectue les remplacements decrits dans l'algorithme, et ne renvoit donc rien ( ... -> UNIT ) *)
       
       
       
       
       
       
       
(****************************************************************************************)
(********************* --> Fonction annexe : "Reinsertion" <-- **************************)
(****************************************************************************************)

(* "ordre_sur_seg A B C D", a utiliser pour C et D sur le segment (A,B), renvoie "true" si A,C,D,B sont alignes dans cet ordre, "false" sinon (cad si A,D,C,B sont alignes dans cet ordre) *)

let ordre_sur_seg (xa,ya) (xb,yb) (xc,yc) (xd,yd) =
        if xb > (xa +. epsilon) then xd > xc else
        if xa > (xb +. epsilon) then xc > xd else
        if yb > ya then yd > yc else
        yc > yd ;;

(* L'utilisation de epsilon permet de s'assurer que la droite n'apparait pas comme verticale qu'a cause d'approximations. *)

(* "insert_seg A B L P" renvoie la liste L de points du segment (A,B) dans laquelle on a ajoute P de sorte que L, supposee initiallement triee par ordre des points sur (A,B), demeurre ainsi triee. *)

(* let rec insert_seg A B L P =
        match L with
        | [] -> [P]
        | Q::queue -> let (P',a,b) = P and (Q',c,d) = Q in
                                        if P' = Q' then (print_int a ; print_string " " ; print_int c ; L) else
                                        if ordre_sur_seg A B P' Q' then P::L else Q::(insert_seg A B queue P) ;; *)
                                       
let rec insert_seg A B L (P,a,b) =
        match L with
        | [] -> [(P,a,b)]
        | (Q,c,d)::queue -> if P = Q
                                                then (print_string "!" ; print_string (string_of_bool (a = c)) ; print_string "-" ; print_string (string_of_bool (b = d)) ; print_string "!" ; (P,a,b)::queue )
                                                else
                                                if ordre_sur_seg A B P Q then (P,a,b)::L else (Q,c,d)::(insert_seg A B queue (P,a,b)) ;;

(* On ne prend pas la peine de creer un programme plus performant car on peut considerer le nombre d'intersections sur un meme segment comme assez faible pour que le temps alors pris demeurre negligeable face au temps prix pour le reste. *)
(* P et les points de L sont en realite ici des triplets (point,int,int) *)







(*****************************************************************************************)
(********************** --> Transformation croisee de A et de C <-- **********************)
(*****************************************************************************************)

(* Dans un premier temps, pour A = [|P(1);P(2);...;P(N)|], on calculera le tableau TA = [|L(1);L(2);...;L(N-1)|], ou L(i) designe la liste triee des intersections de (P(i),P(i+1)) avec C.
Paralellement, pour C = [|[|(Q(1,1),V(1,1));(Q(1,2),V(1,2));...;(Q(1,M),V(1,M))|];[|(Q(2,1),V(2,1));(Q(2,2),V(2,2));...|];...|], on calculera le tableau de tableaux TC = [|[L(1,1);L(1,2);...];[...];...|], ou L(i,j) designe la liste triee des intersections de (P(i,j),P(i,j+1)) avec A.
Les points de ces listes seront en realite les triplets evoques lors de la description de l'algorithme. *)
(* "tab_intersections A C" donne (TA,TC,nombre d'elements distincts de A et TA,tableaux des nombres d'elements distincts d'un tableau de C et du tableau de TC correspondant).
Ces 2 nombres serviront a la creation de A et C transformes. *)

let tab_intersections acquis carte =
        let lg_acquis = (vect_length acquis) - 1 and lg_carte = (vect_length carte) in
        let inter_acquis = make_vect lg_acquis [] and inter_carte = make_vect lg_carte [||] in
        let nbr_acquis = ref lg_acquis and nbrs_carte = make_vect lg_carte 0 in
        for i = 0 to (lg_carte - 1) do
                let frontiere = carte.(i) in
                let lg_frontiere = (vect_length frontiere) - 1 in
                inter_carte.(i) <- make_vect lg_frontiere [] ;
                let Ti = inter_carte.(i) and nbr_frontiere = ref lg_frontiere in
                for j = 0 to (lg_frontiere - 1) do
                        let (Q,W) = frontiere.(j) and (Q',W') = frontiere.(j+1) in
                        let Dfrontiere = make_droite Q Q' in
                        for k = 0 to (lg_acquis - 1) do
                                let (P,V) = acquis.(k) and (P',V') = acquis.(k+1) in
                                if P = Q then
                                        begin
                                        Ti.(j) <- (insert_seg Q Q' (Ti.(j)) (Q,2+W,k)) ;
                                        inter_acquis.(k) <- (insert_seg P P' (inter_acquis.(k)) (P,2+V,(i,j)))
                                        end
                                        else
                                if not (P = Q) then
                                begin
                                if test_sur_seg Q Q' P then
                                        begin
                                        Ti.(j) <- (insert_seg Q Q' (Ti.(j)) (P,6+W,k)) ; nbr_frontiere := !nbr_frontiere + 1 ;
                                        inter_acquis.(k) <- (insert_seg P P' (inter_acquis.(k)) (P,4+V,(i,j)))
                                        end
                                        else
                                if test_sur_seg P P' Q then
                                        begin
                                        Ti.(j) <- (insert_seg Q Q' (Ti.(j)) (Q,4+W,k)) ;
                                        inter_acquis.(k) <- (insert_seg P P' (inter_acquis.(k)) (Q,6+V,(i,j))) ; nbr_acquis := !nbr_acquis + 1
                                        end
                                        else
                                        begin
                                let I = inter_drt_drt Dfrontiere (make_droite P P') in
                                if (test_sur_seg P P' I) & (test_sur_seg Q Q' I) & (not (P' = Q')) then
                                        begin
                                        Ti.(j) <- insert_seg Q Q' (Ti.(j)) (I,8+W,k) ; nbr_frontiere := !nbr_frontiere + 1 ;
                                        inter_acquis.(k) <- insert_seg P P' (inter_acquis.(k)) (I,8+V,(i,j)) ; nbr_acquis := !nbr_acquis + 1
                                        end
                                        end
                                end
                        done
                done ;
                nbrs_carte.(i) <- !nbr_frontiere
        done ;
        (inter_acquis,inter_carte,!nbr_acquis,nbrs_carte) ;;

(*A partir d'ici, les tableaux ne bouclent plus. *)

(*La fonction suivante remplace les elements du tableau, a partir de celui d'indice k, par ceux de la liste, et renvoie le nombre d'elements de la liste.*)

let rec list_inside_vect liste tableau k =
        match liste with
        | [] -> 0
        | a::q -> (tableau.(k) <- a ; (list_inside_vect q tableau (k+1))+1 ) ;;

(* On ecrit maintenant la fonction "transformation acquis carte" renvoyant (A,C,origin_A,origin_C), avec A et C transformes comme decrit, et origin_A et origin_C les tableaux donnant les nouvelles positions dans A et C des points initiaux.
Ces positions permetterons d'obtenir plus rapidement, pour un point commun dans un tableau, la position de ce point dans l'autre tableau.*)

let transformation acquis carte =
                        print_string "transf " ;
        let (TA,TC,nbrA,nbrsC) = (tab_intersections acquis carte) in
        let lg_acquis = (vect_length acquis) - 1 and lg_carte = (vect_length carte) - 1 in
        let A = make_vect nbrA ((0.,0.),0,(0,0)) and C = make_vect (lg_carte + 1) [||] in
        let origin_A = make_vect lg_acquis 0 and origin_C = make_vect (lg_carte + 1) [||] in
        (* calcule de A et de origin_A*)
        let k = ref 0 in
        for k' = 0 to (lg_acquis - 1) do
                let L = TA.(k') and (P,V) = acquis.(k') in
                A.(!k) <- (P,V,(-1,-1)) ;
                origin_A.(k') <- !k ;
                k := !k + 1 ;
                if not (L=[]) then
                        let (P',V',V'') = hd L in
                        if P = P' then k := !k - 1 ;
                k := (list_inside_vect L A !k) + !k ;
        done ;
        (* calcule de C *)
        for i = 0 to lg_carte do
                let frontiere = carte.(i) and Tfrontiere = TC.(i) in
                let lg_frontiere = (vect_length frontiere) -1 in
                C.(i) <- make_vect (nbrsC.(i)) ((0.,0.),0,0) ;
                origin_C.(i) <- make_vect lg_frontiere 0 ;
                let nouv_frontiere = C.(i) and origin_frontiere = origin_C.(i) in
                let j = ref 0 in
                for j' = 0 to (lg_frontiere - 1) do
                        let L = Tfrontiere.(j') and (P,V) = frontiere.(j') in
                        nouv_frontiere.(!j) <- (P,V,-1) ;
                        origin_frontiere.(j') <- !j ;
                        j := !j + 1 ;
                        if not (L=[]) then
                                let (P',V',V'') = hd L in
                                if P = P' then j := !j - 1 ;
                        j := (list_inside_vect L nouv_frontiere !j) + !j ;
                done
        done ;
        (* rendu du resultat *)
                        print_string "- transf' " ;
        (A,C,origin_A,origin_C) ;;


       
(* On modifie maintenant ce resultat pour que les indices accompagnant les points communs correspondent a leur position dans l'autre tableau. *)

let rec trouve tableau P n =
        let (Q,a,b) = tableau.(n) in
        if P = Q then n else trouve tableau P (n+1) ;;
(* -> cherche P dans le tableau en commencant au rang n *)

let precise_indices (A,C,origin_A,origin_C) =
        let lg_A = (vect_length A) - 1 and lg_C = (vect_length C) - 1 in
        (* travail sur A  *)
        for k = 0 to lg_A do
                let (P,V,(i,j)) = A.(k) in
                if V > 1 then A.(k) <- (P,V,(i,(trouve (C.(i)) P (origin_C.(i).(j)))))
        done ;
        (* travail sur C *)
        for i = 0 to lg_C do
                let frontiere = C.(i) in
                let lg_frontiere = (vect_length frontiere) - 1 in
                for j = 0 to lg_frontiere do
                        let (P,V,k) = frontiere.(j) in
                        if V > 1 then frontiere.(j) <- (P,V,(trouve A P (origin_A.(k))))
                done
        done ;
        (A,C) ;;

let transformation_ultime acquis carte =
        precise_indices (transformation acquis carte) ;;

       
       
       
       

(*****************************************************************************************)
(************ --> Exploitation de (A,C) : "Follow the yellow break road" <-- *************)
(*****************************************************************************************)

(* Il faudra et suffira de traiter tous les points communs. On retiendra donc un tableau "traites" de le taille celui de A, definit comme suit :
Si A.(i) est traite (ou point initial de A), traite.(i) = 1.
Si A.(i) est a traiter, traite.(i) = 0. *)



let rec parcours_traites traites lg_A n =
        if n > lg_A then -1 else
        if traites.(n) = 0 then n else parcours_traites traites lg_A (n+1) ;;

let cartographie A C =
                        print_string " --  carto" ;
        let lg_A = (vect_length A) - 1 and lg_C = (vect_length C) - 1 in
        let nouvelle_carte = ref [] in
        (* calcule des longueurs des frontieres *)
        let lg_front = make_vect (lg_C + 1) 0 in
        let rec_max = ref 0 in (* *)
        for i = 0 to lg_C do
                lg_front.(i) <- (vect_length (C.(i))) ;
                rec_max := !rec_max + vect_length (C.(i)) (* *)
        done ;
        (* creation de "traites" *)
        let traites = make_vect (lg_A + 1) 0 in
        for i = 0 to lg_A do
                let (P,V,V') = A.(i) in
                if V < 2 then traites.(i) <- 1
        done ;
        (* creation de "frontieres_passees" *)
        let frontieres_passees = make_vect (lg_C + 1) 0 in
        (* parcours de A et de C *)
        let depart = ref (parcours_traites traites lg_A 0) in
        while !depart > -1 do
                let nouvelle_frontiere = ref [] in
                let (P0,V0,(i0,j0)) = A.(!depart) in
                let (Q0,W0,k0) = C.(i0).(j0) in
                let P = ref P0 and V = ref V0 and W = ref W0 and k = ref (!depart) and i = ref i0 and j = ref j0 in
                let t = ref 0 in
                let recur = ref 0 in (* *)
                while (not (!P = P0)) or (!t = 0) do
                        recur := !recur + 1 ; (* *)
                        t := 1 ;
                        if !i = -1 then
                                begin
                                nouvelle_frontiere := (!P,(!V mod 2))::(!nouvelle_frontiere) ;
                                k := (!k + 1) mod (lg_A + 1) ;
                                let (a,b,(c,d)) = A.(!k) in P := a ; V := b ; i := c ; j := d ;
                                if !i > -1 then
                                        begin let (a',b',c') = C.(!i).(!j) in W := b' end
                                end
                        else
                        if !k = -1 then
                                begin
                                nouvelle_frontiere := (!P,(!W mod 2))::(!nouvelle_frontiere) ;
                                frontieres_passees.(!i) <- 1 ;
                                j := (!j + 1) mod (lg_front.(!i)) ;
                                let (a',b',c') = C.(!i).(!j) in P := a' ; W := b' ; k := c' ;
                                if !k > -1 then
                                        begin let (a,b,(c,d)) = A.(!k) in V := b end
                                end
                        else
                        if ((!W mod 2) = 1) then
                                begin
                                nouvelle_frontiere := (!P,1)::(!nouvelle_frontiere) ;
                                traites.(!k) <- 1 ;
                                frontieres_passees.(!i) <- 1 (* ?!?!?!?!? *) ;
                                j := (!j + 1) mod (lg_front.(!i)) ;
                                let (a',b',c') = C.(!i).(!j) in P := a' ; W := b' ; k := c' ;
                                if !k > -1 then
                                        begin let (a,b,(c,d)) = A.(!k) in V := b end
                                end
                        else
                        if ((!V mod 2) = 1) then
                                begin
                                nouvelle_frontiere := ((!P),1)::(!nouvelle_frontiere) ;
                                traites.(!k) <- 1 ;
                                k := (!k + 1) mod (lg_A + 1)  ;
                                let (a,b,(c,d)) = A.(!k) in P := a ; V := b ; i := c ; j := d ;
                                if !i > -1 then
                                        begin let (a',b',c') = C.(!i).(!j) in W := b' end
                                end
                        else
                        let (P',V',(i',j')) = A.(!k + 1) and (Q',W',k') = C.(!i).(!j + 1) in
                        if test_ext !P P' Q' then
                                begin
                                nouvelle_frontiere := (!P,(!W mod 2))::(!nouvelle_frontiere) ;
                                frontieres_passees.(!i) <- 1 (* ?!?!?!?!? *) ;
                                traites.(!k) <- 1 ;
                                j := (!j + 1) mod (lg_front.(!i)) ;
                                P := Q' ; W := W' ; k := k' ;
                                if !k > -1 then
                                        begin let (a,b,(c,d)) = A.(!k) in V := b end
                                end
                        else
                                begin
                                nouvelle_frontiere := (!P,(!V mod 2))::(!nouvelle_frontiere) ;
                                traites.(!k) <- 1 ;
                                k := (!k + 1) mod (lg_A + 1)  ;
                                P := P' ; V := V' ; i := i' ; j := j' ;
                                if !i > -1 then
                                        begin let (a',b',c') = C.(!i).(!j) in W := b' end
                                end
                done ;
                nouvelle_carte := (!nouvelle_frontiere)::(!nouvelle_carte) ;
                depart := (parcours_traites traites lg_A (!depart))
        done ;
        (* donnee des resultats, avec ajout des frontieres non croisees *)
        let nbr_front = ref 0 in
        for i = 0 to lg_C do
                nbr_front := !nbr_front + 1 - frontieres_passees.(i)
        done ;
        let lg_nC = (list_length (!nouvelle_carte)) - 1 in
        let nouv_C = make_vect (lg_nC + 1 + !nbr_front) [||] in
        for i = 0 to lg_nC do
                nouv_C.(i) <- list_in_vect (rev (hd (!nouvelle_carte))) ;
                nouvelle_carte := tl (!nouvelle_carte)
        done ;
        let i = ref (lg_nC + 1) in
        for i' = 0 to lg_C do
                if frontieres_passees.(i') = 0 then
                        begin
                        let lg_frontiere = lg_front.(i') in
                        let frontiere = C.(i') and frontiere_pure = make_vect lg_frontiere ((0.,0.),0) in
                        for j = 0 to (lg_frontiere - 1) do
                                let (P,V,k) = frontiere.(j) in frontiere_pure.(j) <- (P,V)
                        done ;
                        nouv_C.(!i) <- frontiere_pure ;
                        i := !i + 1
                        end
        done ;
                        print_string " - carto' " ;
        nouv_C ;;
       

       
       


(*****************************************************************************************)
(** --> Reconnaissance des coins - Simplification des segments : "Coin Coin Coin !" <-- **)
(*****************************************************************************************)


let simplifier frontiere =
        let lg_frontiere = (vect_length frontiere) - 1 in
        let retires = make_vect (lg_frontiere + 1) 0 and nbr_restant = ref lg_frontiere in
        (* reperage des points a oter, remplacement des coins les intersections *)
        for i1 = 0 to (lg_frontiere - 1) do
                let i2 = ((i1 + 1) mod (lg_frontiere)) and i3 = ((i1 + 2) mod (lg_frontiere)) and i4 = ((i1 + 3) mod (lg_frontiere)) in
                let (P1,V1) = frontiere.(i1) and (P2,V2) = frontiere.(i2) and (P3,V3) = frontiere.(i3) in
                if (V1 = V2) & (test_sur_seg P1 P3 P2) then
                        begin
                        retires.(i2) <- 1 ; nbr_restant := !nbr_restant - 1
                        end ;
                if (V1 = 1) & (V2 = 0) & (V3 = 1) & ((dist2 P2 P3) < delta2) then
                        begin
                        retires.(i2) <- 1 ; nbr_restant := !nbr_restant - 1 ;
                        let (P4,V4) = frontiere.(i4) in
                        let I = (inter_drt_drt (make_droite P1 P2) (make_droite P3 P4)) in
                        frontiere.(i3) <- (I,1) ;
                        if i3 = 0 then frontiere.(lg_frontiere) <- (I,1) ;
                        end
        done ;
        (*reecriture de la frontiere *)
        let nouvelle_frontiere = make_vect (!nbr_restant + 1) ((0.,0.),0) in
        let k = ref 0 in
        for i = 0 to lg_frontiere do
                if retires.(i) = 0 then
                        begin nouvelle_frontiere.(!k) <- frontiere.(i) ; k :=!k + 1 end ;
        done ;
        nouvelle_frontiere.(!nbr_restant) <- nouvelle_frontiere.(0) ;
        nouvelle_frontiere ;;


let simplification carte =
        let lg_carte = (vect_length carte) - 1 in
        for i = 0 to lg_carte do
                carte.(i) <- (simplifier carte.(i)) done ;;

(* Cette simplification est de type ...->UNIT *)





(*****************************************************************************************)
(******************* --> Donnee des resultats pour Mathematica <-- ***********************)
(*****************************************************************************************)

(* Graphics[{{Thick, Hue[1],Line[{{1, 1}, {2, 6}, {5, 2}, {1, 1}}]},{Thick, Hue[.5],Line[{{2, 1}, {5, 5}}]}}] *)

let print_point (x,y) =
        print_string "{" ; print_float x ; print_string "," ; print_float y ; print_string "}" ;;

let vect_in_line couleur tableau =
        let lg_tableau = (vect_length tableau) - 1 in
        print_string "{Thick, Hue[" ; print_float couleur ; print_string "],Line[{" ;
        for i = 0 to lg_tableau do
                print_point tableau.(i) ;
                if i < lg_tableau then print_string ","
        done ;
        print_string "}]}" ;;

let list_in_line couleur liste =
        let liste2 = ref liste in
        print_string "{Thick, Hue[" ; print_float couleur ; print_string "],Line[{" ;
        while not (!liste2 = []) do
                print_point (hd (!liste2)) ;
                liste2  := tl (!liste2) ;
                if not (!liste2 = []) then print_string ","
        done ;
        print_string "}]}" ;;

let frontiere_in_line couleur_mur couleur_inconnu frontiere =
        let lg_frontiere = (vect_length frontiere) - 2 in
        for i = 0 to lg_frontiere do
                let (P,V) = frontiere.(i) and (P',V') = frontiere.(i+1) in
                print_string "{Thick, Hue[" ;
                if V = 1 then print_float couleur_mur else print_float couleur_inconnu ;
                print_string "],Line[{" ;
                print_point P ; print_string "," ;  print_point P' ;
                print_string "}]}" ;
                if i < lg_frontiere then print_string ","
        done ;;

let graphic_carte c_env c_rob c_mur c_inc environnement robot carte =
        let lg_environnement = (vect_length environnement) - 1 in
        let lg_carte = (vect_length carte) - 1 in
        print_string "Graphics[{" ;
        for i = 0 to lg_environnement do
                vect_in_line c_env environnement.(i) ;
                print_string ","
        done ;
        list_in_line c_rob [robot ; robot] ;
        for i = 0 to lg_carte do
                print_string "," ;
                frontiere_in_line c_mur c_inc carte.(i)
        done ;
        print_string "}]" ; print_newline () ;;
       
let graphic_carte_acquis c_env c_rob c_mur c_inc c_acquis environnement robot carte acquis =
        let lg_environnement = (vect_length environnement) - 1 in
        let lg_carte = (vect_length carte) - 1 in
        print_string "Graphics[{" ;
        for i = 0 to lg_environnement do
                vect_in_line c_env environnement.(i) ;
                print_string ","
        done ;
        list_in_line c_rob [robot ; robot] ;
        for i = 0 to lg_carte do
                print_string "," ;
                frontiere_in_line c_mur c_inc carte.(i)
        done ;
        print_string "," ; list_in_line c_acquis acquis ;
        print_string "}]" ; print_newline () ;;





(*****************************************************************************************)
(************************** --> Cas de la teleportation <-- ******************************)
(*****************************************************************************************)


let destination carte =
        let lg_carte = vect_length carte in
        let D = ref (-1.,-1.) in
        let i = ref 0 in
        while (!i < lg_carte) & (!D = (-1.,-1.)) do
                let frontiere = carte.(!i) in
                let lg_frontiere = (vect_length frontiere) - 1 in
                let j = ref 0 in
                while (!j < lg_frontiere) & (!D = (-1.,-1.)) do
                        let ((x,y),V) = frontiere.(!j) in
                        if V = 0 then
                                begin
                                let ((x',y'),V') = frontiere.(!j + 1) in
                                D := ( ((x +. x') /. 2.) +. delta *. (y' -. y) /. (dist (x,y) (x',y')) , ((y +. y') /. 2.) +. delta *. (x -. x') /. (dist (x,y) (x',y')) )
                                end ;
                        j := !j + 1
                done ;
                i := !i + 1
        done ;
        !D ;;

let explore nbr_capteurs (c1,c2,c3,c4,c5) environnement carte robot =
        let acquis = (acquisition nbr_capteurs environnement robot) in
        graphic_carte_acquis c1 c2 c3 c4 c5 environnement robot carte acquis ;
        print_newline () ;
        let acquis2 = (list_in_vect (recon_mur robot acquis)) in
        remplacements robot acquis2 carte ;
        let (A,C) = transformation_ultime acquis2 carte in
        verification1 A ; verification2 C ; (* *)
        let nouvelle_carte = cartographie A C in
        simplification nouvelle_carte ;
        graphic_carte c1 c2 c3 c4 environnement robot nouvelle_carte ;
        nouvelle_carte ;;
       
let exploration nbr_capteurs (c1,c2,c3,c4,c5) environnement robot0 iterations_max =
        let acquis0 = acquisition nbr_capteurs environnement robot0 in
        graphic_carte_acquis c1 c2 c3 c4 c5 environnement robot0 [|[||]|] acquis0 ;
        let acquis1 = [|list_in_vect (recon_mur robot0 acquis0)|] in
        simplification acquis1 ;
        let carte = ref acquis1 in
        graphic_carte c1 c2 c3 c4 environnement robot0 !carte ;
        let D = ref (destination !carte) in
        let k = ref 0 in
        while ( !k < iterations_max ) & not ( !D = (-1.,-1.)) do
                k := !k + 1 ;
                print_newline () ; print_newline () ;
                carte := (explore nbr_capteurs (c1,c2,c3,c4,c5) environnement !carte !D) ;
                D := (destination !carte)
        done ;
        if !D = (-1.,-1.) then "carte obtenue" else "carte incomplete" ;;

let environnement = [|[|0.,0.;50.,0.;50.,40.;40.,50.;0.,50.;0.,0.|]|] and robot0 = (20.,20.) in exploration 100 (0.2,0.4,0.6,0.8,1.) environnement robot0 10 ;;

let environnement = [|[|0.,0.;400.,0.;400.,350.;0.,350.;0.,0.|];[|150.,75.;225.,50.;225.,125.;150.,125.;150.,75.|];[|275.,75.;325.,100.;325.,200.;275.,275.;225.,175.;275.,200.;275.,75.|];[|125.,175.;125.,250.;150.,300.;75.,275.;50.,200.;100.,225.;125.,175.|]|] and robot0 = (175.,200.) in exploration 100 (0.2,0.4,0.6,0.8,1.) environnement robot0 10 ;;

let environnement = [|[|0.,0.;75.,0.;75.,100.;125.,100.;125.,0.;175.,0.;175.,175.;75.,175.;75.,225.;125.,225.;125.,275.;0.,275.;0.,0.|]|] and robot0 = (25.,25.) in exploration 100 (0.2,0.4,0.6,0.8,1.) environnement robot0 10 ;;

(* Exemple : environnement = [|[|0.,0.;400.,0.;400.,350.;0.,350.;0.,0.|];[|150.,75.;225.,50.;225.,125.;150.,125.;150.,75.|];[|275.,75.;325.,100.;325.,200.;275.,275.;225.,175.;275.,200.;275.,75.|];[|125.,175.;125.,250.;150.,300.;75.,275.;50.,200.;100.,225.;125.,175.|]|]
robot0 = (175.,200.) *)
let environnement = [|[|0.,0.;400.,0.;400.,350.;0.,350.;0.,0.|];[|150.,75.;225.,50.;225.,125.;150.,125.;150.,75.|];[|275.,75.;325.,100.;325.,200.;275.,275.;225.,175.;275.,200.;275.,75.|];[|125.,175.;125.,250.;150.,300.;75.,275.;50.,200.;100.,225.;125.,175.|]|] and robot0 = (175.,200.) in exploration 100 (0.2,0.4,0.6,0.8,1.) environnement robot0 10 ;;
let environnement = [|[|0.,0.;75.,0.;75.,100.;125.,100.;125.,0.;175.,0.;175.,175.;75.,175.;75.,225.;125.,225.;125.,275.;0.,275.;0.,0.|]|] and robot0 = (25.,25.) in exploration 100 (0.2,0.4,0.6,0.8,1.) environnement robot0 10 ;;



(* Pbs : precise_indices , cartographie *)