Génération de plusieurs images à partir d'un fichier

Tout ce qui concerne l'utilisation ou l'installation d'Asymptote.

Modérateur: gdm_asy

Règles du forum
Merci d'éviter le style SMS dans vos messages et de penser à utiliser la fonction Recherche avant de poster un message. Pour joindre des fichiers à vos messages, consulter ce sujet.
> Penser à utiliser les balises Code pour poster du code.

Génération de plusieurs images à partir d'un fichier

Messagepar Romain Janvier » Mardi 24 Août 2010, 21:17

Bonjour,

J'ai fait un petit script python qui permet de generer plusiseurs images à partir d'un seul fichier. En fait je m'en sers pour ensuite faire des "animations" dans beamer.

Voici le code du script:

Code: Tout sélectionner
#!/usr/bin/python
# Filename: asy2slides.py
"""
asy2slides.py permet de creer plusieurs images a partir d'un seul
fichier asymptote.

Utilisation:
  asy2slides.py fichier.py
  asy2slides.py fichier1.asy ... fichierN.asy

Pour cela il faut indiquer dans le fichier ce qui sera sur chaque image.

Il suffit de rajouter avec le bloc de commandes concernees un commentaire:
/* couche 4 */
"couche" est le mot recherche par asy2slides.
Tout ce qui suit le commentaire et qui se trouve avant le prochain commentaire
se trouvera dans les images indiquees.

Pour indiquer les images, il est possible d'utiliser les expressions suivantes:
  4          pour aller sur la quatrieme image
  2,5,8      pour aller sur les images 2, 5 et 8
  3-7        pour aller des images 3 a 7 incluses
  -6         pour aller de la premiere a la 6eme image
  3-         pour aller de la 3eme a la derniere image

Tout ce qui se trouve avant la premiere indication de couche se trouvera au
debut de chaque fichier servant a generer les images.

Pour indiquer ce qui doit se trouver a la fin de chaque fichier,
il faut utiliser le commentaire:
/* fin */

Les fichiers servant a generer les images sont crees en utilisant les blocs
correspondant dans l'ordre dans lequel ils apparaissent dans le fichier
original.

Lors de la compilation, asy2slides affiche du code permettant d'utiliser
les images dans beamer

Ce fichier est librement modifiable et redistribuable.
"""

import subprocess
import sys


def maxslides(l_textes):
  #calcul le nombre max de slides
  monmax=1
  for texte in l_textes:
    t1=texte.split(",")
    for i in t1:
      t2=i.split("-")
      if len(t2)==1:
#on suppose qu'il y a au moins un nombre     
        monmax=max(int(t2[0]),monmax)
      else:
#on suppose qu'il n'y a pas plus de 2 nombres
        if t2[0].strip()!="":
          monmax=max(int(t2[0]),monmax)
        if t2[1].strip()!="":
          monmax=max(int(t2[1]),monmax)
  return monmax

""" grammaire de def des slides:
  slides := seq[,seq]*
  seq := nb
  seq := nb-
  seq := nb-nb
  seq := -nb
  """
def parseslides(texte,max):
  res=[]
  t1=texte.split(",")
  #print t1
  for i in t1:
    t2=i.split("-")
    if len(t2)==1:
#on suppose qu'il y a au moins un nombre     
      res+=[int(t2[0])]
    else:
#on suppose qu'il n'y a pas plus de 2 nombres
      val1=1
      val2=max+1
      if t2[0].strip()!="":
        val1=int(t2[0])
      if t2[1].strip()!="":
        val2=int(t2[1])+1
      for i in range(val1,val2):
        res+=[i]
  #print "le res de ",texte," est ",res
  return res


def parseasy(name):
  f=open(name,'r')
  #print "on ouvre", name
#texte du debut et de fin
  debutfin=["",""]
  debut=0
  fin=0
  couche=-1
#associe a chaque slide la liste des couches a afficher
  assoccouches=dict({})
#liste des textes de chaque couche
  couches=[]
  slides=[]
  ligne = f.readline()
  #print "on commence"
  while ligne!='':
    #print ligne[0:1]
    if ligne[0:2]=="/*":
      #print "un commentaire"
      #On est dans un commentaire
      ligne2=ligne.split("couche")
      if len(ligne2)>1:
        #print "on vient de voir une couche"
#on vient de voir une def de couche
        couche+=1
        #print couche
        slides+=[ligne2[1][:-3]]
        couches+=[""]
      if len(ligne.split("fin"))>1:
        fin=1
    if fin:
      debutfin[1]+=ligne
    elif couche>-1:
      couches[couche]+=ligne
    else:
      debutfin[0]+=ligne
    ligne = f.readline()
  max=maxslides(slides)
  #print slides
  #print "max:",max
  for i in range(len(slides)):
    res=parseslides(slides[i],max)
    for j in res:
      #print "res:",res,"j:",j,"asso:",str(assoccouches.get(j,"non"))
      if j in assoccouches and i not in assoccouches[j]:
        assoccouches[j]+=[i]
      elif j not in assoccouches:
        assoccouches[j]=[i]
  #print assoccouches
  #print couches
  lname=["/usr/bin/asy"]
  for i in range(max):
    j=i+1
    print "on passe a ",j," sur ",max
    nameout=name[:-4]+"_"+str(j)+".asy"
    lname+=[nameout]
    #print "/* texte pour le slide "+str(j)+" */"
    slides_a_afficher=assoccouches.get(j,[])
    #print slides_a_afficher
    l=sorted(slides_a_afficher)
    fout=open(nameout,'w')
    print "ecriture de ",nameout
    fout.write(debutfin[0])
    for k in l:
      fout.write(couches[k])
    fout.write(debutfin[1])
    fout.close()
  for i in range(1,len(lname)):
    print "\only<"+str(i)+">{\includegraphics{asymptote/"+lname[i][:-3]+"eps}}%"
  print "on compile" 
  #os.execv('/usr/bin/asy',lname)
  #print lname
  subprocess.call(lname)
  #print "on a fini de compiler"
   
