Tableau de proportionnalité et PGCD

Tout ce qui concerne le langage Asymptote. Ce langage est supporté sur le forum via les balises asy.

Modérateur : gdm_asy

Règles du forum
Merci de soigner la rédaction de vos messages et de consulter ce sujet avant de poster. Pensez également à utiliser la fonction recherche du forum.
Romain Janvier
Utilisateur éprouvé
Utilisateur éprouvé
Messages : 146
Inscription : lundi 23 août 2010, 14:57

Tableau de proportionnalité et PGCD

Message par Romain Janvier »

Bonjour,

Comme j'en ai parlé sur le forum LaTeX, voici mon fichier permettant d'afficher des tableau de proportionnalité, des produits en croix et des pgcd avec la méthode d'Euclide. C'est un peu brouillon, mais c'est parce que je les modifie au fur et à mesure.

Voici le code de tableau_proport.asy

Code : Tout sélectionner

/* debut */
import geometry;

struct Texte {
 string texte; // le texte
 object obj;   // l'objet obtenu en affichant le texte
 pair size;    // (longueur,hauteur) de l'objet
 pair min;     // coin inferieur gauche de l'objet
 pair max;     // coin superieur droit de l'objet
 pen ptexte;   // pen pour le texte
 static Texte Texte(string texte,real echelle=1cm,pen ptexte=currentpen) {
   Texte T=new Texte;
   T.texte=texte;
   T.obj=Label(baseline(texte),ptexte);
   picture tmp;
   add(tmp,T.obj);
   T.size=size(tmp)/echelle;
   T.min=min(tmp)/echelle;
   T.max=max(tmp)/echelle;
   T.ptexte=ptexte;
   return T;
 };

};

object operator cast(Texte T) {
return T.obj;
};

pair operator cast(Texte T) {
return T.size;
};

from Texte unravel Texte;

typedef string[][] tableau;

struct Fleche {
 string texte;  // le texte sur la fleche
 pair origine;  // la case de depart
 pair destination;  // la case d'arrivee
 pair direction1;   // direction de depart
 pair direction2;   // direction d'arrivee
 pair offseto;  // decalage du depart
 pair offsetd;  // decalage de l'arrivee
 pair offsett;  // decalage du texte
 arrowbar pointe; // type de fleche
 pen penfleche; // pen pour la fleche
 pen pentexte; // pen du texte
 pen penovale; //pen de l'ovale

 static Fleche Fleche(string texte, pair origine, pair destination, pair direction1, pair direction2=-direction1,pair offseto=(0,0), pair offsetd=(0,0), pair offsett=(0,0),arrowbar pointe=ArcArrow,pen penfleche=currentpen,pen pentexte=currentpen,pen penovale=currentpen) {
   Fleche F=new Fleche;
   F.texte=texte;
   F.origine=origine;
   F.destination=destination;
   F.direction1=direction1;
   F.direction2=direction2;
   F.offseto=offseto;
   F.offsetd=offsetd;
   F.offsett=offsett;
   F.pointe=pointe;
   F.penfleche=penfleche;
   F.pentexte=pentexte;
   F.penovale=penovale;
   return F;
 };

};
from Fleche unravel Fleche;

// Plaque la direction sur la direction N, S, E ou W la plus proche.
// Si la direction est un des bissectrices, alors on ajoute les deux
// direction les plus proches.
pair posfleche(pair direction) {
  pair res=(0,0);
  real r=degrees(direction);
  if ((r<=45) || (r>=315)) {
    res+=(1,0);
  };
  if ((r>=45) && (r<=135)) {
    res+=(0,1);
  };
  if ((r>=135) && (r<=225)) {
    res+=(-1,0);
  };
   if ((r>=225) && (r<=315)) {
    res+=(0,-1);
  };
  return res;
};

// Retourne le point obtenu en se placant dans un cadre dont mes points
// extremes sont min et max, en utilisant les valeurs de decal comme
// position relative.
// Si decal=(0,0), c'est le milieu
// Si decal=(1,1), coin superieur droit
// Si decal=(-1,-1), coin inferieur gauche...
pair positionrelative(pair decalage, pair min, pair max)
{
  real x=0, y=0;
  if (decalage.x>0) {
     x=decalage.x*max.x;
  } else {
     x=-decalage.x*min.x;
  };
  if (decalage.y>0) {
     y=decalage.y*max.y;
  } else {
     y=-decalage.y*min.y;
  };
  return (x,y);
}

