program projet; var i,j:integer, h,v:char; (* Les variables h et v sont utilis‚es pour comparer le sens des segments*) begin (************************************************************) h:='h';(* Initialisation des variables h et v *) v:='v'; pref iiuwgraph block var t,tab:arrayof segment;(* Le tableau tab contient les segments saisis soit au clavier, soit … l'aide de la souris ou soit cr‚er al‚atoirement, et le tableau t est le r‚sultat du tri de tab suivant les ordonn‚es (et les abscisses si les ordonn‚es sont ‚gales *) (************************************************************) (* Les fonctions de convertion des abscisses et des ordonn‚es en entier(pixel) (xconv_en_entier,yconx_en_entier) ou en r‚el (yconv_en_reel,xconv_en_reel) *) unit xconv_en_entier:function(x:real):integer; begin result:=entier(40+20*x); end xconv_en_entier; unit yconv_en_entier:function(y:real):integer; begin result:=entier(210-20*y); end yconv_en_entier; unit xconv_en_reel:function(x:integer):real; begin result:=(x-40)/20; end xconv_en_reel; unit yconv_en_reel:function(y:integer):real; begin result:=(210-y)/20; end yconv_en_reel; (************************************************************) (* La structure de la classe segment, la procedure saisie utile pour la procedure clavier *) unit segment:class; var sens:char, x1,x2,y1,y2:real; (* La procedure saisie n'est utilis‚e que si les segments sont saisis au clavier *) unit saisie:procedure(input sens:char;inout x1,y1,x2,y2:real); var i,k:integer,j:real, b:boolean; begin if sens=h then call move(40,290); call outstring("entrer la valeur de l'ordonn‚e : Y= "); i:=inkey;j:=1.0;k:=0;y1:=0.0;b:=false; while i<>13 do call hascii(i); call move(350+7*k,290); if i<>46 then y1:=10*y1+i-48; fi; k:=k+1; if b then j:=j/10.0 fi; if i=46 then b:=true fi; i:=inkey; od; y1:=y1*j;if y1>10.0 then y1:=10.0 fi; call move(40,310); call outstring("entrer la valeur de l'abscisse1 : X1= "); i:=inkey;j:=1.0;k:=0;x1:=0.0;b:=false; while i<>13 do call hascii(i); call move(350+7*k,310); if i<>46 then x1:=10*x1+i-48; fi; k:=k+1; if b then j:=j/10.0 fi; if i=46 then b:=true fi; i:=inkey; od; x1:=x1*j; call move(40,330); call outstring("entrer la valeur de l'abscisse2 : X2= "); i:=inkey;j:=1.0;k:=0;x2:=0.0;b:=false; while i<>13 do call hascii(i); call move(350+7*k,330); if i<>46 then x2:=10*x2+i-48; fi; k:=k+1; if b then j:=j/10.0 fi; if i=46 then b:=true fi; i:=inkey; od; x2:=x2*j; if x1>x2 then y2:=x1;x1:=x2;x2:=y2; fi; y2:=y1;if x2>28.0 then x2:=28.0 fi;if x1>28.0 then x1:=28 fi; call move(xconv_en_entier(x1),yconv_en_entier(y1)); call draw(xconv_en_entier(x2),yconv_en_entier(y2)); else if sens=v then call move(40,290); call outstring("entrer la valeur de l'abscisse : X= "); i:=inkey;j:=1.0;k:=0;x1:=0.0;b:=false; while i<>13 do call hascii(i); call move(350+7*k,290); if i<>46 then x1:=10*x1+i-48; fi; k:=k+1; if b then j:=j/10.0 fi; if i=46 then b:=true fi; i:=inkey; od; x1:=x1*j;if x1>28 then x1:=28 fi; call move(40,310); call outstring("entrer la valeur de l'ordonn‚e1 : Y1= "); i:=inkey;j:=1.0;k:=0;y1:=0.0;b:=false; while i<>13 do call hascii(i); call move(350+7*k,310); if i<>46 then y1:=10*y1+i-48; fi; k:=k+1; if b then j:=j/10.0 fi; if i=46 then b:=true fi; i:=inkey; od; y1:=y1*j; call move(40,330); call outstring("entrer la valeur de l'ordonn‚e2 : Y2= "); i:=inkey;j:=1.0;k:=0;y2:=0.0;b:=false; while i<>13 do call hascii(i); call move(350+7*k,330); if i<>46 then y2:=10*y2+i-48; fi; k:=k+1; if b then j:=j/10.0 fi; if i=46 then b:=true fi; i:=inkey; od; y2:=y2*j; if y1>y2 then x2:=y1;y1:=y2;y2:=x2; fi; x2:=x1;if y2>10 then y2:=10 fi;if y1>10 then y1:=10 fi; call move(xconv_en_entier(x1),yconv_en_entier(y1)); call draw(xconv_en_entier(x2),yconv_en_entier(y2)); fi; fi; call move(40,275); call outstring(" "); call move(40,290); call outstring(" "); call move(40,310); call outstring(" "); call move(40,330); call outstring(" "); end saisie; end segment; (*************************************************************) (* La procedure tri, comme son nom l'indique, trie le tableau contenant tous les segments(tab) et met le r‚sultat dans un autre tableau(t) *) unit tri:procedure(tb:arrayof segment;output ta:arrayof segment); var i,j,k,n:integer,t:arrayof integer; begin n:=upper(tb); array t dim(1:n); array ta dim(1:n); for i:=1 to n do t(i):=i od; for i:=1 to n-1 do for j:=i+1 to n do if tb(i).y1>tb(j).y1 then k:=t(i); t(i):=t(j); t(j):=k; fi; if tb(i).y1=tb(j).y1 then if tb(i).x1>tb(j).x1 then k:=t(i); t(i):=t(j); t(j):=k; fi; fi; od; od; for i:=1 to n do ta(i):=new segment; ta(i):=tb(t(i)); od; call move(60,295);call color(9); call outstring("Fin du tri."); call move(60,310);call color(5); call outstring("Appuyer sur une touche pour voir ");call color(14); call outstring("les intersections ‚ventuelles. "); call move(60,325);call color(15); call outstring("Pour revenir au menu pr‚c‚dent, taper sur une nouvelle touche"); j:=inkey; end tri; (*************************************************************) (* Cette procedure est appel‚‚e par la procedure intersection, si les conditions pour une intersection sont r‚alis‚es, pour tracer l'intersection *) unit trace:procedure(c:char,x,y,z:real); begin if c='p' then call point(xconv_en_entier(x),yconv_en_entier(y)); fi; if c=h then call move(xconv_en_entier(x),yconv_en_entier(y)); call draw(xconv_en_entier(z),yconv_en_entier(y)); fi; if c=v then call move(xconv_en_entier(x),yconv_en_entier(y)); call draw(xconv_en_entier(x),yconv_en_entier(z)); fi; end trace; (*************************************************************) (* La procedure parcours a pour but de traiter le tableau tri‚ et si n‚cessaire faire appel … une de ses procedures(traitement, intersection) ou classe(arb) pour trouver toutes les intersections existantes *) unit parcours:procedure(tab:arrayof segment); (* La classe arb va servir … traiter uniquement les segments verticaux *) unit arb:class; var nb:integer,tv:arrayof segment; unit insertion:procedure(tab:arrayof segment,nb:integer;inout tv:arrayof segment); var i,j:integer; begin array tv dim(1:nb);j:=0; for i:=1 to upper(tab) do; if tab(i).sens=v then j:=j+1; tv(j):=new segment;tv(j).sens:=v; tv(j).x1:=tab(i).x1;tv(j).y1:=tab(i).y1; tv(j).x2:=tab(i).x2;tv(j).y2:=tab(i).y2; fi; od; end insertion; unit Arb_parcours:procedure(vertical:arrayof segment); begin for i:=1 to upper(vertical) do for j:=i+1 to upper(vertical) do call intersection(vertical(i),vertical(j)); od;od; end Arb_parcours; end arb; (* La procedure intersection permet de v‚rifier si les conditions d'intersection entre deux segments sont r‚alis‚es *) unit intersection:procedure(s1,s2:segment); begin call color(14); if s1.sens=s2.sens then if s1.sens=h then if s1.y1=s2.y1 then if s2.x2<=s1.x2 then call trace(h,s2.x1,s1.y1,s2.x2); else call trace(h,s2.x1,s1.y1,s1.x2); fi; fi; else if s1.x1=s2.x1 then if s2.y1<=s1.y2 then if s2.y2<=s1.y2 then call trace(v,s2.x1,s2.y1,s2.y2); else call trace(v,s2.x1,s2.y1,s1.y2); fi; fi; fi; fi; else if s1.y1>=s2.y1 and s1.y2<=s2.y2 then call trace('p',s2.x1,s1.y1,0); fi; fi; end intersection; (* La procedure traitement parcours le tableau tri‚ et r‚alise un traitement diff‚rent selon s'il s'agit d'un segment horizontal ou d'un segment vertical *) unit traitement: procedure(tab:arrayof segment); var i,j:integer,b:boolean; var bst:arb; begin bst:=new arb;b:=false;bst.nb:=0; for i:=1 to upper(tab) do if tab(i).sens=h then for j:=1 to upper(tab) do if j<>i then if tab(i).x1<=tab(j).x1 then if tab(i).x2>=tab(j).x2 or tab(i).x2>=tab(j).x1 then call intersection(tab(i),tab(j)); fi; fi;fi; od; else bst.nb:=bst.nb+1;b:=true; fi; od; call bst.insertion(tab,bst.nb,bst.tv); if b then call bst.Arb_parcours(bst.tv) fi; end traitement; begin call traitement(tab); i:=inkey; end; (*************************************************************) (* Cette procedure r‚alise le cadre dans lequel les segments,les intersections de segments et le dialogue avec l'utilisateur sont ‚cris *) unit graphisme:procedure; begin call cls; call color(10);call move(0,0); call hfill(640);call draw(0,250); call hfill(640);call move(639,0); call draw(639,349);call draw(0,349); call draw(0,250);call color(15); call move(40,10);call draw(40,210); call hfill(599); for i:=1 to 10 do call move(38,210-20*i); call draw(42,210-20*i); call move(28,210-i*20); if (i/10)<1 then call hascii(48+i); else call move(20,210-i*20); call hascii(48+i/10); call move(28,210-i*20); call hascii(i-entier(i/10)*10+48); fi; od; call move(10,8);call outstring("Y"); call move(26,215);call outstring("0"); for i:= 1 to 28 do call move(40+i*20,212); call draw(40+i*20,208); call move(33+i*20,218); if (i/10)<1 then call hascii(48+i); else call hascii(48+i/10); call move(40+i*20,218); call hascii(i-entier(i/10)*10+48); fi; od; call move(620,210);call outstring("X"); end; (*************************************************************) (* La procedure souris permet la saisie des segments … l'aide de la souris *) unit souris:procedure(output tab:arrayof segment); var i,j,n,h1,h2,v1,v2:integer, b:boolean; begin call graphisme; call move(40,260);call color(15); call outstring("Appuyer sur le bouton de gauche pour la premiŠre coordonn‚es"); call move(40,280); call outstring("puis sur le bouton de droite pour la seconde coordonn‚es."); call move (40,300); call outstring("Appuyer sur entr‚e pour continuer."); i:=inkey; call move(40,260);call color(15); call outstring(" "); call move(40,280); call outstring(" "); call move (40,300); call outstring(" "); pref MOUSE BLOCK unit click:procedure (output x,y,z,t:integer); var p:integer,l,r,c:boolean; begin call status(x,y,l,r,c); do call getpress(0,x,y,p,l,r,c); if l then call move(x,y);x:=inxpos;y:=inypos;call point(x,y); fi; if r then exit fi; od; call status(z,t,l,r,c); do call getpress(1,z,t,p,l,r,c); if r then call move(z,t);z:=inxpos;t:=inypos;call point(z,t); exit; fi; if l then exit fi; od; end click; begin b:=init(i); if b then call showcursor;call setwindow(40,600,10,210); call defcursor(1,12,13);call move(40,260); call outstring("Entrer le nombre de segments(12 au maximum) : "); i:=inkey;call hascii(i);n:=i-48; if i<>13 then i:=inkey; if i<>13 then call hascii(i); n:=10*n+i-48; fi; fi; array tab dim(1:n); for i:=1 to n do tab(i):=new segment; call move(40,280);call color(i); call outstring("Entrer le sens du segment (h/v) : "); j:=inkey;tab(i).sens:=chr(j);call hascii(0); if tab(i).sens=h then call hascii(72); call click(tab(i).x1,tab(i).y1,tab(i).x2,tab(i).y2); tab(i).x1:=xconv_en_reel(tab(i).x1); tab(i).x2:=xconv_en_reel(tab(i).x2); tab(i).y1:=yconv_en_reel(tab(i).y1); tab(i).y2:=yconv_en_reel(tab(i).y2); tab(i).y2:=tab(i).y1; if tab(i).x1>tab(i).x2 then j:=tab(i).x1; tab(i).x1:=tab(i).x2; tab(i).x2:=j; fi; call move(xconv_en_entier(tab(i).x1),yconv_en_entier(tab(i).y1)); call draw(xconv_en_entier(tab(i).x2),yconv_en_entier(tab(i).y2)); else call hascii(86); call click(tab(i).x1,tab(i).y1,tab(i).x2,tab(i).y2); tab(i).x1:=xconv_en_reel(tab(i).x1); tab(i).x2:=xconv_en_reel(tab(i).x2); tab(i).y1:=yconv_en_reel(tab(i).y1); tab(i).y2:=yconv_en_reel(tab(i).y2); tab(i).x2:=tab(i).x1; if tab(i).y1>tab(i).y2 then j:=tab(i).y1; tab(i).y1:=tab(i).y2; tab(i).y2:=j; fi; call move(xconv_en_entier(tab(i).x1),yconv_en_entier(tab(i).y1)); call draw(xconv_en_entier(tab(i).x2),yconv_en_entier(tab(i).y2)); fi; od; else call move(100,200);call outstring(" NO M O U S E "); fi; end; end souris; (*************************************************************) (* La procedure clavier est appel‚e si le choix "saisie au clavier" est s‚lectionner". *) unit clavier:procedure(output tab:arrayof segment); var i,j,n:integer; begin call graphisme;call move(40,260); call outstring("Entrer le nombre de segments(12 au maximum) : "); n:=inkey;call hascii(n);n:=n-48; j:=inkey;if j<>13 then n:=10*n+j-48; call hascii(j); fi; array tab dim(1:n); for i:=1 to n do tab(i):=new segment; call move(40,275);call color(i); call outstring("Entrer le sens du segment (h/v) : "); j:=inkey;tab(i).sens:=chr(j);call hascii(0); if tab(i).sens=h then call hascii(72); call tab(i).saisie(tab(i).sens,tab(i).x1,tab(i).y1,tab(i).x2,tab(i).y2); else call hascii(86); call tab(i).saisie(tab(i).sens,tab(i).x1,tab(i).y1,tab(i).x2,tab(i).y2); fi; od; end clavier; (*************************************************************) (* Menu principal *) unit menu:procedure; var choix:integer; (* Sous-menu du choix num‚ro 2 du menu principal *) unit menu2:procedure; var choix:integer; begin call graphisme; call move(40,260);call outstring(" Choix du mode de saisie :"); call move(80,275);call outstring("1- au clavier."); call move(80,290);call outstring("2- avec la souris."); call move(80,305);call outstring("3- retour au menu principal"); call move(40,325);call outstring("Votre choix : "); choix:=inkey;call hascii(choix);choix:=choix-48; case choix when 1 :do call clavier(tab); call tri(tab,t); call parcours(t); call menu2; exit; od; when 2 : do call souris(tab); call tri(tab,t); call parcours(t); call menu2; exit; od; when 3 : do call move(150,325); call outstring("retour au menu principal"); i:=inkey; exit; od; otherwise call menu2; esac; end menu2; unit choix_alea : procedure(output tab:arrayof segment); var nb_seg,nb_segh,nb_segv,i,j,k:integer,x1,x2,y1,y2:real; begin j:=0; call ranset(1); nb_seg:=2+entier(10*random); array tab dim (1:nb_seg); k:=0; nb_segh:=entier(nb_seg*random); (* nombre de segments horizontaux *) for i:=1 to nb_segh do y1:=10*random;y2:=y1;j:=j+1;call color(j); x1:=28*random;x2:=28*random; tab(j):=new segment;tab(j).sens:=h; tab(j).x1:=x1;tab(j).x2:=x2; tab(j).y1:=y1;tab(j).y2:=y2; if tab(i).x1>tab(i).x2 then k:=tab(i).x1;tab(i).x1:=tab(i).x2;tab(i).x2:=k; fi; if tab(i).y1>tab(i).y2 then k:=tab(i).y1;tab(i).y1:=tab(i).y2;tab(i).y2:=k; fi; call point(xconv_en_entier(tab(i).x1),yconv_en_entier(tab(i).y1)); call draw(xconv_en_entier(tab(i).x2),yconv_en_entier(tab(i).y1)); od; nb_segv:=nb_seg-nb_segh; for i:=1 to nb_segv do x1:=28*random;x2:=x1;j:=j+1;call color(j); y1:=10*random;y2:=10*random; tab(j):=new segment;tab(j).sens:=v; tab(j).x1:=x1;tab(j).x2:=x2; tab(j).y1:=y1;tab(j).y2:=y2; if tab(j).x1>tab(j).x2 then k:=tab(j).x1;tab(j).x1:=tab(j).x2;tab(j).x2:=k; fi; if tab(j).y1>tab(j).y2 then k:=tab(j).y1;tab(j).y1:=tab(j).y2;tab(j).y2:=k; fi; call point(xconv_en_entier(tab(j).x1),yconv_en_entier(tab(j).y1)); call draw(xconv_en_entier(tab(j).x1),yconv_en_entier(tab(j).y2)); od; end choix_alea; begin call cls; call move(300,0);call color(10);call outstring("MENU"); call move(60,60);call color(15); call outstring("1- choix al‚atoire de segments."); call move(60,100); call outstring("2- choix des segments par l'utilisateur."); call move(60,140);call outstring("3- fin du programme."); call move(60,220);call outstring("Votre choix :"); choix:=inkey;call hascii(choix);choix:=choix-48; case choix when 1:do call graphisme; call choix_alea(tab); call tri(tab,t); call parcours(t); call menu; exit; od; when 2:do call menu2; call menu;exit; od; when 3:do call cls; call move(250,50); call outstring("FIN DU PROGRAMME"); exit; od; otherwise call menu; esac; end menu; (*************************************************************) (* Programme principal *) begin call gron(nocard); call menu; i:=inkey; call groff; end; end projet;