PROGRAM Spirale;
{
Epreuve informatique de l'Ecole Polytechnique           92.031
--------------------------------------------------------------


1/   Tout point M d'un plan E peut être classiquement repéré
     par un couple de coordonnées polaires (r,theta) où r est
     sa distance à l'origine et theta un angle défini modulo Ò .

     On appelle fonction spirale toute application (r,theta)->phi(r,theta),
     définie en tout point du plan E qui
     possède la propriété suivante :

                   tau
     (1)    phi(r.e   ,theta) = phi(r,theta+lambda.tau)

     Chercher une expression canonique de phi(r,theta) .
     Citer des exemples, des cas particuliers ou limites.

     Pour limiter la variété des applications numériques, i
     est conseillé de se restreindre désormais au cas :

         phi(r,theta) = [Log(r)+theta] mod 2Ò


2/   On appelle spirale le lieu des points M tels que

     (2)  phi(r,theta) = Constante

     Tracer la spirale définie par :

     (3)  phi(r,theta) = 0


3/   Soit D une droite fixe dans E et t un paramètre.
     Ecrire un programme Pascal qui dessine l'intersection
     entre cette droite et la spirale correspondant à
     l'équation :

     (4)  phi(r,theta) =t      0 <= t < 2Ò

     Les points d'intersection forment des intervalles sur D.
     Que peut-on dire de la longueur de ces intervalles ?
     Calculer le plus petit d'entre eux.


4/   La droite D restant fixée, chercher la valeur de t qui
     minimise la longueur de ce plus petit intervalle.


5/   Soit M un point fixe de E. Combien de tangentes à la
     spirale peut-on construire à partir de ce point ?

     Montrer lorsque t varie que la spirale "tourne sur elle-
     même" et que le lieu des points de tangence est une
     courbe facile à tracer.

                             -=-=-
     }


uses crt, modubase;

Const
     pas=0.1;
     zoom=1.2;


Type
    Points = record
              rho,theta :real;
             end;
    angle = real;


VAR
   Lambda       : real;
   t0           : real;
   Ch           : char;


Function spi(theta:angle):real;
begin
     spi:=exp((t0-theta)/lambda);
end;

Function Ecart(theta,thetaD:angle;rD:real):real;
begin
        Ecart:=rD-spi(theta)*cos(theta-thetaD);
end;

Procedure Genere(VAR M:points;theta:angle);
begin
     M.theta:=theta;
     M.rho:=spi(theta);
end;


Procedure Joindre(M1,M2:points);
begin
     with M1 do Deplace(rho*cos(theta),rho*sin(theta));
     with M2 do Trace  (rho*cos(theta),rho*sin(theta));
end ;

Procedure TraceSpirale;
Const
     pas=0.1;
     zoom=1;
Var
   M1,M2,M3,M4 : points;
begin
     Genere(M1,0);
     M2:=M1;
     repeat
           M3:=M1;
           Genere(M1,M1.theta+pas);
           Joindre(M1,M3);
           M4:=M2;
           Genere(M2,M2.theta-pas);
           Joindre(M2,M4);
     until M1.rho<0.00001;
end;

Procedure TracePoint(M:Points);
begin
     With M do Croix(rho*cos(theta),rho*sin(theta));
end;

Procedure TraceDroite(rD:real;thetaD:angle);
Var
   M1,M2,M3,M4: points;
begin
     with M1 do
          begin
               rho:=rD;
               theta :=ThetaD;
          end;
     M2:=M1;
     repeat
           M3:=M1;
           with M1 do
                begin
                     theta:=theta+pas;
                     if cos(theta-thetaD)<>0 then
                        rho:=rD/cos(theta-thetaD);
                end;
           joindre(M1,M3);
           M4:=M2;
           with M2 do
                begin
                     theta:=theta-pas;
                     if cos(theta-thetaD)<>0 then
                        rho:=rD/cos(theta-thetaD);
                end;
           joindre(M2,M4);
     until M1.theta-thetaD>=(pi/2-pas);
end;

Function Intervalle(rD:real;thetaD:angle;VAR Contact:Points):real;
Cons
     pas = 0.01;
var
     theta,theta1,theta2 : angle;