if __name__ == "__main__":
  if len(sys.argv)==1:
    print "usage: asy2slides.py fichier.asy [fichier2.asy]*"
  else:
    for name in sys.argv[1:]:
      parseasy(name)


Et voici un exemple de fichier me permettant de genere mes images:

Code: Tout sélectionner
/* debut */
/* ceci sera dans toutes les images */
import geometry;
import graph_pi;
unitsize(1cm);

pair A=(0,0);
pair B=(3,1);
pair D=(-1,2);
pair C=D+B;
pair Pt=(3.5,2);
pair Pt1=(3.5,1.5);
pair Pt2=(3.5,1);
pair Pt3=(3,3);
pair Pt4=(3,2.5);
draw((-3,-2)--(8,4),white);
draw(A--2B,white);
draw(C--(C-2B),white);
draw(A--2D,white);
draw(C--(C-2D),white);


/* couche 1 */
/* ceci ne sera que dans la premiere image */
draw(A--B,lightgray);
draw(C--D,lightgray);
draw(A--D,lightgray);
draw(C--B,lightgray);
label("$O$ est le centre",Pt,align=NE);
label("de sym\'etrie",Pt1,align=NE);
label("entre $A$ et $C$",Pt2,align=NE);
draw((Pt+(0.3,0.5))..controls Pt+(0,1) and C+(0.5,0.1)..C,Arrow());
draw((Pt2+(0.3,-0.1))..controls Pt2+(0.1,-1) and A+(1,-0.3)..A,Arrow());

/* couche 2 */
/* ceci ne sera que dans l'image 2 */
draw(A--2B);
draw(C--(C-2B));
draw(A--D,lightgray);
draw(C--B,lightgray);
label("$(AB)$ et $(CD)$",Pt3,align=NE);
label("sont sym\'etriques",Pt4,align=NE);
draw((Pt3+(0.4,0.5))..controls Pt3+(-0.4,1.3) and (C-0.3B+(1,1))..(C-0.3B),Arrow());
draw((Pt4+(0.3,-0.1))..controls Pt4+(0.1,-1) and 0.7B+(1,1)..0.7B,Arrow());

/* couche 3 */
/* ceci ne sera que dans l'image 3 */
draw(A--2D);
draw(C--(C-2D));
draw(A--B,lightgray);
draw(C--D,lightgray);
label("$(AD)$ et $(CB)$",Pt3,align=NE);
label("sont sym\'etriques",Pt4,align=NE);
draw((Pt3+(0.4,0.5))..controls Pt3+(-0.4,1.3) and (1.5D+(1,0.5))..1.5D,Arrow());
draw((Pt4+(0.3,-0.1))..controls Pt4+(0.1,-1) and B-0.5D+(1,1)..B-0.5D,Arrow());

/* couche 4 */
/* ceci ne sera que dans l'image 4 */
draw(A--2B);
draw(C--(C-2B));
draw(A--2D);
draw(C--(C-2D));
label("Donc $B$ et $D$",Pt3,align=NE);
label("sont sym\'etriques",Pt4,align=NE);
draw((Pt3+(0.4,0.5))..controls Pt3+(-0.4,1.3) and (D+(1,1))..D,Arrow());
draw((Pt4+(0.3,-0.1))..controls Pt4+(0.1,-1) and B+(0.2,1)..B,Arrow());

/* couche 5 */
/* ceci ne sera que dans l'image 5 */
draw(A--B,red,StickIntervalMarker(1,2,red));
draw(C--D,red,StickIntervalMarker(1,2,red));
draw(A--D,lightgray);
draw(C--B,lightgray);

/* couche 6- */
/* ceci sera dans l'image 6 et les suivantes */
draw(A--B,red,StickIntervalMarker(1,2,red));
draw(C--D,red,StickIntervalMarker(1,2,red));
draw(C--B,blue,StickIntervalMarker(1,1,blue));
draw(A--D,blue,StickIntervalMarker(1,1,blue));

/* couche 7 */
/* ceci ne sera que dans l'image 7 */
draw(B--D,purple,StickIntervalMarker(2,3,purple));

/* fin */
/* ceci sera dans toutes les images */
draw(A--C,deepgreen,TildeIntervalMarker(2,1,deepgreen));
label("$A$",A,align=S+0.1W);
label("$B$",B,align=SW+S);
label("$C$",C,align=N+0.5E);
label("$D$",D,align=NE+N);
dot(A);
dot(B);
dot(C);
dot(D);
dot(Label("$O$",align=1.5S+0.5E),midpoint(segment(A,C)));
xlimits(-3,8,Crop);
ylimits(-2,4,Crop);


L'avantage, c'est que pour changer quelque chose, il suffit de modifier un seul fichier et de tout regenerer.

Ca manque d'options, mais ca me suffit. A priori, ca ne marche que sous linux, mais ca ne doit pas etre compliqué de le modifier pour mac os ou windows.

J'espere que cela pourra vous servir.

Si vous avez des remarques, ameliorations, critiques, n'hesitez pas.

Romain Janvier
Romain Janvier
Kilo-utilisateur
 
Messages: 146
Inscription: Lundi 23 Août 2010, 13:57
Statut actuel: Actif et salarié | Enseignant

Publicité

Re: Generation de plusieurs images à partir d'un fichier