// affiche tableau cree le tableau avec les fleches
// Tableau T : le texte du tableau
// Fleche[] LF : liste des fleches a placer ;
//               les coordonnees (i,j) correspondent a la colonne i
//               et la ligne j, en comptant a partir de 0
// Fleche[] LF2 : liste de fleches a placer dans le tableau
// pair P : Coin superieur gauche du tableau (pas encore utilisé)
// bool regulier : toutes les colonnes a partir de la 2e ont la meme taille
// real largmin : largeur minimum des colonnes a partir de la 2e
// real hautmin : hauteur minimum des lignes
// real margehoriz : marge horizontale autour des textes
// real margevertic : marge verticale autour des textes
// bool ellipse : trace les ellipses ou pas
void affichetableau(tableau T,Fleche[] LF=new Fleche[],Fleche[] LF2=new Fleche[],pair P=(0,0),bool regulier=false, real largmin=0, real hautmin=0,real margehoriz=0.05, real margevertic=0.05,bool ellipse=true){
  Texte[][] textes;
  int lignes=0, colonnes=T.length; // nombre de lignes et de colonnes
  real[] largeurs; // largeur des colonnes
  real[] hauteurs; // hauteur des lignes
  real hauteurtotale=0;
  real largeurmax=largmin;
  // on calcule les tailles des labels
  for(int i=0; i< T.length; ++i) {
    string[] TT=T[i];
    textes[i]=new Texte[];
    if (lignes<TT.length) {
      lignes=TT.length;
    };
    hauteurs[i]=hautmin;
    for(int j=0; j< TT.length; ++j) {
       //write("i="+(string)i+" j="+(string)j);
       if(largeurs.length<j+1) {
          //write("on initialise");
          largeurs[j]=largmin;
       };
       //write((string)i+","+(string)j);
       Texte txt=Texte(TT[j]);
       textes[i][j]=txt;
       if(txt.size.y>hauteurs[i]) {
         hauteurs[i]=txt.size.y;
       };
       if(txt.size.x>largeurs[j]) {
         //write("on met a jour");
         largeurs[j]=txt.size.x;
         if ((txt.size.x > largeurmax) && (j>0)) {
           ////write("on update");
           largeurmax=txt.size.x;
         };
       };
      //write(largeurs[j]);
    };
    hauteurtotale+=hauteurs[i]+2margevertic;
  };
  //write(largeurmax);
  real larg=largeurmax;
  real h=0;
  pair[][] listepos; 
  // on affiche
  for(int i=0; i< T.length; ++i) {
     h-=hauteurs[i]/2+margevertic;
     string[] TT=T[i];
     listepos[i]=new pair[];
     real l=0;
     for(int j=0; j< TT.length; ++j) {
       //write("i="+(string)i+" j="+(string)j+" larg="+(string)larg);
       if (i==0) {
         draw((l,0)--(l,-hauteurtotale));
       };
       if ((j==0) || (!regulier)) {
          //write("larg="+(string)largeurs[j]);
          larg=largeurs[j];
       };
       l+=larg/2+margehoriz;
       listepos[i][j]=(l,h);
       //write("(l,h)="+(string)listepos[i][j]);
       add(textes[i][j],(l,h));
       l+=larg/2+margehoriz;
       larg=largeurmax;
     };
     if (i==0) {
       draw((0,0)--(l,0));
       draw((l,0)--(l,-hauteurtotale));
     };
     h-=hauteurs[i]/2+margevertic;
     draw((0,h)--(l,h));
  };
  // on s'occupe des fleches avec les ellipses
  for(Fleche F : LF) {
    pair d1=F.direction1;
    pair d2=F.direction2;
    pair p1=F.origine;
    pair p2=F.destination;
    pair v1=posfleche(d1);
    pair v2=posfleche(-d2);
    pair pt1=(v1.x*(largeurs[floor(p1.x)]/2+margehoriz),v1.y*(hauteurs[floor(p1.y)]/2+margevertic))+listepos[floor(p1.y)][floor(p1.x)]+F.offseto;
    pair pt2=(v2.x*(largeurs[floor(p2.x)]/2+margehoriz),v2.y*(hauteurs[floor(p2.y)]/2+margevertic))+listepos[floor(p2.y)][floor(p2.x)]+F.offsetd;
    path fleche=pt1..controls pt1+d1 and pt2-d2..pt2;
    //path fleche=pt1{d1}..{d2}pt2;
    draw(fleche,F.penfleche,F.pointe);
    if (ellipse) {
       draw(Label(F.texte,F.pentexte),ellipse,midpoint(fleche)+F.offsett,F.penovale,FillDraw(fillpen=white));
    } else {
       label(F.texte,midpoint(fleche),F.offsett,F.pentexte);
    };
  };
  // on s'occupe des fleches pour les produits en croix
  for(Fleche F : LF2) {
    pair d1=F.direction1;
    pair d2=F.direction2;
    int xo=floor(F.origine.x);
    int yo=floor(F.origine.y);
    int xd=floor(F.destination.x);
    int yd=floor(F.destination.y);
    pair p1=listepos[yo][xo];
    pair p2=listepos[yd][xd];
    Texte t1=textes[yo][xo];
    Texte t2=textes[yd][xd];
    pair pt1=p1+positionrelative(d1,t1.min,t1.max)+F.offseto;
    pair pt2=p2+positionrelative(d2,t2.min,t2.max)+F.offsetd;
    path fleche=pt1--pt2;
    draw(fleche,F.penfleche,F.pointe);
  };

};


