import tkinter from math import * from functools import partial ver="1.1.0" #Déclaration des variables #Tailles du menu (minimal pour la hauteur) WMENU = 200 HMENU = 450 #Couleur des champs de saisie en erreur WRONG="tomato" #Les différentes polices d'écritures utilisées dans le programme t3font = ('Times Roman', 18,'bold') t2font = ('Times Roman', 14,'bold') t1font = ('Times Roman', 12,'underline') pbfont = ('Times Roman',11,'bold') pfont = ('Times Roman',10) bfont = ('Times Roman',10) mfont = ('Times Roman',10,'bold') b2font = ('Times Roman',12,'bold') curves=[] #Liste de stockage des courbes LENCURVES=10 #Nombre de variables d'une courbe ACTIVE=0 #Clé d'accès à une variable TYPE=1 EQ=2 XEQ=3 YEQ=4 PARMIN=5 PARMAX=6 PARSTEP=7 CCOLOR=8 SIZE=9 #TYPES PARAM=0 POLAR=1 YFX=2 XFY=3 ntypes=["Arc parametré","Courbe polaire","y=f(x)","x=f(y)"] types={ntypes[PARAM]:PARAM,ntypes[POLAR]:POLAR,ntypes[YFX]:YFX,ntypes[XFY]:XFY} #Idem pour le stockage des variables pour le graphique graph=[] LENGRAPH=14 XMIN=0 XMAX=1 YMIN=2 YMAX=3 AXIS1=4 AXIS2=5 AXIS3=6 AXIST1=7 AXIST2=8 AXISA=9 GRID1=10 GRID2=11 GRID3=12 GCOLOR=13 #Idem pour le stockage des variables des options opts=[] LENOPTS=4 TX=0 TY=1 ZOOM=2 RND=3 scr=0 #Courbe sélectionnée dans le menu page=1 #Page du menu zoombe=False def start(): '''Lancement du programme''' global win #Définition de la fenetre en variable globale win=tkinter.Tk() #Création de la fenetre / démarrage de tkinter #Création des variables tkinter (courbes, graph, options) tkvars([],[-5,5,-5,5,1,1,0,1,1,1,1,1,1,"white"],[500,500,0,3]) #tkvars([],[-4.5,4.5,-6,3,0,0,0,0,0,0,0,0,0,"white"],[500,500,0,3]) #Ajout d'une nouvelle courbe suivant certains paramètres #newCurve(1,ntypes[POLAR],"cos(t)/(1-sin(t))","","",0,2*pi,0.1,"red",1) #newCurve(1,ntypes[PARAM],"","t**5-(10/3)*t**3","(-t**4+(11/5)*t**2)*3/2",-1.825,1.825,0.01,"red",2) #newCurve(1,ntypes[POLAR],"sin(2*t)","","",0,"2*pi",0.1,"red",1) #Création des éléments de la fenetre paintwin() def paintwin(): global win,cv #le canvas doit être global pour l'accès d'autres fonctions #Création de la fenetre width=opts[TX].get()+WMENU #Largeur en fonction du canvas + menu #Hauteur en fonction du canvas mais minimum du menu if(opts[TY].get()",enter) #La touche entrée appelle la fonction enter win.bind("",zoom) #Cration du menu avec rafraichissement du canvas menu(1,True,False) #Fin de la création de la fenetre win.mainloop() def menu(pagea,repaint,same,*args): global menuf #Si on demande de rafraichir le canvas, on appelle paint if(repaint): paint() #On essaye de détruire l'ancien menu, menuf try: menuf.destroy() except NameError: #Si menuf n'existe pas, on ne fais rien pass except tkinter.TclError: pass #On crée un nouveau conteneur d'élements, menuf menuf=tkinter.Frame(win) #Si on demande juste de rafraichir le menu, on prend page comme réference if(same): if(page==1): page1(menuf) #Ajouts des élements de la page 1 sur menuf if(page==2): page2(menuf) if(page==3): page3(menuf) else: #Sinon on prend le paramètre pagea pour changer de page if(pagea==1): page1(menuf) if(pagea==2): page2(menuf) if(pagea==3): page3(menuf) #On positionne le menu à droite du canvas #side LEFT signifie le sens d'ajout des élements #fill Y signifie que l'élement doit remplir toute la hauteur disponible menuf.grid(column=1,row=0,sticky=tkinter.N) def menuBar(frame,n): #Barre de navigation du menu men=tkinter.Frame(frame) #Nouveau conteneur ajouté à celui en paramètre #Les différents boutons #partial permet de rajouter des paramètres à une fonction de commande b1=tkinter.Button(men,text="Courbes",font=mfont,command=partial(menu,1,False,False),width=7) b2=tkinter.Button(men,text="Graph",font=mfont,command=partial(menu,2,False,False),width=7) b3=tkinter.Button(men,text="Options",font=mfont,command=partial(menu,3,False,False),width=7) #Modification du bouton de la page actuelle if(n==1): b1.config(state=tkinter.DISABLED,bg="yellow") if(n==2): b2.config(state=tkinter.DISABLED,bg="yellow") if(n==3): b3.config(state=tkinter.DISABLED,bg="yellow") #Position des boutons sur une grille b1.grid(column=0,row=0) b2.grid(column=1,row=0) b3.grid(column=2,row=0) men.pack(fill=tkinter.X) def page1(frame): global page page=1 f=tkinter.Frame(frame) #Nouveau conteneur ajouté à celui en paramètre menuBar(f,1) #On ajoute les boutons sur f f1=tkinter.Frame(f) #Conteneur des boutons de navigation des ourbes #celui de droite appelle la fonction move(-1) #et affiche le nombre de courbes avant b1=tkinter.Button(f1,text=("<= ("+str(scr)+")"),font=bfont,command=partial(move,-1),width=11) if(scr==0): #Si il n'y as pas de courbes avant, il est désctivé b1.config(state=tkinter.DISABLED) b1.grid(column=0,row=0) #on l'ajoute sur une grille del b1 #On libère la mémoire #le bouton de gauche affiche le nombre de courbes apres b2=tkinter.Button(f1,text=("("+str(len(curves)-scr-1)+") =>"),font=bfont,command=partial(move,1),width=11) #S'il ni y en a pas, on change son nom et sa commande if(scr==len(curves)-1 or len(curves)==0): b2.config(text="Nouvelle courbe",command=badd) b2.grid(column=1,row=0) del b2 f1.pack(fill=tkinter.X) #on pack l'ensemble des boutons #Si scr se trouve dans la liste des courbes #Il se peut que non si il n'y a pas de courbes if(len(curves)>scr): #A chaque element de saisie se trouve une variable de la liste du début #la modification s'effectue en instantanée mais pas le rafraichissement #du graph ici géré par entrée #Cela permet aussi de choisir quand on a finis l'edition #pour eviter les erreurs constamment f1=tkinter.LabelFrame(f,text=("Courbe "+str(scr+1)),padx=5,pady=5) f2=tkinter.Frame(f1) tkinter.Label(f2,text="Type :",font=pfont).grid(column=0,row=0) tkinter.OptionMenu(f2,curves[scr][TYPE],*ntypes,command=ctype).grid(column=1,row=0) f2.pack(fill=tkinter.X) if(types[curves[scr][TYPE].get()]==PARAM): f2=tkinter.LabelFrame(f1,text="Equations paramétriques",padx=5,pady=5) tkinter.Label(f2,text="x(t)=",font=pfont).grid(column=0,row=0) e=tkinter.Entry(f2,textvariable=curves[scr][XEQ],width=19) try: ft(curves[scr][XEQ].get(),0.01) except(ZeroDivisionError): pass except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=0) tkinter.Label(f2,text="y(t)=",font=pfont).grid(column=0,row=1) e=tkinter.Entry(f2,textvariable=curves[scr][YEQ],width=19) try: ft(curves[scr][YEQ].get(),0.01) except(ZeroDivisionError): pass except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=1) f2.pack(fill=tkinter.X) else: f2=tkinter.LabelFrame(f1,text="Equation",padx=5,pady=5) if(types[curves[scr][TYPE].get()]==POLAR): tkinter.Label(f2,text="ρ(t)=",font=pfont).grid(column=0,row=0) e=tkinter.Entry(f2,textvariable=curves[scr][EQ],width=19) try: ft(curves[scr][EQ].get(),0.01) except(ZeroDivisionError): pass except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=0) if(types[curves[scr][TYPE].get()]==YFX): tkinter.Label(f2,text="y=f(x)=",font=pfont).grid(column=0,row=0) e=tkinter.Entry(f2,textvariable=curves[scr][EQ],width=19) try: x=0.01 eval(curves[scr][EQ].get()) except(ZeroDivisionError): pass except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=0) if(types[curves[scr][TYPE].get()]==XFY): tkinter.Label(f2,text="x=f(y)=",font=pfont).grid(column=0,row=0) e=tkinter.Entry(f2,textvariable=curves[scr][EQ],width=19) try: y=0.01 eval(curves[scr][EQ].get()) except(ZeroDivisionError): pass except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=0) f2.pack(fill=tkinter.X) if(types[curves[scr][TYPE].get()]==PARAM or types[curves[scr][TYPE].get()]==POLAR): f2=tkinter.LabelFrame(f1,text="Paramètre t",padx=5,pady=5) if(types[curves[scr][TYPE].get()]==POLAR): f2.config(text="Paramètre t (θ)") tkinter.Label(f2,text="Min:",font=pfont).grid(column=0,row=0) e=tkinter.Entry(f2,textvariable=curves[scr][PARMIN],width=6) try: int(eval(curves[scr][PARMIN].get())) except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=0) tkinter.Label(f2,text="Max:",font=pfont).grid(column=2,row=0) e=tkinter.Entry(f2,textvariable=curves[scr][PARMAX],width=6) try: int(eval(curves[scr][PARMAX].get())) except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=3,row=0) tkinter.Label(f2,text="Pas:",font=pfont).grid(column=0,row=1) e=tkinter.Entry(f2,textvariable=curves[scr][PARSTEP],width=6) try: int(1/eval(curves[scr][PARSTEP].get())) except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=1) f2.pack(fill=tkinter.X) f2=tkinter.LabelFrame(f1,text="Autre",padx=5,pady=5) tkinter.Label(f2,text="Couleur: ",font=pfont).grid(column=0,row=0) tkinter.Entry(f2,textvariable=curves[scr][CCOLOR],width=10).grid(column=1,row=0) tkinter.Label(f2,text="Epaisseur:",font=pfont).grid(column=0,row=1) e=tkinter.Entry(f2,textvariable=curves[scr][SIZE],width=10) try: int(curves[scr][SIZE].get()) except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=1) f2.pack(fill=tkinter.X) f2=tkinter.Frame(f1,padx=5,pady=5) tkinter.Button(f2,text="Supprimer",width=12,command=partial(delCurve,scr),font=bfont).grid(column=0,row=0) tkinter.Checkbutton(f2,text="Visible",variable=curves[scr][ACTIVE],command=paint).grid(column=1,row=0) f2.pack(fill=tkinter.X) f2.pack() f1.pack(fill=tkinter.Y) f.pack(fill=tkinter.BOTH,anchor=tkinter.N) def page2(frame): global page page=2 #mêmes principes que précedemment f=tkinter.Frame(frame) menuBar(f,2) f1=tkinter.LabelFrame(f,text="Fenêtre",padx=5,pady=5) f2=tkinter.Frame(f1) f3=tkinter.LabelFrame(f2,text="X",padx=5,pady=5) tkinter.Label(f3,text="min:",font=pfont).grid(column=0,row=0) e=tkinter.Entry(f3,textvariable=graph[XMIN],width=7) try: int(eval(graph[XMIN].get())) except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=0) tkinter.Label(f3,text="max:",font=pfont).grid(column=2,row=0) e=tkinter.Entry(f3,textvariable=graph[XMAX],width=7) try: int(eval(graph[XMAX].get())) except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=3,row=0) f3.grid(column=0,row=0) f3=tkinter.LabelFrame(f2,text="Y",padx=5,pady=5) tkinter.Label(f3,text="min:",font=pfont).grid(column=0,row=0) e=tkinter.Entry(f3,textvariable=graph[YMIN],width=7) try: int(eval(graph[YMIN].get())) except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=1,row=0) tkinter.Label(f3,text="max:",font=pfont).grid(column=2,row=0) e=tkinter.Entry(f3,textvariable=graph[YMAX],width=7) try: int(eval(graph[YMAX].get())) except(NameError): e.config(bg=WRONG) except: e.config(bg=WRONG) e.grid(column=3,row=0) f3.grid(column=0,row=1) f2.pack(fill=tkinter.X) f2=tkinter.Frame(f1) tkinter.Button(f2,text="Orthonormer X",command=orthx).grid(column=0,row=0) tkinter.Button(f2,text="Orthonormer Y",command=orthy).grid(column=1,row=0) f2.pack(fill=tkinter.X) st=tkinter.NORMAL if(not(azoomenable)): st=tkinter.DISABLED tkinter.Button(f1,text="Zoom auto",command=azoom,state=st).pack(fill=tkinter.X) f1.pack(fill=tkinter.BOTH) f1=tkinter.LabelFrame(f,text="Graduation",padx=5,pady=5) f2=tkinter.LabelFrame(f1,text="Axes",padx=5,pady=5) tkinter.Checkbutton(f2,text="1 ",variable=graph[AXIS1],command=paint,width=7).pack() tkinter.Checkbutton(f2,text="0.5",variable=graph[AXIS2],command=paint,width=7).pack() tkinter.Checkbutton(f2,text="0.1",variable=graph[AXIS3],command=paint,width=7).pack() f2.grid(column=0,row=0) f2=tkinter.LabelFrame(f1,text="Grille",padx=5,pady=5) tkinter.Checkbutton(f2,text="1 ",variable=graph[GRID1],command=paint,width=7).pack() tkinter.Checkbutton(f2,text="0.5",variable=graph[GRID2],command=paint,width=7).pack() tkinter.Checkbutton(f2,text="0.1",variable=graph[GRID3],command=paint,width=7).pack() f2.grid(column=1,row=0) f1.pack(fill=tkinter.BOTH) f1=tkinter.LabelFrame(f,text="Autre",padx=5,pady=5) f2=tkinter.Frame(f1) tkinter.Label(f2,text="Fond:",font=pfont).grid(column=0,row=0) tkinter.Entry(f2,textvariable=graph[GCOLOR],width=18).grid(column=1,row=0) f2.pack() tkinter.Checkbutton(f1,text="Titre des axes",variable=graph[AXIST1],command=paint).pack(anchor=tkinter.NW) tkinter.Checkbutton(f1,text="Axes flechés",variable=graph[AXISA],command=paint).pack(anchor=tkinter.NW) tkinter.Checkbutton(f1,text="Unités",variable=graph[AXIST2],command=paint).pack(anchor=tkinter.NW) f1.pack(fill=tkinter.X) f.pack(fill=tkinter.BOTH,anchor=tkinter.N) def page3(frame): global page page=3 #idem f=tkinter.Frame(frame) menuBar(f,3) f1=tkinter.LabelFrame(f,text="Taille du graph",padx=5,pady=5) tkinter.Label(f1,text="X:",font=pfont).grid(column=0,row=0) e=tkinter.Entry(f1,textvariable=opts[TX],width=6) try: int(opts[TX].get()) except: e.config(bg=WRONG) e.grid(column=1,row=0) tkinter.Label(f1,text="Y:",font=pfont).grid(column=2,row=0) e=tkinter.Entry(f1,textvariable=opts[TY],width=6) try: int(opts[TX].get()) except: e.config(bg=WRONG) e.grid(column=3,row=0) tkinter.Button(f1,text="changer",font=bfont,command=restart).grid(column=4,row=0) f1.pack(fill=tkinter.X) f1=tkinter.LabelFrame(f,text="Autre",padx=5,pady=5) tkinter.Checkbutton(f1,text="Zoomer localement",variable=opts[ZOOM]).pack(anchor=tkinter.NW) f2=tkinter.Frame(f1) tkinter.Label(f2,text="Précision déplacements:",font=pfont).grid(column=0,row=0) tkinter.Entry(f2,textvariable=opts[RND],width=5).grid(column=1,row=0) f2.pack() f1.pack(fill=tkinter.X) f1=tkinter.LabelFrame(f,text="Informations",padx=5,pady=5) tkinter.Label(f1,text="Commandes",font=pbfont).pack() tkinter.Label(f1,text="Entrée - Valider les champs\nClic gauche - Déplacer l'origine\nClic droit - Dézoomer\nClic droit (glisser) - Zoomer\nMolette - Zoomer/Dézoomer",font=pfont).pack() tkinter.Label(f1,text="Divers",font=pbfont).pack() tkinter.Label(f1,text="\"pi\" est valide dans l'écriture\ndes fonctions et valeurs.",font=pfont).pack() tkinter.Label(f1,text="A propos",font=pbfont).pack() tkinter.Label(f1,text="Graph version "+ver+"\nDéveloppé par : Clément Gouin\nclement.gouin@reseau.eseo.fr",font=pfont).pack() f1.pack(fill=tkinter.X) f.pack(fill=tkinter.BOTH,anchor=tkinter.N) def paint(): global cv,autozoom,azoomenable try: cv.destroy() except NameError: pass except tkinter.TclError: pass cv=tkinter.Canvas(win,width=opts[TX].get(),height=opts[TY].get()) cv.grid(column=0,row=0,sticky=tkinter.N) cv.bind("",bu1) cv.bind("",bu3) cv.bind("",bu3m) cv.bind("",bu3r) #Une des fonctions principales du programme #elle permet le rafraichissement du canvas #on crée tout d'abord le fond par un rectangle, #on efface rien, on colle juste le fond par dessus le précédent cv.create_rectangle(2,2,opts[TX].get(),opts[TY].get()-3,fill=graph[GCOLOR].get()) #suivant les paramètres, on affiche les grilles et axes ou non if(graph[GRID3].get()): gridf(0.1,"grey90") if(graph[GRID2].get()): gridf(0.5,"grey80") if(graph[GRID1].get()): gridf(1,"grey70") #Ici on met en paramètre qui est l'axe maitre, #car c'est lui qui affiche les noms des axes, les unités et les fleches if(graph[AXIS1].get()): axisf(1,"grey40",4,True) #L'axe 1 est toujours maitre s'il est actif if(graph[AXIS2].get()): axisf(0.5,"grey40",2,(not(graph[AXIS1].get()))) #Sinon c'est le 0.5 etc. if(graph[AXIS3].get()): axisf(0.1,"grey40",1,(not(graph[AXIS1].get()) and not(graph[AXIS2].get()))) #enfin on affiche les courbes successivement et si elles sont affichées autozoom=[0,0,0,0] azoomenable=False if(len(curves)>0): for k in range(len(curves)): if(curves[k][ACTIVE].get()): curvef(k,curves[k][CCOLOR].get(),curves[k][SIZE].get()) if(zoombe): cv.create_rectangle(zoomb[0][0],zoomb[0][1],zoomb[1][0],zoomb[1][1],outline="red") def gridf(pas,col): #On récupère les différentes variables try: tx,ty,xmax,xmin,ymax,ymin=opts[TX].get(),opts[TY].get(),eval(graph[XMAX].get()),eval(graph[XMIN].get()),eval(graph[YMAX].get()),eval(graph[YMIN].get()) except: pass else: factx=tx/(abs(xmax-xmin)) facty=ty/(abs(ymax-ymin)) n = int((2+abs(ymax-ymin))/pas) d=abs(ymin)-abs(int(ymin)) for k in range(n+1): cv.create_line(0,ty-(k*pas+d-1)*facty,tx,ty-(k*pas+d-1)*facty,fill=col) n = int((2+abs(xmax-xmin))/pas) d=abs(xmin)-abs(int(xmin)) for k in range(n+1): cv.create_line((k*pas+d-1)*factx,0,(k*pas+d-1)*factx,ty,fill=col) def axisf(pas,col,t1,high): try: tx,ty,xmax,xmin,ymax,ymin=opts[TX].get(),opts[TY].get(),eval(graph[XMAX].get()),eval(graph[XMIN].get()),eval(graph[YMAX].get()),eval(graph[YMIN].get()) except: pass else: factx=tx/(abs(xmax-xmin)) facty=ty/(abs(ymax-ymin)) if(min(xmin,xmax)<0 and max(xmin,xmax)>0): n = int((2+abs(ymax-ymin))/pas) d=abs(min(ymin,ymax))-abs(int(min(ymin,ymax))) if(high and graph[AXISA].get()): if(ymax>ymin): cv.create_line(-sgn(xmin,xmax)*xmin*factx,0,-sgn(xmin,xmax)*xmin*factx,ty,fill=col,arrow=tkinter.FIRST) else: cv.create_line(-sgn(xmin,xmax)*xmin*factx,0,-sgn(xmin,xmax)*xmin*factx,ty,fill=col,arrow=tkinter.LAST) else: cv.create_line(-sgn(xmin,xmax)*xmin*factx,0,-sgn(xmin,xmax)*xmin*factx,tx,fill=col) for k in range(n+1): cv.create_line(-sgn(xmin,xmax)*xmin*factx-t1,ty-(k*pas+d-1)*facty,-sgn(xmin,xmax)*xmin*factx+t1+1,ty-(k*pas+d-1)*facty,fill=col) if(high and graph[AXIST2].get() and min(ymin,ymax)pas): cv.create_text(-10-sgn(xmin,xmax)*xmin*factx,ty-(pas-ymin)*facty,text=str(pas),font=pfont,fill=col) if(high and graph[AXIST1].get()): if(ymax>ymin): cv.create_text(-10-xmin*factx,15,text="y",font=pfont,fill=col) else: cv.create_text(-10-xmin*factx,ty-35,text="y",font=pfont,fill=col) if(min(ymin,ymax)<0 and max(ymin,ymax)>0): n = int((2+abs(xmax-xmin))/pas) d=abs(min(xmin,xmax))-abs(int(min(xmin,xmax))) if(high and graph[AXISA].get()): if(xmax>xmin): cv.create_line(0,ty+sgn(ymin,ymax)*ymin*facty,tx,ty+sgn(ymin,ymax)*ymin*facty,fill=col,arrow=tkinter.LAST) else: cv.create_line(0,ty+sgn(ymin,ymax)*ymin*facty,tx,ty+sgn(ymin,ymax)*ymin*facty,fill=col,arrow=tkinter.FIRST) else: cv.create_line(0,ty+sgn(ymin,ymax)*ymin*facty,tx,ty+sgn(ymin,ymax)*ymin*facty,fill=col) for k in range(n+1): cv.create_line((k*pas+d-1)*factx,ty+sgn(ymin,ymax)*ymin*facty-t1,(k*pas+d-1)*factx,ty+sgn(ymin,ymax)*ymin*facty+t1+1,fill=col) if(high and graph[AXIST2].get() and min(xmin,xmax)pas): cv.create_text((pas-xmin)*factx,ty+sgn(ymin,ymax)*ymin*facty+15,text=str(pas),font=pfont,fill=col) if(high and graph[AXIST1].get()): if(xmax>xmin): cv.create_text(tx-10,ty+ymin*facty+15,text="x",font=pfont,fill=col) else: cv.create_text(10,ty+ymin*facty+15,text="x",font=pfont,fill=col) def curvef(k,col,ta): global curves,azoomenable,autozoom try: tx,ty,xmax,xmin,ymax,ymin,parmin,parmax,parstep=opts[TX].get(),opts[TY].get(),eval(graph[XMAX].get()),eval(graph[XMIN].get()),eval(graph[YMAX].get()),eval(graph[YMIN].get()),eval(curves[k][PARMIN].get()),eval(curves[k][PARMAX].get()),eval(curves[k][PARSTEP].get()) 1/parstep except: pass else: factx=tx/(xmax-xmin) facty=ty/(ymax-ymin) if(types[curves[k][TYPE].get()]==PARAM): azoomenable=True if(types[curves[k][TYPE].get()]==POLAR): azoomenable=True curves[k][XEQ].set("("+curves[k][EQ].get()+")*cos(t)") curves[k][YEQ].set("("+curves[k][EQ].get()+")*sin(t)") if(types[curves[k][TYPE].get()]==YFX): curves[k][XEQ].set("t") curves[k][YEQ].set(curves[k][EQ].get().replace('x','t')) curves[k][PARMIN].set(xmin) curves[k][PARMAX].set(xmax) curves[k][PARSTEP].set(abs(xmax-xmin)/(tx)) if(types[curves[k][TYPE].get()]==XFY): curves[k][YEQ].set("t") curves[k][XEQ].set(curves[k][EQ].get().replace("y","t")) curves[k][PARMIN].set(ymin) curves[k][PARMAX].set(ymax) curves[k][PARSTEP].set(abs(ymax-ymin)/(ty)) n = int((parmax-parmin)/parstep)+2 li=[]; for k1 in range(n): t=parmin+k1*parstep try: li+=[[ft(curves[k][XEQ].get(),t),ft(curves[k][YEQ].get(),t),True]] if(azoomenable): if(li[k1][0]>autozoom[XMAX]): autozoom[XMAX]=li[k1][0] if(li[k1][0]autozoom[YMAX]): autozoom[YMAX]=li[k1][1] if(li[k1][1]0): savcurves = [] for k in range(len(curves)): temp=[] for l in range(len(curves[k])): temp+=[curves[k][l].get()] savcurves+=[temp[:]] savgraph=[] for k in range(len(graph)): savgraph+=[graph[k].get()] savopts=[] for k in range(len(opts)): savopts+=[opts[k].get()] win.destroy() win=tkinter.Tk() tkvars(savcurves,savgraph,savopts) paintwin() def tkvars(cu,ax,op): global curves,graph,opts #Définitions des variables et de leur type curves=[] if(len(cu)>0): for k in range(len(cu)): newCurve(cu[k][ACTIVE],cu[k][TYPE],cu[k][EQ],cu[k][XEQ],cu[k][YEQ],cu[k][PARMIN],cu[k][PARMAX],cu[k][PARSTEP],cu[k][CCOLOR],cu[k][SIZE]) graph=LENGRAPH*[None] graph[XMAX]=tkinter.StringVar() graph[XMIN]=tkinter.StringVar() graph[YMIN]=tkinter.StringVar() graph[YMAX]=tkinter.StringVar() graph[AXIS1]=tkinter.IntVar() graph[AXIS2]=tkinter.IntVar() graph[AXIS3]=tkinter.IntVar() graph[AXIST1]=tkinter.IntVar() graph[AXIST2]=tkinter.IntVar() graph[AXISA]=tkinter.IntVar() graph[GRID1]=tkinter.IntVar() graph[GRID2]=tkinter.IntVar() graph[GRID3]=tkinter.IntVar() graph[GCOLOR]=tkinter.StringVar() for k in range(len(graph)): graph[k].set(ax[k]) opts=LENOPTS*[None] opts[TX]=tkinter.IntVar() opts[TY]=tkinter.IntVar() opts[ZOOM]=tkinter.IntVar() opts[RND]=tkinter.IntVar() for k in range(len(opts)): opts[k].set(op[k]) def newCurve(active,typef,eq,xeq,yeq,tmin,tmax,tstep,color,size): global curves,scr #Ajout d'une courbe curves+=[LENCURVES*[None]] n=len(curves)-1 curves[n][ACTIVE]=tkinter.IntVar() curves[n][TYPE]=tkinter.StringVar() curves[n][EQ]=tkinter.StringVar() curves[n][XEQ]=tkinter.StringVar() curves[n][YEQ]=tkinter.StringVar() curves[n][PARMIN]=tkinter.StringVar() curves[n][PARMAX]=tkinter.StringVar() curves[n][PARSTEP]=tkinter.StringVar() curves[n][CCOLOR]=tkinter.StringVar() curves[n][SIZE]=tkinter.IntVar() curves[n][ACTIVE].set(active) curves[n][TYPE].set(typef) curves[n][EQ].set(eq) curves[n][XEQ].set(xeq) curves[n][YEQ].set(yeq) curves[n][PARMIN].set(tmin) curves[n][PARMAX].set(tmax) curves[n][PARSTEP].set(tstep) curves[n][CCOLOR].set(color) curves[n][SIZE].set(size) def delCurve(n): global curves,scr #Destruction d'une courbe del curves[n] scr-=1 menu(1,True,False) def enter(event): #Evenement correspondand à l'appui de la touche entrée menu(1,True,True) def bu1(event): global graph #Evenement du clic de la souris #le graph ce centre sur ce clic tx,ty,xmax,xmin,ymax,ymin=opts[TX].get(),opts[TY].get(),eval(graph[XMAX].get()),eval(graph[XMIN].get()),eval(graph[YMAX].get()),eval(graph[YMIN].get()) factx=tx/(xmax-xmin) facty=ty/(ymax-ymin) dx=(event.x-tx/2)/factx dy=(event.y-ty/2)/facty graph[XMAX].set(rnd(xmax+dx,opts[RND].get())) graph[XMIN].set(rnd(xmin+dx,opts[RND].get())) graph[YMAX].set(rnd(ymax-dy,opts[RND].get())) graph[YMIN].set(rnd(ymin-dy,opts[RND].get())) menu(2,True,True) def bu3(event): global zoomb,zoombe,win zoombe=True zoomb=[[event.x,event.y],[event.x,event.y]] win.after(20,paint) def bu3m(event): global zoomb,win zoomb[1]=[event.x,event.y] win.after(20,paint) def bu3r(event): global zoomb,zoombe,graph tx,ty,xmax,xmin,ymax,ymin=opts[TX].get(),opts[TY].get(),eval(graph[XMAX].get()),eval(graph[XMIN].get()),eval(graph[YMAX].get()),eval(graph[YMIN].get()) zoombe=False if(abs(zoomb[0][0]-zoomb[1][0])<5 and abs(zoomb[0][1]-zoomb[1][1])<5): factx=opts[TX].get()/(abs(xmax-xmin)) facty=opts[TY].get()/(abs(ymax-ymin)) factx/=2 facty/=2 dx=(opts[TX].get()-(xmax-xmin)*factx)/factx dy=(opts[TY].get()-(ymax-ymin)*factx)/factx graph[XMAX].set(rnd(xmax+dx/2,opts[RND].get())) graph[XMIN].set(rnd(xmin-dx/2,opts[RND].get())) graph[YMAX].set(rnd(ymax+dy/2,opts[RND].get())) graph[YMIN].set(rnd(ymin-dy/2,opts[RND].get())) else: factx=opts[TX].get()/(abs(xmax-xmin)) facty=opts[TY].get()/(abs(ymax-ymin)) graph[XMIN].set(rnd(xmin+zoomb[0][0]/factx,opts[RND].get())) graph[XMAX].set(rnd(xmin+zoomb[1][0]/factx,opts[RND].get())) graph[YMIN].set(rnd(ymax-zoomb[0][1]/facty,opts[RND].get())) graph[YMAX].set(rnd(ymax-zoomb[1][1]/facty,opts[RND].get())) menu(1,True,True) def zoom(event): global graph #Evenement de la molette de la souris tx,ty,xmax,xmin,ymax,ymin=opts[TX].get(),opts[TY].get(),eval(graph[XMAX].get()),eval(graph[XMIN].get()),eval(graph[YMAX].get()),eval(graph[YMIN].get()) zoom = event.delta/120 factx=opts[TX].get()/(abs(xmax-xmin)) facty=opts[TY].get()/(abs(ymax-ymin)) factx+=zoom*2 facty+=zoom*2 dx=(opts[TX].get()-(xmax-xmin)*factx)/factx dy=(opts[TY].get()-(ymax-ymin)*factx)/factx graph[XMAX].set(rnd(xmax+dx/2,opts[RND].get())) graph[XMIN].set(rnd(xmin-dx/2,opts[RND].get())) graph[YMAX].set(rnd(ymax+dy/2,opts[RND].get())) graph[YMIN].set(rnd(ymin-dy/2,opts[RND].get())) if(zoom>0 and opts[ZOOM].get()): dx=(event.x-opts[TX].get()/2)/factx dy=(event.y-opts[TY].get()/2)/facty graph[XMAX].set(rnd(graph[XMAX]+dx,opts[RND].get())) graph[XMIN].set(rnd(graph[XMIN]+dx,opts[RND].get())) graph[YMAX].set(rnd(graph[YMAX]-dy,opts[RND].get())) graph[YMIN].set(rnd(graph[YMIN]-dy,opts[RND].get())) menu(2,True,True) def azoom(): global graph graph[XMAX].set(autozoom[XMAX]*1.1) graph[XMIN].set(autozoom[XMIN]*1.1) graph[YMAX].set(autozoom[YMAX]*1.1) graph[YMIN].set(autozoom[YMIN]*1.1) menu(2,True,True) def badd(): global scr #ajout d'une courbe vide avec le bouton "Nouvelle Courbe" newCurve(0,ntypes[PARAM],"","","",0,0,0.1,"black",1) if(len(curves)>1): scr+=1 menu(1,True,False) def ctype(*args): #TODO if(types[curves[scr][TYPE].get()]==POLAR and curves[scr][EQ].get()!=""): curves[scr][EQ].set(curves[scr][EQ].get().replace("y","t")) curves[scr][EQ].set(curves[scr][EQ].get().replace("x","t")) if(types[curves[scr][TYPE].get()]==XFY and curves[scr][EQ].get()!=""): curves[scr][EQ].set(curves[scr][EQ].get().replace("t","y")) curves[scr][EQ].set(curves[scr][EQ].get().replace("x","y")) if(types[curves[scr][TYPE].get()]==YFX and curves[scr][EQ].get()!=""): curves[scr][EQ].set(curves[scr][EQ].get().replace("t","x")) curves[scr][EQ].set(curves[scr][EQ].get().replace("y","x")) menu(1,False,False) def move(n): global scr #Changement de courbe dans le menu if(n>0 and scr0): scr-=1 menu(1,False,False) def orthx(): global graph #Orthonormalisation de l'axe x en fonction de l'axe y tx,ty,xmax,xmin,ymax,ymin=opts[TX].get(),opts[TY].get(),eval(graph[XMAX].get()),eval(graph[XMIN].get()),eval(graph[YMAX].get()),eval(graph[YMIN].get()) if(xmax