Messagepar OG » Mardi 24 Août 2010, 21:56

Bonsoir

Merci. Le fait de pouvoir générer uniquement la 4ème ou de 1 à 4 peut être pratique.
Cela sort un eps ? Il pourrait être utile d'avoir un choix de sortie pdf (svg, png soyons fous) ?

Cela me fait penser que j'avais l'intention de faire un code à la matplotlib, une directive python pour sphinx qui permet d'inclure le code coloré par pygments et/ou le graphique.

O.G.
OG
Modérateur
 
Messages: 2285
Inscription: Lundi 12 Mars 2007, 11:20
Localisation: Rouen
Statut actuel: Actif et salarié | Maître de conférence

Re: Génération de plusieurs images à partir d'un fichier

Messagepar Romain Janvier » Mardi 24 Août 2010, 23:58

Pour faire du pdf ou un autre format, on peut le demander dans le fichier asy, non. Ca fait un moment que je n'en ai pas fait, mais il n'y a pas une commande pour ca, du genre outputformat=png?

Et pour choisir les slides a regenerer, ca peut aussi se faire, mais pour cela il faut que je rajoute le support des options passées en lignes de commandes et je ne suis pas specialement pressé de le faire.

Si vraiment on ne veut modifier que la 4eme image, on peut tout generer une premiere fois et ensuite bidouiller fichier_4.asy.

Pendant que j'y pense, j'ai un probleme avec ce script. Lorsque les images produites ont des bounding box differentes, ca produti des images avec des dimensions differentes. Je n'ai pas trouvé comment faire cracher à asymptote les coordonnees des bounding box de chaque image pour ensuite mettre les dimensions max dans mon fichier asy.

J'avais trouve comment imprimer les coordonnées max et min, mais l'unité obtenue ne correspondait pas à l'unité que j'utilise, donc je ne savais pas trop quoi en faire.

Si quelqu'un sait comment faire, ca m'interesse.

Merci.
Romain Janvier
Kilo-utilisateur
 
Messages: 146
Inscription: Lundi 23 Août 2010, 13:57
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar chellier » Mercredi 25 Août 2010, 08:55

Romain Janvier a écrit:Pendant que j'y pense, j'ai un probleme avec ce script. Lorsque les images produites ont des bounding box differentes, ca produti des images avec des dimensions differentes. Je n'ai pas trouvé comment faire cracher à asymptote les coordonnees des bounding box de chaque image pour ensuite mettre les dimensions max dans mon fichier asy.

J'avais trouve comment imprimer les coordonnées max et min, mais l'unité obtenue ne correspondait pas à l'unité que j'utilise, donc je ne savais pas trop quoi en faire.

Si quelqu'un sait comment faire, ca m'interesse.


Bonjour,
Voilà comment je procède :

Code: Tout sélectionner
pair mini, maxi;
picture pic; 
pic.add(currentpicture);// Sauvegarde de l'image dans pic
mini=min(pic)/cm; maxi=max(pic)/cm; // coordonnées (cm) de la "bounding box" (gauche,bas) et (droite,haut)


Christophe
chellier
Modérateur
 
Messages: 355
Inscription: Samedi 25 Juillet 2009, 11:25
Localisation: Le Creusot
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar Romain Janvier » Mercredi 25 Août 2010, 09:53

Merci pour l'info, mais lorsque j'affiche le resultat pour le fichier que j'ai donné en exemple, j'obtiens:
min(-0.105833333333333,-0.0705555555555556)
max(0.282222222222222,0.141111111111111)

Ca ne correspond pas du tout aux limites de mon fichier. Par contre, si je vire les "/cm", ca me donne:
min(-3,-2)
max(8,4)

Ce qui correspond aux limites que j'ai indiqué.

Du coup, je pourrai eventuellement faire une premiere passe en compilant le fichier .asy tel qu'il est, recuperer les limites et ensuite rajouter le code pour faire la meme dimension à chaque image.

D'ailleurs, quelle est la meilleure facon de faire, pour obliger l'image à rentrer dans un rectangle de doagonale (-3,-2) - (8,4)?

Dans l'exemple, j'ai mis:
Code: Tout sélectionner
xlimits(-3,8,Crop);
ylimits(-2,4,Crop);


Mais il me semble que j'avais eu des problemes avec ca. Du coup après, je faisais un trait en blanc reliant les deux points extremes. Mais ce n'est pas très "propre".

Et je vais reflechir à l'ajout des options.
Romain Janvier
Kilo-utilisateur
 
Messages: 146
Inscription: Lundi 23 Août 2010, 13:57
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar chellier » Mercredi 25 Août 2010, 10:09

Romain Janvier a écrit:Merci pour l'info, mais lorsque j'affiche le resultat pour le fichier que j'ai donné en exemple, j'obtiens:
min(-0.105833333333333,-0.0705555555555556)
max(0.282222222222222,0.141111111111111)

Ca ne correspond pas du tout aux limites de mon fichier. Par contre, si je vire les "/cm", ca me donne:
min(-3,-2)
max(8,4)

Ce qui correspond aux limites que j'ai indiqué.


Heu oui, exact :oops:

Romain Janvier a écrit:D'ailleurs, quelle est la meilleure facon de faire, pour obliger l'image à rentrer dans un rectangle de doagonale (-3,-2) - (8,4)?

Dans l'exemple, j'ai mis:
Code: Tout sélectionner
xlimits(-3,8,Crop);
ylimits(-2,4,Crop);


Mais il me semble que j'avais eu des problemes avec ca. Du coup après, je faisais un trait en blanc reliant les deux points extremes. Mais ce n'est pas très "propre".