begin
     theta:=t0-Ln(rD);
     repeat
           theta:=theta-pas;
     until Ecart(theta,thetaD,rD)<0;
     theta1:=theta;
     repeat
           theta:=theta-pas;
     until Ecart(theta,thetaD,rD)>0;
     theta2:=theta;
     Genere(Contact,theta);
     Intervalle := sqrt(
                        sqr(spi(theta1))+sqr(spi(theta2))
                       - 2*spi(theta1)*spi(theta2)*cos(theta1-theta2)
                        );
end



Procedure Init;
begin
      Initgraphique;
      IsoFenetre(-zoom,zoom,-zoom*0.6);
      Modetexte;
end;



Procedure Presentation;
begin;
      Modetexte;
      Efface;
      WriteLN(' ======= La Spirale  ========');
      WriteLN('                              ');
      WriteLN('                              ');
      WriteLN('                              ');
      WriteLN('   (1) Question 1             ');
      WriteLN('   (2) Question 2             ');
      WriteLN('   (3) Question 3             ');
      WriteLN('   (4) Question 4             ');
      WriteLN('   (5) Question 5             ');
      WriteLN('                              ');
      WriteLN('   Tapez votre choix          ');
      WriteLN('                              ');
      WriteLN('                              ');
end;

Procedure Question1;
begin
     Efface;
     Writeln('+---------------------- Question n°1 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦   Expression canonique : phi(M)=F(h(rho,theta))                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦  où F(x) est une application quelconque de   0<=x<2Ò              ¦');
     Writeln('¦  et h(rho,theta)=[lambda.Log(rho)+theta] mod 2Ò                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦  Exemple :                                                        ¦');
     Writeln('¦            phi(rho,theta)=[lambda.Log(rho)+theta] mod (2Ò/k)      ¦');
     Writeln('¦                   où lambda est réel, et k>0 entier               ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦  Cas particuliers :                                               ¦');
     Writeln('¦                    phi(rho,theta)=1    : le plan E entier         ¦');
     Writeln('¦                    phi(rho,theta)=theta: Une droite passant par O ¦');
     Writeln('¦  Cas limite :                                                     ¦');
     Writeln('¦                    phi(rho,theta)=rho  : Un cercle de centre O    ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
end;

Procedure Question2;
begin
     Efface;
     Writeln('+---------------------- Question n°2 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦        La spirale s''obtient par :                                 ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                    -theta                                         ¦');
     Writeln('¦            rho = e                                                ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
     Pause;
     Lambda:=1;
     t0:=0;
     ModeGraphique;
     TraceSpirale;
end;



Procedure Question3;
var
   rD     : real;
   thetaD ,
   Theta  : angle;
   M      :Points;
begin
     Efface;
     Writeln('+---------------------- Question n°3 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦    La spirale découpe sur D des intervalles croissants :          ¦');
     Writeln('¦    de part et d''autre d''un intervalle central                     ¦');
     Writeln('¦    L''équation de D s''écrit :                                      ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦         rho:= rD/cos(theta-thetaD)=droite(theta)                  ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦    On fait varier theta de theta0 à -l''infini où                  ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦         theta0=-Log(rD)                                           ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦ en cherchant les deux premières valeurs de theta telles que :     ¦');
     Writeln('¦ l''écart  :    rD-cos(theta-thetaD).exp(-theta)  soit nul          ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
     Writeln('Entrez les valeurs de rD et de ThetaD :');
   {  Write('rD=');readln(rD);
      Write('thetaD=');readln(thetaD); }
      rD:=1/4;ThetaD :=1.7;
     Pause;
     Lambda:=1;
     t0:=0;
     ModeGraphique;
     TraceSpirale;
     TraceDroite(rD,ThetaD);
     Deplace(-zoom,zoom/2);
     Ecris('premier intervalle=');
     EcrisReel(Intervalle(rD,ThetaD,M));
end;

Procedure Question4;
var
   rD           : real;
   thetaD,Theta : angle;
   t1,t2,i1,i2  : real;
   temp         : real;
   M            : Points;
begin
     Efface;
     Writeln('+---------------------- Question n°4 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦     On fait varier t0                                             ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦     Par extrapolations Newton, on cherche la tangente             ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
      Writeln('Entrez les valeurs de rD et de ThetaD :');
   {  Write('rD=');readln(rD);
      Write('thetaD=');readln(thetaD); }
      rD:=1/4;ThetaD :=1.7;
     Writeln('Entrez le pas de calcul :');
   {  Write('pas=');readln(pas); }
     Pause;
     Lambda:=1;
     t1:=0;
     t2:=-0.1;
     ModeGraphique;
     Couleur(Brillant);
     M.rho:=0;
     Couleur(Vert);
     TracePoint(M);
     TraceDroite(rD,ThetaD);
     Repeat
           t0:=t2;i2:=Intervalle(rD,ThetaD,M);
           t0:=t1;i1:=Intervalle(rD,ThetaD,M) ;
           Deplace(-zoom,0.7);Ecris('t1=');EcrisReel(t1);
                              Ecris('  i1=');Ecrisreel(i1);
           Deplace(-zoom,0.6);Ecris('t2=');EcrisReel(t2);
                              Ecris('  i2=');Ecrisreel(i2);
           if i2>i1 then
              begin
                   t2:=(t1+t2)/2;
              end
           else
              begin
                   temp:=t2;
                   t2:=t2*2-t1;
                   t1:=temp;
              end;
     until abs(t2-t1)<0.01;
     Couleur(Magenta);
     TracePoint(M);
     Couleur(-Brillant);
     TraceSpirale;
end;


Procedure Question5;
var
   rM : real;
   ThetaM : angle;
   rD : real;
   ThetaD,t1,t2,temp,Theta : angle;
   pas  : real;
   i1,i2  : real;
   x1,x2,y1,y2 :real;
   M1,M2 : points;
begin
     Efface;
     Writeln('+---------------------- Question n°5 -------------------------------+');
     Writeln('¦                                                                   ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦       On abaisse les tangentes à la Spirale :                     ¦');
     Writeln('¦                                                                   ¦');
     Writeln('¦       et on voit que le lieu des points de contacts quand         ¦');
     Writeln('¦       la spirale tourne est un cercle, ce qui s''explique          ¦');
     Writeln('¦       par le fait que la spirale logarithmique coupe les          ¦');
     Writeln('¦       rayons selon un angle constant.                             ¦');
     Writeln('¦                                                                   ¦');
     Writeln('+-------------------------------------------------------------------+');
      Writeln('Entrez les valeurs de rM et de ThetaM :');
   {  Write('rM=');readln(rM);
      Write('thetaM=');readln(thetaM); }
      rM:=0.4;ThetaM :=0.2;
     Writeln('Entrez le pas de calcul :');
   {  Write('pas=');readln(pas); }
      pas:=0.2;
     Lambda:=1;
     ModeGraphique;
     Couleur(Rouge);
     M1.rho:=rM;
     M1.theta:=ThetaM;
     TracePoint(M1);
     ThetaD:=0;
     M2.rho:=0;
     Couleur(Vert);
     TracePoint(M2);
     Repeat
           ThetaD :=ThetaD+pas;
           rD:= rM*cos(ThetaD-ThetaM);
           Couleur(-Jaune);
           TraceDroite(rD,ThetaD);
           t1:=0;
           t2:=-0.1;
           repeat
                      t0:=t2;i2:=Intervalle(rD,ThetaD,M1);
                      t0:=t1;i1:=Intervalle(rD,ThetaD,M1);
                      Deplace(-zoom,0.5);Ecris('t1=');EcrisReel(t1);
                              Ecris('  i1=');EcrisReel(i1);
                      Deplace(-zoom,0.4);Ecris('t2=');EcrisReel(t2);
                              Ecris('  i2=');EcrisReel(i2);
                     if i2>i1 then
                        begin
                            t2:=(t1+t2)/2;
                        end
                     else
                        begin
                            temp:=t2;
                            t2:=t2*2-t1;
                            t1:=temp;
                        end;
           until abs(t2-t1)<0.003;
     Couleur(Magenta);
     TracePoint(M1);
     Couleur(Vert);
     if M2.rho>0 then
        Joindre(M1,M2);
     Couleur(Magenta);
     TracePoint(M1);
     M2:=M1;
     Couleur(-Brillant);
     TraceSpirale;
     Couleur(-Jaune);
     TraceDroite(rD,ThetaD);
     TraceSpirale;
   until ThetaD>2*pi;

end;

{ Bloc principal }
begin
  Init;
  Repeat
     Presentation;
     Ch:= ReadKey;
     case ch of
          '1':  Question1;
          '2':  Question2;
          '3' : Question3;
          '4' : Question4;
          '5' : Question5;
     end;
     Pause;
  until false;
