Page 1 sur 1

Macros pour afficher des resolutions d'equations

MessagePosté: Mercredi 25 Août 2010, 14:03
par Romain Janvier
Bonjour,

Voici des macros que j'ai fait l'annee derniere pour afficher la resolution d'equations ou d'inequations avec des fleches sur les cotés.

Image

Les macros:

Code: Tout sélectionner
/* debut */
import geometry;
unitsize(1cm);


/* format: {{membre1,membre2,transition_sur_fleches_laterales,
                             transition_fleche_milieu},...}
   interligne: ecart entre chaque ligne (en unitsize ?)
   decalhorizontal: decalage horizontal entre le membre le plus long et
                    le centre des elipses. (unite?)
   margehorizontale: decalage horizontal des fleches par rapport aux membres (unite?)
   margeverticale: decalage en dessus ou en dessous (unite?)
*/

void solveequation(string[][] l_texte,real interligne=1.5, real decalhorizontal=20, real margehorizontale=5, real margeverticale=5, string[] l_operateurs=new string[] {}) {
  pair milieu1;
  pair milieu2;
  real positionhorizontale;
  /* phase 1: placer les operateurs */
  object[] l_egals=new object[] {}; // labels se trouvant a la place des '=', des '>' ou '<'
  int nb_equations=l_texte.length; // nombre de lignes de la resolution
  for(int i=0; i<nb_equations;++i) {
    l_egals[i]=Label("$0$",(0,-i*interligne)); // on place des 0 la ou seront les operateurs
  } /* QUEST: pourquoi ne pas mettre directement l'operateur? */

  /* phase 2: placer les membres de l'equation */
  add(new void(frame f, transform t) {
  // liste des points pour aligner a droite et a gauche des =
  pair[] l_points_egal=new pair[] {};
  // labels correspondant aux membres
  object[] l_membres=new object[] {};
  real largmax=0; // la longeur du membre le plus long
  for(int i=0; i<nb_equations;++i) {
    l_points_egal[2i]=point(l_egals[i],SW,t);
    l_points_egal[2i+1]=point(l_egals[i],SE,t);
    milieu1=(l_points_egal[2i]+l_points_egal[2i+1])/2;
    if (l_operateurs.length>i) { // si on a defini des operateurs, on les met
      add(f,Label(l_operateurs[i],milieu1,0.7N,basealign));}
    else /* QUEST: ca sent un peu la bidouille ce 0.7N */
     { // sinon on met '='
      add(f,Label("$=$",milieu1,0.7N,basealign));
     }
    l_membres[2i]=Label(l_texte[i][0]); // membre gauche
    l_membres[2i+1]=Label(l_texte[i][1]); // membre droit
    // on met a jour la longeur max
    largmax=max(new real[] {largmax,size(l_membres[2i]).x,size(l_membres[2i+1]).x});
    add(f,Label(l_membres[2i],l_points_egal[2i],NW,basealign));
    add(f,Label(l_membres[2i+1],l_points_egal[2i+1],NE,basealign));
  }

  /* phase 3: on place les labels sur les fleches laterales */
  positionhorizontale=largmax+decalhorizontal+margehorizontale;
  for(int i=0; i<nb_equations-1;++i) {
    /* on test s'il y a un texte a mettre */
    if (l_texte[i].length>2 && l_texte[i][2]!="") {
      milieu1 =(l_points_egal[2i]+l_points_egal[2i+2])/2;
      milieu2 =(l_points_egal[2i+1]+l_points_egal[2i+3])/2;
      /* fleche droite */
      draw(f,(l_points_egal[2i+1]+(size(l_membres[2i+1]).x+margehorizontale,0)){E}..
       {SE}(milieu2+(positionhorizontale,size(l_egals[0]).y/2)){SW}..
       {W}(l_points_egal[2i+3]+(size(l_membres[2i+3]).x+margehorizontale,size(l_egals[0]).y)),ArcArrow);
      /* fleche gauche */
      draw(f,(l_points_egal[2i]+(-size(l_membres[2i]).x-margehorizontale,0)){W}..
       {SW}(milieu1+(-positionhorizontale,size(l_egals[0]).y/2)){SE}..
       {E}(l_points_egal[2i+2]+(-size(l_membres[2i+2]).x-margehorizontale,size(l_egals[0]).y)),ArcArrow);

      /* Pour mettre les textes lateraux,
         on fait un oval noir,
         puis un oval blanc moins grand.
         On peut surement faire mieux. */
      draw(l_texte[i][2],ellipse,
           inverse(t)*((l_points_egal[2i]+l_points_egal[2i+2])/2+(-positionhorizontale,size(l_egals[0]).y/2)),
           0.8,Fill(black));
      draw(l_texte[i][2],ellipse,
           inverse(t)*((l_points_egal[2i]+l_points_egal[2i+2])/2+(-positionhorizontale,size(l_egals[0]).y/2)),
           Fill(white));
      draw(l_texte[i][2],ellipse,
           inverse(t)*((l_points_egal[2i+1]+l_points_egal[2i+3])/2+(positionhorizontale,size(l_egals[0]).y/2)),
           0.8,Fill(black));
      draw(l_texte[i][2],ellipse,
           inverse(t)*((l_points_egal[2i+1]+l_points_egal[2i+3])/2+(positionhorizontale,size(l_egals[0]).y/2)),
           Fill(white));
      /* QUEST: pourquoi ce n'est pas draw(f,... */
    }
    else
    { // s'il n'y a pas de texte laterale, on fait une fleche entre l'operateur courant et le suivant.
      milieu1=(l_points_egal[2i]+l_points_egal[2i+1])/2;
      milieu2=(l_points_egal[2i+2]+l_points_egal[2i+3])/2;
      draw(f,(milieu1-(0,margeverticale))--
              milieu2+(0,size(l_egals[0]).y+margeverticale),
              Arrow);
      if (l_texte[i].length>3 && l_texte[i][3]!="") { // s'il y a un texte, on le rajoute.
       add(f,Label(l_texte[i][3],
           (milieu1+milieu2+(0,size(l_egals[0]).y))/2,
           2E));
      }
    }
  }
  }); //fin add
}