Tu peux essayer
Code: Tout sélectionner
 clip(box((-3,-2),(8,4)));

Christophe
chellier
Modérateur
 
Messages: 355
Inscription: Samedi 25 Juillet 2009, 11:25
Localisation: Le Creusot
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar Romain Janvier » Mercredi 25 Août 2010, 10:35

Je suis en train de lire les docs du module argparse de python. Ca permet de faire des trucs pas mal.

Les options que je compte mettre pour l'instant:
-choisir la ou les couches a generer.
-calculer les limites min et max et les rajouter au fichier initial (ou aux fichiers generes?)
-faire le menage et virer les fichiers .asy en plus.
-passer des options a asymptote pour choisir le type des images de sortie, par exemple.

Ensuite il faudra que je regarde comment je peux rajouter des options pour choisir le format des lignes correspondant au code beamer.

Par contre, pour cette histoire de limites, j'avais essayé avec "min(currentpicture)" et ca ne marchait pas vraiment. C'est le add qui fait tout? Ca force la generation de l'image avant de faire le calcul, c'est ca?
Romain Janvier
Kilo-utilisateur
 
Messages: 146
Inscription: Lundi 23 Août 2010, 13:57
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar chellier » Mercredi 25 Août 2010, 11:01

Romain Janvier a écrit:Par contre, pour cette histoire de limites, j'avais essayé avec "min(currentpicture)" et ca ne marchait pas vraiment. C'est le add qui fait tout? Ca force la generation de l'image avant de faire le calcul, c'est ca?

C'est un problème d'unités. Apparemment l'unité de currentpicture est toujours le bp (c'est là qu'il faut le "/cm"). Alors que pour pic, l'unité sera bien celle des points.

C'est ce que j'ai compris, mais ce sont des subtilités d'asymptote pas évidentes (pour moi :oops: ).

Christophe
chellier
Modérateur
 
Messages: 355
Inscription: Samedi 25 Juillet 2009, 11:25
Localisation: Le Creusot
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar Romain Janvier » Mercredi 25 Août 2010, 12:23

Pour moi aussi c'est galère.

Je ferai un autre sujet, mais j'ai aussi fait des macros pour afficher les differentes etapes de resolutions d'une equation, en mettant des fleches sur les cotés pour indiquer l'operation effectuee, et j'ai galéré pour placer les fleches comme il faut.

D'ailleurs, il y a un moyen pour utiliser les longueurs de latex dans asymptote, du genre \em ou \ex, ou toute autre longueur latex?
Romain Janvier
Kilo-utilisateur
 
Messages: 146
Inscription: Lundi 23 Août 2010, 13:57
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar chellier » Mercredi 25 Août 2010, 13:18

Romain Janvier a écrit:D'ailleurs, il y a un moyen pour utiliser les longueurs de latex dans asymptote, du genre \em ou \ex, ou toute autre longueur latex?

Il me semble que seul le pt TeX est défini. Il faudrait définir les autres.

Romain Janvier a écrit:Je ferai un autre sujet, mais j'ai aussi fait des macros pour afficher les differentes etapes de resolutions d'une equation, en mettant des fleches sur les cotés pour indiquer l'operation effectuee, et j'ai galéré pour placer les fleches comme il faut.

Intéressant. Je m'étais aussi penché sur le problème des flèches sur le côté... dur dur !

Christophe
chellier
Modérateur
 
Messages: 355
Inscription: Samedi 25 Juillet 2009, 11:25
Localisation: Le Creusot
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar Romain Janvier » Dimanche 29 Août 2010, 18:53

J'ai mis à jour mon script pour utiliser des options. Je vous conseille de sauvegarder vos fichiers avant de tester. Vous pouvez faire "asy2slides.py -h" pour avoir les options.

J'ai du installer python-argparse pour pouvoir l'utiliser.

Lors de la premiere utilisation avec un nouveau fichier, il crée une sauvegarde "monfichier.old", au cas où. Elle n'est pas ecrasée par la suite, Mais elle est effacée par l'option -c, qui vire aussi tous les .asy générés.