//tableau tutu = {{"Nombre de stylos","$1$","$2$","$5$"},{"Prix en euros et en francs aussi","$1,5$","$3$","$7,5$"}};
//Fleche F1=Fleche("$\times2$",(1,0),(2,0),N);
//Fleche F4=Fleche("$\times5$",(1,0),(3,0),2N,offseto=(-0.2,0));
//Fleche F2=Fleche("$\times5$",(1,1),(3,1),S);
//Fleche F3=Fleche("$\times1,5$",(3,0),(3,1),E,offseto=(0,-0.1),offsetd=(0,0.1),offsett=(0.2,0));
//Fleche F5=Fleche("$:1,5$",(3,1),(3,0),3E,offseto=(0,-0.2),offsetd=(0,+0.2));

//Fleche Bob=Fleche("",(0,0),(1,1),SE,NW,Arrows);
//affichetableau(tutu,new Fleche[] {F4,F5,F2,F3,F1},new Fleche[] {Bob},true,largmin=1);


// affichepgcd affiche la methode d'euclide en rajoutant des fleches
// nb1 : premier nombre de depart
// nb2 : second nombre
// Tableau T : le texte du tableau
// aff : indique si on doit afficher le texte correspondant
// afffleche : false si on ne doit jamais afficher les fleches
// incomplet : indique la longueur des dots a mettre 
//             si on remplace les vals dans les pgcd par des dots
// real largmin : largeur minimum des colonnes
// real hautmin : hauteur minimum des lignes
// real margehoriz : marge horizontale autour des textes
// real margevertic : marge verticale autour des textes
void affichepgcd(int nb1, int nb2,int[][] aff=new int[][], bool afffleches=true, real incomplet=0, real largmin=0, real hautmin=1,real margehoriz=0, real margevertic=0.05){
  Texte[][] textes;
  tableau T;
  int n1=max(nb1,nb2);
  int n2=min(nb1,nb2);
  int q=quotient(n1,n2);
  int r=n1%n2;
  while (r>0) {
    string pgcd1=(incomplet>0) ? "\dfill{"+(string)incomplet+"cm}" :
                                 (string)n1+";"+(string)n2;
    string pgcd2=(incomplet>0) ? "\dfill{"+(string)incomplet+"cm}" :
                                 (string)n2+";"+(string)r;
    T[T.length]=new string[] {"$"+(string)n1+"$","$=$",
                              "$"+(string)q+"$","$\times$",
                              "$"+(string)n2+"$","$+$","$"+(string)r+"$",
                              "\;d'o\`u PGCD$("+pgcd1+
                              ")=\text{PGCD}("+pgcd2+")$"};
    n1=n2;
    n2=r;
    q=quotient(n1,n2);
    r=n1%n2;
  };
    string pgcd1=(incomplet>0) ? "\dfill{"+(string)incomplet+"cm}" :
                                 (string)n1+";"+(string)n2;
    string pgcd2=(incomplet>0) ? "\ldots" : (string)n2;
    T[T.length]=new string[] {"$"+(string)n1+"$","$=$",
                              "$"+(string)q+"$","$\times$",
                              "$"+(string)n2+"$","$+$","$"+(string)r+"$",
                              "\;d'o\`u PGCD$("+pgcd1+
                              ")="+pgcd2+"$"};
  int lignes=0, colonnes=T.length; // nombre de lignes et de colonnes
  int defaut=0; //pour completer les infos d'affichage
  if (aff.length==0) {
     defaut=1; // si aff est nul, on affiche tout
  };
  for (int i=0;i<aff.length;++i) {
    for (int j=aff[i].length;j<8;++j) {
      aff[i][j]=defaut;
    };
  };
  if (aff.length<colonnes) {
    for (int i=aff.length;i<colonnes;++i) {
       aff[i]=new int[] {defaut,defaut,defaut,defaut,defaut,defaut,defaut,defaut};
    };
  };
  real[] largeurs; // largeur des colonnes
  real[] hauteurs; // hauteur des lignes
  real hauteurtotale=0;
  real largeurmax=largmin;
  // on calcule les tailles des labels
  for(int i=0; i< T.length; ++i) {
    string[] TT=T[i];
    textes[i]=new Texte[];
    if (lignes<TT.length) {
      lignes=TT.length;
    };
    hauteurs[i]=hautmin;
    pen ptxt=black;
    for(int j=0; j< TT.length; ++j) {
       //write("i="+(string)i+" j="+(string)j);
       if(largeurs.length<j+1) {
          //write("on initialise");
          largeurs[j]=largmin;
       };
       //write((string)i+","+(string)j);
       ptxt=(aff[i][j]==1) ? black : white;
       Texte txt=Texte(TT[j],ptxt);
       textes[i][j]=txt;
       if(txt.size.y>hauteurs[i]) {
         hauteurs[i]=txt.size.y;
       };
       if(txt.size.x>largeurs[j]) {
         //write("on met a jour");
         largeurs[j]=txt.size.x;
         if ((txt.size.x > largeurmax) && (j>0)) {
           ////write("on update");
           largeurmax=txt.size.x;
         };
       };
      //write(largeurs[j]);
    };
    hauteurtotale+=hauteurs[i]+2margevertic;
  };
  //write(largeurmax);
  real larg=largeurmax;
  real h=0;
  pair[][] listepos; 
  // on affiche
  for(int i=0; i< T.length; ++i) {
     h-=hauteurs[i]/2+margevertic;
     string[] TT=T[i];
     listepos[i]=new pair[];
     real l=0;
     for(int j=0; j< TT.length; ++j) {
       //write("i="+(string)i+" j="+(string)j+" larg="+(string)larg);
          //write("larg="+(string)largeurs[j]);
       larg=largeurs[j];
       if (j+1<TT.length) {
         l+=larg/2+margehoriz;
       } else {
         l+=margehoriz+textes[i][j].size.x/2;
       };
       listepos[i][j]=(l,h);
       //write("(l,h)="+(string)listepos[i][j]);
       //if (aff[i][j]==1) { 
       add(textes[i][j],(l,h)); //};
       l+=larg/2+margehoriz;
       larg=largeurmax;
     };
       h-=hauteurs[i]/2+margevertic;
  };
  for(int i=0;i<listepos.length-1;++i) {
    pair p1=listepos[i][4]+(0,textes[i][4].min.y);
    pair p2=listepos[i][6]+(0,textes[i][4].min.y);
    pair p3=listepos[i+1][0]+(0,textes[i+1][0].max.y);
    pair p4=listepos[i+1][4]+(0,textes[i+1][4].max.y);
    path fleche1=p1{SW}..{SW}p3;
    path fleche2=p2{SW}..{SW}p4;

    //path fleche=pt1{d1}..{d2}pt2;
    if (afffleches || (aff[i+1][0]==1)) { draw(fleche1,ArcArrow(TeXHead));};
    if (afffleches || (aff[i+1][4]==1)) { draw(fleche2,ArcArrow(TeXHead));};

    //draw(F.texte,ellipse,midpoint(fleche)+F.offsett,FillDraw(fillpen=white));
  };
};
Et voici des exemples :