Le code des macros est assez attroce, mais j'ai pas mal bidouillé pour le faire, sans forcement tout comprendre. Si quelqu'un a une facon plus simple pour calculer les coordonnées d'une boite, ca m'interesse.

En gros, il faut donner une liste de listes de strings, qui ont le format {membre gauche, membre droit, texte coté, texte milieu}. Les membres sont ceux de l'equation à la ligne correspondant, le texte cote, c'est ce qu'on met sur les fleches laterales (x2; -5...) et texte milieu, c'est pour mettre sur la fleche du milieu. On peut ne pas mettre de texte sur les fleches.

La deuxieme liste, c'est les operateurs entre les membres. Il me semble qu'il est optionnel et dans ce cas on met des "=". Et le decalhorizontal, je ne sais plus ce que ca fait et j'ai la fleme de regarder dans mon code. Je crois que c'est pour le decalage des fleches sur les cotes.

Mais comme je l'ai dit, c'est tres artisanal. Ca meriterait d'etre grandement amelioré et epuré. J'aimerai bien faire la meme chose, mais pour des tableaux de proportionnalite.

Et je vais essayer de faire un programme python qui prend l'equation et crache tout seul la resolution avec les etapes intermediaires. Mais c'est pas pour tout de suite.

Re: Macros pour afficher des resolutions d'equations

MessagePosté: Mercredi 25 Août 2010, 20:38
par chellier
Romain Janvier a écrit:Le code des macros est assez atroce

Euh... non, non :roll: :)

Bon, c'est vrai que c'est pas simple. Je ne vais pas essayer de regarder de trop près le code (sinon je vais prendre mal à la tête).
Qu'appelles-tu "coordonnées des boites" ? Il faut juste le centre non ?

Je donne un exemple de ce que j'avais fait avec l'aide d'un exemple de la galerie de GM. Ce sera plus simple pour ceux qui suivraient le fil et je crois que l'idée est la même :
Code: Tout sélectionner
unitsize(1cm);

usepackage("amsmath");
usepackage("amsfonts");
usepackage("amssymb");

pair z0=(-1.75,0), z1=(1.75,0), z2=(0,1), z3=(0,-1);

object boite1=draw("$x < 5$",box,z2,invisible);
object boite2=draw("$\times (-2)$",ellipse,z0);
object boite3=draw("$\times (-2)$",ellipse,z1);
object boite4=draw("$\quad\dots\quad$",box,z3,invisible);

add(new void(picture pic, transform t) {
    draw(pic,point(boite1,W,t){W}..{S}point(boite2,N,t));
    draw(pic,point(boite2,S,t){S}..{E}point(boite4,NW,t),Arrow);
    draw(pic,point(boite1,E,t){E}..{S}point(boite3,N,t));
    draw(pic,point(boite3,S,t){S}..{W}point(boite4,NE,t),Arrow);
});

boite.png
boite.png (12.43 Kio) Vu 1139 fois

Christophe

Re: Macros pour afficher des resolutions d'equations

MessagePosté: Jeudi 26 Août 2010, 08:58
par Romain Janvier
C'est ce dont je me suis inspiré pour mes macros.

Mais le probleme, c'est que je ne peux pas deviner à l'avance la position des annotations sur les fleches.

En tout cas j'aime bien la forme de tes fleches dans ton exemple. Il faudrait que je reprenne mon code, mais je ne sais pas si j'aurai le temps d'ici la rentrée.

Edit:
J'ai mis à jour mon code en le commentant un peu mieux et en rajoutant quelques variables pour simplifier la lecture.

Mais il y a des trucs bizarres. J'ai mis des commentaires avec "QUEST:" pour indiquer mes interogations. Il faut dire que j'avais beaucoup bidouillé pour arriver à ce resultat et que j'ai un peu du mal à comprendre ce que fait ce "add( new void(frame ..."