J'ai encore un peu de mal avec le clip(box(... qui me sort des resultats bizarres avec mes "equations". Peut etre parce que j'utilise un "add(new void(..." Ca me sort des erreurs à la compilation. Et j'ai un autre fichier pour lequel j'obtiens des coordonnées qui ne correspondent pas. En plus le clip(box(... ne semble pas avoir d'effet.

C'est bien la bonne methode pour imposer les dimensions de la bbox de l'image? Parce que je veux, c'est que toutes mes images générées aient la meme bbox, comme ca, ca ne fait pas de deplacement bizarre lorsque je change de slide dans beamer.

Et pour ceux qui n'ont pas asymptote installé dans /usr/bin, vous pouvez changer l'emplacement de l'executable à la ligne 51.

Voici le code:

Code: Tout sélectionner
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Filename: asy2slides.py

"""
asy2slides.py permet de creer plusieurs images a partir d'un seul
fichier asymptote.

Utilisation:
  asy2slides.py fichier.py
  asy2slides.py fichier1.asy ... fichierN.asy

Pour cela il faut indiquer dans le fichier ce qui sera sur chaque image.

Il suffit de rajouter avec le bloc de commandes concernees un commentaire:
/* couche 4 */
"couche" est le mot recherche par asy2slides.
Tout ce qui suit le commentaire et qui se trouve avant le prochain commentaire
se trouvera dans les images indiquees.

Pour indiquer les images, il est possible d'utiliser les expressions suivantes:
  4          pour aller sur la quatrieme image
  2,5,8      pour aller sur les images 2, 5 et 8
  3-7        pour aller des images 3 a 7 incluses
  -6         pour aller de la premiere a la 6eme image
  3-         pour aller de la 3eme a la derniere image

Tout ce qui se trouve avant la premiere indication de couche se trouvera au
debut de chaque fichier servant a generer les images.

Pour indiquer ce qui doit se trouver a la fin de chaque fichier,
il faut utiliser le commentaire:
/* fin */

Les fichiers servant a generer les images sont crees en utilisant les blocs
correspondant dans l'ordre dans lequel ils apparaissent dans le fichier
original.

Lors de la compilation, asy2slides affiche du code permettant d'utiliser
les images dans beamer

Ce fichier est librement modifiable et redistribuable.
"""

import subprocess
import sys
import argparse
import shutil
import os

asypath='/usr/bin/asy'

def ajoutcode(fich,fichbbox,fichtmp):
  #on recopie le fichier en enlevant un eventuel clip(box(...
  f1=open(fich,'r')
  f2=open(fichbbox,'w')
  for ligne in f1:
    # on recopie tout sauf 'clip'
    if not ligne.strip().startswith('clip'):
      f2.write(ligne)
#  shutil.copy(fich,fichbbox)
#  f=open(fichbbox,'a')
  f2.write('pair minibbox, maxibbox;\n')
  f2.write('picture picbbox;\n')
  f2.write('picbbox.add(currentpicture);\n')
  f2.write('write("clip(box("+(string)min(picbbox,true)+","+(string)max(picbbox,true)+"));");\n')
  f2.write('file fout = output("'+fichtmp+'",false);\n')
  f2.write('write(fout);')
  f2.write('write(fout,"clip(box("+(string)min(picbbox,true)+","+(string)max(picbbox,true)+"));");\n')
  f1.close()
  f2.close()

def ajoutbbox(fich,fichbbox,bbox):
  f1=open(fich,'w')
  f2=open(fichbbox,'r')
  fin=1
  for ligne in f2:
    # on recopie tout sauf le code rajoute
    if ligne=='pair minibbox, maxibbox;\n':
      break
    if ligne=='/* fin */\n':
      print "on a vu la fin"
      fin=0
    f1.write(ligne)
  if fin:
    print "on rajoute la fin"
    f1.write('/* fin */\n')
  f1.write(bbox)
  f1.close()
  f2.close()


def maxslides(l_textes):
  #calcul le nombre max de slides
  monmax=1
  for texte in l_textes:
    t1=texte.split(",")
    for i in t1:
      t2=i.split("-")
      if len(t2)==1:
#on suppose qu'il y a au moins un nombre     
        monmax=max(int(t2[0]),monmax)
      else:
#on suppose qu'il n'y a pas plus de 2 nombres
        if t2[0].strip()!="":
          monmax=max(int(t2[0]),monmax)
        if t2[1].strip()!="":
          monmax=max(int(t2[1]),monmax)
  return monmax

""" grammaire de def des slides:
  slides := seq[,seq]*
  seq := nb
  seq := nb-
  seq := nb-nb
  seq := -nb
  """

def parseslides(texte,max):
  res=[]
  t1=texte.split(",")
  #print t1
  for i in t1:
    t2=i.split("-")
    if len(t2)==1:
#on suppose qu'il y a au moins un nombre     
      res+=[int(t2[0])]
    else:
#on suppose qu'il n'y a pas plus de 2 nombres
      val1=1
      val2=max+1
      if t2[0].strip()!="":
        val1=int(t2[0])
      if t2[1].strip()!="":
        val2=int(t2[1])+1
      for i in range(val1,val2):
        res+=[i]
  #print "le res de ",texte," est ",res
  return res


def parseasy(name,options,slideslc):
  f=open(name,'r')
  #print "on ouvre", name
#texte du debut et de fin
  debutfin=["",""]
  debut=0
  fin=0
  couche=-1
#associe a chaque slide la liste des couches a afficher
  assoccouches=dict({})
#liste des textes de chaque couche
  couches=[]
  slides=[]
  ligne = f.readline()
  #print "on commence"
  while ligne!='':
    #print ligne[0:1]
    if ligne[0:2]=="/*":
      #print "un commentaire"
      #On est dans un commentaire
      ligne2=ligne.split("couche")
      if len(ligne2)>1:
        #print "on vient de voir une couche"
#on vient de voir une def de couche
        couche+=1
        #print couche
        slides+=[ligne2[1][:-3]]
        couches+=[""]
      if len(ligne.split("fin"))>1:
        fin=1
    if fin:
      debutfin[1]+=ligne
    elif couche>-1:
      couches[couche]+=ligne
    else:
      debutfin[0]+=ligne
    ligne = f.readline()
  max=maxslides(slides)
  #print slides
  #print "max:",max
  for i in range(len(slides)):
    res=parseslides(slides[i],max)
    for j in res:
      #print "res:",res,"j:",j,"asso:",str(assoccouches.get(j,"non"))
      if j in assoccouches and i not in assoccouches[j]:
        assoccouches[j]+=[i]
      elif j not in assoccouches:
        assoccouches[j]=[i]
  #print assoccouches
  #print couches
  listeslides=[]
# On cherche les slides donnes en ligne de commande
  if slideslc!='':
    listeslides=parseslides(slideslc,max)
  lname=[asypath,options]
# On s'occupe des slides a creer
  for i in range(max):
    j=i+1
    if slideslc=='' or j in listeslides:
      print "on passe a ",j," sur ",max
      nameout=name[:-4]+"_"+str(j)+".asy"
      lname+=[nameout]
      #print "/* texte pour le slide "+str(j)+" */"
      slides_a_afficher=assoccouches.get(j,[])
      #print slides_a_afficher
      l=sorted(slides_a_afficher)
      fout=open(nameout,'w')
      print "ecriture de ",nameout
      fout.write(debutfin[0])
      for k in l:
        fout.write(couches[k])
      fout.write(debutfin[1])
      fout.close()
  for i in range(max):
    print "\only<"+str(i+1)+">{\includegraphics{asymptote/"+\
        name[:-4]+"_"+str(i+1)+".asy}%"
  print "on compile" 
  #os.execv('/usr/bin/asy',lname)
  #print lname
  subprocess.call(lname)
  #print "on a fini de compiler"
   
if __name__ == "__main__":
  parser = argparse.ArgumentParser(description="Produit plusieurs images a\
      partir d'un seul fichier asymptote.")
  parser.add_argument('fichiers', metavar='fichier.asy', type=str,
      nargs='+', help='Un fichier asymptote.')
  parser.add_argument('-s','--slides',
      type=str, default='',
      help='Indique les slides a afficher.')
  parser.add_argument('-b','--bbox', action='store_true',
      help='Calcule la bbox maximum et la rajoute au fichier initial.')
  parser.add_argument('-c','--clean',action='store_true',
      help='Efface les fichiers intermediaires mais pas les images produites.')
  parser.add_argument('-o','--options',type=str, default='',
      help='Options passees a asy.')
# On parse la ligne de commande
  args = parser.parse_args()

  for fich in args.fichiers:
    fichbbox=fich+'-bbox.asy'
    fichtmp=fich+'-bbox.tmp'
    fichold=fich+'.old'
# ajout de la bbox maximale
    if args.bbox:
#on fait une premiere sauvegarde qui ne sera pas ecrasee
      if not os.path.exists(fich+'.old'):
        shutil.copy(fich,fichold)
#on rajoute du code pour obtenir les dimensions de la bbox
      ajoutcode(fich,fichbbox,fichtmp)
      # On compile une premiere fois et on recupere la bbox     
      subprocess.call([asypath ,fichbbox])
      ftmp=open(fichtmp,'r')
      # On verifie que tout se passe bien:
      ltmp= ftmp.readlines()
      ftmp.close()
      if len(ltmp)==1 and ltmp[0].startswith('clip(box(('):
        ajoutbbox(fich,fichbbox,ltmp[0])

#effacement des fichiers inutiles
    if args.clean:
      listefichiers=os.listdir('.')
      for dirfile in listefichiers:
        if dirfile==fichold or dirfile.startswith(fich+'-bbox.') or \
          (dirfile.startswith(fich[:-4]+"_") and dirfile[-4:]=='.asy'):
            print "Effacement de:",dirfile
            os.remove(dirfile)
    else:
    # Compilation des fichiers:
      parseasy(fich,args.options,args.slides)
     
Romain Janvier
Kilo-utilisateur
 
Messages: 146
Inscription: Lundi 23 Août 2010, 13:57
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar chellier » Dimanche 29 Août 2010, 20:15

Romain Janvier a écrit:J'ai encore un peu de mal avec le clip(box(... qui me sort des resultats bizarres avec mes "equations". Peut etre parce que j'utilise un "add(new void(..." Ca me sort des erreurs à la compilation. Et j'ai un autre fichier pour lequel j'obtiens des coordonnées qui ne correspondent pas. En plus le clip(box(... ne semble pas avoir d'effet.

C'est bien la bonne methode pour imposer les dimensions de la bbox de l'image? Parce que je veux, c'est que toutes mes images générées aient la meme bbox, comme ca, ca ne fait pas de deplacement bizarre lorsque je change de slide dans beamer.

Ah, ces problèmes de bounding box ! Peut-on avoir un ECM reproduisant le problème ?

Christophe
chellier
Modérateur
 
Messages: 355
Inscription: Samedi 25 Juillet 2009, 11:25
Localisation: Le Creusot
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar Romain Janvier » Dimanche 29 Août 2010, 20:24

Voici un exemple qui me produit des coordonnées foireuses et qui ne sont meme pas utilisées lorsque je produis mes images. Ok, ce n'est pas minimal, mais au moins ca illustre le probleme.

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

pair A=(0,0);
pair B=(3,1);
pair D=(-1,2);
pair C=D+B;
pair Pt=(3.5,2);
pair Pt1=(3.5,1.5);
pair Pt2=(3.5,1);
pair Pt3=(3,3);
pair Pt4=(3,2.5);
//draw((-3,-2)--(8,4),white);
//draw(A--2B,white);
//draw(C--(C-2B),white);
//draw(A--2D,white);
//draw(C--(C-2D),white);


/* couche 1 */
draw(A--B,lightgray);
draw(C--D,lightgray);
draw(A--D,lightgray);
draw(C--B,lightgray);
label("$O$ est le centre",Pt,align=NE);
label("de sym\'etrie",Pt1,align=NE);
label("entre $A$ et $C$",Pt2,align=NE);
draw((Pt+(0.3,0.5))..controls Pt+(0,1) and C+(0.5,0.1)..C,Arrow());
draw((Pt2+(0.3,-0.1))..controls Pt2+(0.1,-1) and A+(1,-0.3)..A,Arrow());

/* couche 2 */
draw(A--2B);
draw(C--(C-2B));
draw(A--D,lightgray);
draw(C--B,lightgray);
label("$(AB)$ et $(CD)$",Pt3,align=NE);
label("sont sym\'etriques",Pt4,align=NE);
draw((Pt3+(0.4,0.5))..controls Pt3+(-0.4,1.3) and (C-0.3B+(1,1))..(C-0.3B),Arrow());
draw((Pt4+(0.3,-0.1))..controls Pt4+(0.1,-1) and 0.7B+(1,1)..0.7B,Arrow());

/* couche 3 */
draw(A--2D);
draw(C--(C-2D));
draw(A--B,lightgray);
draw(C--D,lightgray);
label("$(AD)$ et $(CB)$",Pt3,align=NE);
label("sont sym\'etriques",Pt4,align=NE);
draw((Pt3+(0.4,0.5))..controls Pt3+(-0.4,1.3) and (1.5D+(1,0.5))..1.5D,Arrow());
draw((Pt4+(0.3,-0.1))..controls Pt4+(0.1,-1) and B-0.5D+(1,1)..B-0.5D,Arrow());

/* couche 4 */
draw(A--2B);
draw(C--(C-2B));
draw(A--2D);
draw(C--(C-2D));
label("Donc $B$ et $D$",Pt3,align=NE);
label("sont sym\'etriques",Pt4,align=NE);
draw((Pt3+(0.4,0.5))..controls Pt3+(-0.4,1.3) and (D+(1,1))..D,Arrow());
draw((Pt4+(0.3,-0.1))..controls Pt4+(0.1,-1) and B+(0.2,1)..B,Arrow());

/* couche 5 */
draw(A--B,red,StickIntervalMarker(1,2,red));
draw(C--D,red,StickIntervalMarker(1,2,red));
draw(A--D,lightgray);
draw(C--B,lightgray);

/* couche 6- */
draw(A--B,red,StickIntervalMarker(1,2,red));
draw(C--D,red,StickIntervalMarker(1,2,red));
draw(C--B,blue,StickIntervalMarker(1,1,blue));
draw(A--D,blue,StickIntervalMarker(1,1,blue));

/* couche 7 */
draw(B--D,purple,StickIntervalMarker(2,3,purple));

/* fin */
draw(A--C,deepgreen,TildeIntervalMarker(2,1,deepgreen));
label("$A$",A,align=S+0.1W);
label("$B$",B,align=SW+S);
label("$C$",C,align=N+0.5E);
label("$D$",D,align=NE+N);
dot(A);
dot(B);
dot(C);
dot(D);
dot(Label("$O$",align=1.5S+0.5E),midpoint(segment(A,C)));
//xlimits(-3,8,Crop);
//ylimits(-2,4,Crop);

clip(box((-7.74645305663002,-14.7875062637824),(92.7453842214412,18.9867590657749)));
Romain Janvier
Kilo-utilisateur
 
Messages: 146
Inscription: Lundi 23 Août 2010, 13:57
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar chellier » Mardi 31 Août 2010, 10:56

Romain Janvier a écrit:Ok, ce n'est pas minimal, mais au moins ca illustre le probleme.

:roll:

Bon, j'ai fait pas mal d'essais. J'avais un peu de mal avec ces problèmes de bounding box, mais alors là je suis encore plus perdu :?
Si ces problèmes de décalage t'embêtent vraiment, il ne faut pas oublier qu'asymptote sait très bien faire les animations. Il ne faut pas modifier grand chose à ton fichier de départ, et à la fin du code j'ai mis quelques unes des différentes sorties possibles.
Si tu n'es pas contre utiliser acrobat reader (si tu es contre, ça peut se comprendre :wink: ) et que tu compiles avec pdflatex, tu peux inclure directement l'animation produite dans la présentation beamer (enfin je crois, je n'ai pas fait l'essai).
Sinon, cette sortie :
Code: Tout sélectionner
label(anim.pdf("controls,step",keep=true,multipage=false));

permet d'obtenir toutes les figures (les 7 dans ton exemple) au format pdf. Après on peut toujours les convertir en eps.

Voila le code :
Code: Tout sélectionner
/* debut */
/* ceci sera dans toutes les images */
import geometry;
//import graph_pi;   // inutile ici, il me semble ?
import animate;
settings.tex="pdflatex";
settings.outformat="pdf";
unitsize(1cm);

animation anim;

pair A=(0,0);
pair B=(3,1);
pair D=(-1,2);
pair C=D+B;
pair Pt=(3.5,2);
pair Pt1=(3.5,1.5);
pair Pt2=(3.5,1);
pair Pt3=(3,3);
pair Pt4=(3,2.5);

draw(A--C,deepgreen,TildeIntervalMarker(2,1,deepgreen));
label("$A$",A,align=S+0.1W);
label("$B$",B,align=SW+S);
label("$C$",C,align=N+0.5E);
label("$D$",D,align=NE+N);
dot(A);
dot(B);
dot(C);
dot(D);
dot(Label("$O$",align=1.5S+0.5E),midpoint(segment(A,C)));

/* couche 1 */
/* ceci ne sera que dans la premiere image */
save();
draw(A--B,lightgray);
draw(C--D,lightgray);
draw(A--D,lightgray);
draw(C--B,lightgray);
label("$O$ est le centre",Pt,align=NE);
label("de sym\'etrie",Pt1,align=NE);
label("entre $A$ et $C$",Pt2,align=NE);
draw((Pt+(0.3,0.5))..controls Pt+(0,1) and C+(0.5,0.1)..C,Arrow());
draw((Pt2+(0.3,-0.1))..controls Pt2+(0.1,-1) and A+(1,-0.3)..A,Arrow());
anim.add();
restore();

/* couche 2 */
/* ceci ne sera que dans l'image 2 */
save();
draw(A--2B);
draw(C--(C-2B));
draw(A--D,lightgray);
draw(C--B,lightgray);
label("$(AB)$ et $(CD)$",Pt3,align=NE);
label("sont sym\'etriques",Pt4,align=NE);
draw((Pt3+(0.4,0.5))..controls Pt3+(-0.4,1.3) and (C-0.3B+(1,1))..(C-0.3B),Arrow());
draw((Pt4+(0.3,-0.1))..controls Pt4+(0.1,-1) and 0.7B+(1,1)..0.7B,Arrow());
anim.add();
restore();

/* couche 3 */
/* ceci ne sera que dans l'image 3 */
save();
draw(A--2D);
draw(C--(C-2D));
draw(A--B,lightgray);
draw(C--D,lightgray);
label("$(AD)$ et $(CB)$",Pt3,align=NE);
label("sont sym\'etriques",Pt4,align=NE);
draw((Pt3+(0.4,0.5))..controls Pt3+(-0.4,1.3) and (1.5D+(1,0.5))..1.5D,Arrow());
draw((Pt4+(0.3,-0.1))..controls Pt4+(0.1,-1) and B-0.5D+(1,1)..B-0.5D,Arrow());
anim.add();
restore();

/* couche 4 */
/* ceci ne sera que dans l'image 4 */
save();
draw(A--2B);
draw(C--(C-2B));
draw(A--2D);
draw(C--(C-2D));
label("Donc $B$ et $D$",Pt3,align=NE);
label("sont sym\'etriques",Pt4,align=NE);
draw((Pt3+(0.4,0.5))..controls Pt3+(-0.4,1.3) and (D+(1,1))..D,Arrow());
draw((Pt4+(0.3,-0.1))..controls Pt4+(0.1,-1) and B+(0.2,1)..B,Arrow());
anim.add();
restore();

/* couche 5 */
/* ceci ne sera que dans l'image 5 */
save();
draw(A--B,red,StickIntervalMarker(1,2,red));
draw(C--D,red,StickIntervalMarker(1,2,red));
draw(A--D,lightgray);
draw(C--B,lightgray);
anim.add();
restore();

/* couche 6- */
/* ceci sera dans l'image 6 et les suivantes */
draw(A--B,red,StickIntervalMarker(1,2,red));
draw(C--D,red,StickIntervalMarker(1,2,red));
draw(C--B,blue,StickIntervalMarker(1,1,blue));
draw(A--D,blue,StickIntervalMarker(1,1,blue));
anim.add();

/* couche 7 */
/* ceci ne sera que dans l'image 7 */
draw(B--D,purple,StickIntervalMarker(2,3,purple));
anim.add();

/* fin */

erase();

// Choisir une sortie :

//label(anim.pdf("controls,step",keep=true,multipage=false));  //pour figures pdf séparées
//label(anim.pdf("controls,step",keep=true,multipage=true));  // pour animation+multipage
label(anim.pdf("controls,step"));  // pour uniquement l'animation  // step pour "pas à pas"
//anim.movie();  // pdf multipage


Si quelqu'un a une explication claire sur ces problèmes de dimensions-coordonnées de bbox, je suis preneur :D

Christophe
chellier
Modérateur
 
Messages: 355
Inscription: Samedi 25 Juillet 2009, 11:25
Localisation: Le Creusot
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar Romain Janvier » Mardi 31 Août 2010, 11:09

Ben le truc, c'est que je veux mettre ces images avec du texte autour, et pas juste faire des animations "animées". J'en ai fait pour illustrer par exemple le depliage d'un prisme droit, mais dans ce cas je fais effectivement un pdf juste pour l'animation. D'ailleurs j'ai aussi eu ces problemes de bbox, avec un effet de zoom arriere lors du depliage, vu que la bbox augmentait au fur et a mesure.

Et si j'utilise mon script au lieu de animate puis la conversion en multiples eps, c'est parce que dans certain cas, j'ai des constructions plus complexes que juste:

couche 1
couche 2
couche 3
...

mais plutot des

couche 1-3
couche 2,5
couche 4
couche 1,4
...

et ca c'est plus dur avec l'exemple que tu as montré.
Romain Janvier
Kilo-utilisateur
 
Messages: 146
Inscription: Lundi 23 Août 2010, 13:57
Statut actuel: Actif et salarié | Enseignant

Re: Génération de plusieurs images à partir d'un fichier

Messagepar OG » Lundi 04 Octobre 2010, 22:07

Romain Janvier a écrit:D'ailleurs, il y a un moyen pour utiliser les longueurs de latex dans asymptote, du genre \em ou \ex, ou toute autre longueur latex?

Dans quel but ?
C'est peut-être possible en créant une boite contenant le caractère et en récupérant sa taille.

O.G.
OG
Modérateur
 
Messages: 2285
Inscription: Lundi 12 Mars 2007, 11:20
Localisation: Rouen
Statut actuel: Actif et salarié | Maître de conférence

Re: Génération de plusieurs images à partir d'un fichier

Messagepar Romain Janvier » Lundi 04 Octobre 2010, 22:12

Oui mais le probleme c'est de recuperer la taille de la boite. D'après ce que j'ai compris il faut passer par un "add(new void..." qui fait quelque chose d'assez étrange.

En fait c'est quoi l'ordre de compilation de asymptote ? À mon avis, il compile d'abord l'image puis les textes latex. D'où l'interet de rebalancer ces images dans une autre image, pour relancer une compilation et pouvoir utiliser les dimensions des "objets latex". C'est ca ?
Romain Janvier
Kilo-utilisateur
 
Messages: 146
Inscription: Lundi 23 Août 2010, 13:57
Statut actuel: Actif et salarié | Enseignant


Retourner vers Asymptote

 


  • Articles en relation
    Réponses
    Vus
    Dernier message

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 2 invités