Code : Tout sélectionner

import geometry;
import tableau_proport;
unitsize(1cm); //important, sinon cela ne marche pas

tableau tutu={{"Dose d'huile","$2$","\ldots"},{"Dose de super","$3$","\ldots"}};
Fleche F1=Fleche("$\times k$",(2,0),(2,1),E,offseto=(0,-0.1),offsetd=(0,0.1),offsett=(0.2,0));
Fleche F2=Fleche("$: k$",(2,1),(2,0),3E,offseto=(0,-0.2),offsetd=(0,+0.2));
affichetableau(tutu,new Fleche[] {F2,F1},true,largmin=1,hautmin=0.8);
cours-tableau-prop-huile1.png

Code : Tout sélectionner

import geometry;
import tableau_proport;
unitsize(1cm);

tableau tab = {{"Nombre de crayons","$7$","$3$"},{"Prix en euros","$3,85$","$x$"}};
//Fleche F1=Fleche("$\times2$",(4,0),(4,1),E);
Fleche F2=Fleche("",(1,0),(2,1),(1,-0.2),(-1,0.2),Arrows(TeXHead,2bp),penfleche=heavygreen);
Fleche F3=Fleche("",(1,1),(2,0),(1,0.2),(-1,-0.2),Arrows(TeXHead,2bp),penfleche=heavyred);

affichetableau(tab,new Fleche[] {},new Fleche[] {F2,F3},true,largmin=1.5);
cours-produit-croix.png

Code : Tout sélectionner

import geometry;
import tableau_proport;
unitsize(1cm);

affichepgcd(782,136);
cours-pgcd.png
Si vous avez des remarques ou commentaires...
Vous ne pouvez pas consulter les pièces jointes insérées à ce message.

GMaths
Utilisateur chevronné
Utilisateur chevronné
Messages : 2031
Inscription : lundi 01 octobre 2007, 10:20

Re: Tableau de proportionnalité et PGCD

Message par GMaths »

Romain Janvier a écrit :Si vous avez des remarques ou commentaires...
Une lecture très superficielle depuis le lycée... où je ne peux pas tester.

Ce genre de syntaxe (dont je n'avais plus le souvenir : j'ai dû rechercher unravel dans la doc) :

Code : Tout sélectionner

struct Person {
  string firstname;
  string lastname;

  static Person Person(string firstname, string lastname) {
    Person p=new Person;
    p.firstname=firstname;
    p.lastname=lastname;
    return p;
  }
}
from Person unravel Person;
ne peut-elle pas être remplacée par celle-ci plus claire, il me semble :

Code : Tout sélectionner

struct Person {
  string firstname;
  string lastname;

  void operator init(string firstname, string lastname) {
    this.firstname=firstname;
    this.lastname=lastname;
  }
}

Romain Janvier
Utilisateur éprouvé
Utilisateur éprouvé
Messages : 146
Inscription : lundi 23 août 2010, 14:57

Re: Tableau de proportionnalité et PGCD

Message par Romain Janvier »

On peut surement optimiser. Il me semble que j'ai pris modèle sur un exemple trouvé sur le net, mais je ne sais plus lequel. En regardant la doc, j'ai du prendre l'exemple qui se trouve juste en dessous de celui que tu as donné. Et ce n'etait pas le bon...

GMaths
Utilisateur chevronné
Utilisateur chevronné
Messages : 2031
Inscription : lundi 01 octobre 2007, 10:20

Re: Tableau de proportionnalité et PGCD

Message par GMaths »

Romain Janvier a écrit :En regardant la doc, j'ai du prendre l'exemple qui se trouve juste en dessous de celui que tu as donné.
Au dessus, tu veux dire.
Et il me semble qu'ensuite, il propose la syntaxe avec "void operator init" comme simplification.

Romain Janvier
Utilisateur éprouvé
Utilisateur éprouvé
Messages : 146
Inscription : lundi 23 août 2010, 14:57

Re: Tableau de proportionnalité et PGCD

Message par Romain Janvier »

Oui tu as raison.

Sinon ave mes tableaux, on peut aussi mettre les fleches en haut ou en bas, pas juste sur les cotes. Par contre j'ai voulu faire une figure avec des fleches qui partent d'autres fleches, mais là j'ai du bidouiller. Il faudrait stocker les positions des textes sur les fleches, mais là, ca commence à faire vraiment compliqué pour simplement un ou deux cas où c'est utile.

Par contre il faudrait faire une fonction qui remplie le tableau automatiquement. Sauf que comme je l'utilise souvent en mettant des trous pour que les élèves les complètent, cela me generait plus qu'autre chose.