English translation and some fixes
This commit is contained in:
parent
2be4ad8d46
commit
01a9663a88
10
License.txt
10
License.txt
@ -1,10 +0,0 @@
|
|||||||
* Funzioni
|
|
||||||
*
|
|
||||||
* Applicazione per stampare funzioni in python 3.
|
|
||||||
*
|
|
||||||
* Dual licensed under the MIT and GPL licenses:
|
|
||||||
* http://www.opensource.org/licenses/mit-license.php
|
|
||||||
* http://www.gnu.org/licenses/gpl.html
|
|
||||||
*
|
|
||||||
* @author Michele Guerini Rocco aka Rnhmjoj
|
|
||||||
* @since 2013
|
|
108
README.md
108
README.md
@ -1,60 +1,60 @@
|
|||||||
Funzioni
|
# Plotter
|
||||||
========
|
|
||||||
|
|
||||||
Applicazione per stampare funzioni in python 3.
|
## Application to plot functions in python 3.
|
||||||
-----------------------------------------------
|
|
||||||
|
|
||||||
### Informazioni
|
### Info
|
||||||
Un' applicazione per stampare nel piano cartesiano una funzione(per punti, definita a tratti o normale) tramite turtle graphics.
|
An application to plot a function (points, piecewise or normal) using turtle graphics.
|
||||||
L'applicazione è strutturata in due moduli: "grafico.py" contiene le classi e le funzioni per il disegno vero e proprio mentre "funzioni.py" è l'interfaccia grafica(tkinter) al modulo che facilita e ne velocizza l'uso.
|
The application is structured in two modules: "graph.py" contains classes and functions for drawing while "plotter.py" is the GUI (tkinter) module that facilitates and speeds up the use.
|
||||||
Grafico.py è indipendente e può essere usato anche senza l'interfaccia grafica.
|
graph.py is independent and can be used even without the graphical interface.
|
||||||
È possibile salvare il piano cartesiano in formato svg tramite [canvas2svg](Link: http://wm.ite.pl/proj/canvas2svg/index.html).
|
You can save the plot in svg format via [canvas2svg] (Link: http://wm.ite.pl/proj/canvas2svg/index.html).
|
||||||
|
|
||||||
### Istruzioni
|
### Instructions
|
||||||
grafico.py:
|
graph.py:
|
||||||
|
|
||||||
* importare il modulo grafico.py.
|
* Import the module graph.py.
|
||||||
Es. import grafico
|
`import graph`
|
||||||
* Per creare un piano cartesiano istanziare un oggetto "grafico" fornendo le lunghezze degli assi.
|
* Create a Cartesian plane instantiate an object "graph" by providing the lengths of the axes.
|
||||||
Es. piano = grafico.grafico(20,20)
|
`plane = graph.graph(20,20)`
|
||||||
* Per disegnare una funzione usare il metodo disegna fornendo una funzione, l'intervallo nel dominio e il colore.
|
* Draw a function using the method draws providing a function, the interval in the domain, and color.
|
||||||
Es. piano.disegna(lamda x: x**2-2*x+1, -10, 10, ""#92182b")
|
`plane.plot (lambda x: x**2-2*x+1, -10, 10, "#92182b")`
|
||||||
* Per cancellare usare il metodo pulisci.
|
* Clean the graph.
|
||||||
Es. piano.pulisci()
|
`plane.clean()`
|
||||||
|
|
||||||
Grafico() è sottoclasse di turtle.Pen quindi è possibile usare tutti i metodi ereditati.
|
|
||||||
|
|
||||||
funzioni.py:
|
|
||||||
|
|
||||||
Normale:
|
`Graph()` is subclass of turtle.Pen so you can use all the methods inherited.
|
||||||
|
|
||||||
* Inserire la funzione nella prima casella di testo. Tra la variabile e i coefficienti il * non è necessario.
|
|
||||||
Per elevare a potenza usare ^, per il valore assoluto usare |f(x)|.
|
|
||||||
Es. |cos(x)*1/2x|
|
|
||||||
* Inserire l'intervallo della funzione da stampare nella seconda casella.
|
|
||||||
Es. -10,10
|
|
||||||
* Inserire il colore nella terza casella.
|
|
||||||
Una stringa con il nome del colore, una tupla che contiene i numeri RGB del colore o #colore in RGB esadecimale):
|
|
||||||
Es #a1a1a1
|
|
||||||
|
|
||||||
Definita a punti:
|
plotter.py:
|
||||||
|
|
||||||
* Inserire i punti della funzione in una tupla del tipo (x1,y2),(x2,y2).
|
Normal:
|
||||||
Es. (0,0),(1,2),(2,4),(3,-3)
|
|
||||||
* Inserire l'intervallo della funzione da stampare nella seconda casella.
|
* Enter the function in the first text box. Between the variable and the coefficients a * is not necessary.
|
||||||
Es. -10,10
|
Use `^` for exponentiation and `|` for the absolute value |f(x)|.
|
||||||
* Inserire il colore nella terza casella.
|
eg |cos(x)*1/2x|
|
||||||
Una stringa con il nome del colore, una tupla che contiene i numeri RGB del colore o #colore in RGB esadecimale):
|
* Enter the range of the function to print in the second box.
|
||||||
Es #a1a1a1
|
eg -10, 10
|
||||||
|
* Enter the color in the third box. A string with the name of the color, a tuple that contains RGB numbers, #RGB color in hex.
|
||||||
Definita a tratti:
|
eg #a1a1a1
|
||||||
|
|
||||||
* Inserire i tratti in una tupla del tipo [f1(x),(intervallo)],[f2(x),(intervallo)].
|
Defined by points:
|
||||||
Es. [(-x),(-100,0)],[(x),(0,100)]
|
|
||||||
* Inserire l'intervallo della funzione da stampare nella seconda casella.
|
* Insert the points of the function into a tuple of the form (x1, y2), (x2, y2).
|
||||||
Es. -10,10
|
eg (0,0), (1,2), (2,4), (3,-3)
|
||||||
* Inserire il colore nella terza casella.
|
* Enter the range of the function to print the second box.
|
||||||
Una stringa con il nome del colore, una tupla che contiene i numeri RGB del colore o #colore in RGB esadecimale):
|
eg -10,10
|
||||||
Es #a1a1a1
|
* Enter the color in the third box. A string with the name of the color, a tuple that contains RGB numbers, #RGB color in hex.
|
||||||
|
eg #a1a1a1
|
||||||
È possibile usare tutte le funzioni e le costanti del modulo math.
|
|
||||||
|
Piecewise:
|
||||||
|
|
||||||
|
* Enter the traits in a tuple type [f1(x), (range)], [f2(x), (range)].
|
||||||
|
eg [ (-x), (-100,0)], [(x), (0,100)]
|
||||||
|
* Enter the range of the function to print the second box.
|
||||||
|
eg -10.10
|
||||||
|
* Enter the color in the third box. A string with the name of the color, a tuple that contains RGB numbers or #RGB color in hex.
|
||||||
|
eg #a1a1a1
|
||||||
|
|
||||||
|
You can use all the functions and constants defined in `math` module.
|
||||||
|
|
||||||
|
### License
|
||||||
|
Dual licensed under the MIT and GPL licenses:
|
||||||
|
http://www.opensource.org/licenses/mit-license.php
|
||||||
|
http://www.gnu.org/licenses/gpl.html
|
||||||
|
282
funzioni.py
282
funzioni.py
@ -1,282 +0,0 @@
|
|||||||
import tkinter, tkinter.filedialog
|
|
||||||
from math import *
|
|
||||||
import re
|
|
||||||
#import canvas2svg
|
|
||||||
import grafico
|
|
||||||
|
|
||||||
|
|
||||||
class Applicazione(tkinter.Frame):
|
|
||||||
"""
|
|
||||||
Classe dell'applicazione
|
|
||||||
Inizializzarla con un finestra creata con Tk().
|
|
||||||
"""
|
|
||||||
def __init__(self, finestra):
|
|
||||||
tkinter.Frame.__init__(self, finestra)
|
|
||||||
|
|
||||||
#Impostazioni della finestra
|
|
||||||
|
|
||||||
finestra.title("Impostazioni")
|
|
||||||
finestra.resizable(0, 0)
|
|
||||||
finestra.geometry("{}x{}+{}+{}".format(
|
|
||||||
645, 110,
|
|
||||||
int((finestra.winfo_screenwidth() / 2) - 320),
|
|
||||||
finestra.winfo_screenheight()
|
|
||||||
))
|
|
||||||
|
|
||||||
#Variabili
|
|
||||||
|
|
||||||
self.tipo = tkinter.StringVar()
|
|
||||||
self.testo = tkinter.StringVar()
|
|
||||||
self.tipo.set("normale")
|
|
||||||
self.grafico = grafico.Grafico(20, 20)
|
|
||||||
self.frame = self.grafico.frame
|
|
||||||
self.widgets()
|
|
||||||
self.scritta()
|
|
||||||
|
|
||||||
def widgets(self):
|
|
||||||
"""
|
|
||||||
Creare e disegna i widget della finestra.
|
|
||||||
"""
|
|
||||||
|
|
||||||
#Etichette
|
|
||||||
|
|
||||||
self.label1 = tkinter.Label(
|
|
||||||
finestra,
|
|
||||||
textvariable=self.testo
|
|
||||||
)
|
|
||||||
self.label2 = tkinter.Label(
|
|
||||||
finestra,
|
|
||||||
text="Intervallo:"
|
|
||||||
)
|
|
||||||
self.label3 = tkinter.Label(
|
|
||||||
finestra,
|
|
||||||
text="Colore:"
|
|
||||||
)
|
|
||||||
|
|
||||||
#Caselle di testo
|
|
||||||
|
|
||||||
self.casella1 = tkinter.Entry(finestra)
|
|
||||||
self.casella2 = tkinter.Entry(finestra)
|
|
||||||
self.casella3 = tkinter.Entry(finestra)
|
|
||||||
|
|
||||||
#Opzioni
|
|
||||||
|
|
||||||
self.scelta1 = tkinter.Radiobutton(
|
|
||||||
finestra,
|
|
||||||
value="normale",
|
|
||||||
text="Normale",
|
|
||||||
variable=self.tipo,
|
|
||||||
command=self.scritta
|
|
||||||
)
|
|
||||||
self.scelta2 = tkinter.Radiobutton(
|
|
||||||
finestra,
|
|
||||||
value="punti",
|
|
||||||
text="Definita a punti",
|
|
||||||
variable=self.tipo,
|
|
||||||
command=self.scritta
|
|
||||||
)
|
|
||||||
self.scelta3 = tkinter.Radiobutton(
|
|
||||||
finestra,
|
|
||||||
value="tratti",
|
|
||||||
text="Definita a tratti",
|
|
||||||
variable=self.tipo,
|
|
||||||
command=self.scritta
|
|
||||||
)
|
|
||||||
|
|
||||||
#Pulsanti
|
|
||||||
|
|
||||||
self.pulsante1 = tkinter.Button(
|
|
||||||
finestra,
|
|
||||||
text="Disegna",
|
|
||||||
command=self.disegna
|
|
||||||
)
|
|
||||||
self.pulsante2 = tkinter.Button(
|
|
||||||
finestra,
|
|
||||||
text="Cancella",
|
|
||||||
command=self.vuota
|
|
||||||
)
|
|
||||||
self.pulsante3 = tkinter.Button(
|
|
||||||
finestra,
|
|
||||||
text="Pulisci Canvas",
|
|
||||||
command=self.grafico.pulisci
|
|
||||||
)
|
|
||||||
self.pulsante4 = tkinter.Button(
|
|
||||||
finestra,
|
|
||||||
text="Salva",
|
|
||||||
command=self.salva
|
|
||||||
)
|
|
||||||
self.pulsante5 = tkinter.Button(
|
|
||||||
finestra,
|
|
||||||
text="Esci",
|
|
||||||
command=finestra.quit
|
|
||||||
)
|
|
||||||
|
|
||||||
#Layout dei widgets
|
|
||||||
|
|
||||||
self.label1.grid(
|
|
||||||
column=0, row=0,
|
|
||||||
sticky="nw",
|
|
||||||
pady=5, padx=5
|
|
||||||
)
|
|
||||||
self.label2.grid(
|
|
||||||
column=0, row=1,
|
|
||||||
sticky="nw",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
self.label3.grid(
|
|
||||||
column=0, row=2,
|
|
||||||
sticky="nw",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
self.casella1.grid(
|
|
||||||
column=1, row=0,
|
|
||||||
sticky="nw",
|
|
||||||
pady=5, padx=5
|
|
||||||
)
|
|
||||||
self.casella2.grid(
|
|
||||||
column=1, row=1,
|
|
||||||
sticky="nw",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
self.casella3.grid(
|
|
||||||
column=1, row=2,
|
|
||||||
padx=5, pady=2.5
|
|
||||||
)
|
|
||||||
self.scelta1.grid(
|
|
||||||
column=2, row=1,
|
|
||||||
sticky="nw",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
self.scelta2.grid(
|
|
||||||
column=3, row=1,
|
|
||||||
sticky="nw",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
self.scelta3.grid(
|
|
||||||
column=4, row=1,
|
|
||||||
sticky="nw",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
self.pulsante1.grid(
|
|
||||||
column=2, row=0,
|
|
||||||
sticky="nwes",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
self.pulsante2.grid(
|
|
||||||
column=3, row=0,
|
|
||||||
sticky="nwes",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
self.pulsante3.grid(
|
|
||||||
column=4, row=0,
|
|
||||||
sticky="nwes",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
self.pulsante4.grid(
|
|
||||||
column=2, row=2,
|
|
||||||
sticky="nwes",
|
|
||||||
pady=2.5, padx=5,
|
|
||||||
columnspan=2
|
|
||||||
)
|
|
||||||
self.pulsante5.grid(
|
|
||||||
column=4, row=2,
|
|
||||||
sticky="nwes",
|
|
||||||
pady=2.5, padx=5
|
|
||||||
)
|
|
||||||
|
|
||||||
def scritta(self):
|
|
||||||
"""
|
|
||||||
Cambia la scritta in base al tipo di grafico.
|
|
||||||
"""
|
|
||||||
if self.tipo.get() == "normale":
|
|
||||||
self.testo.set("f(x): y =")
|
|
||||||
elif self.tipo.get() == "tratti":
|
|
||||||
self.testo.set("[f1(x),(intervallo)],[f2(x),(intervallo)],...")
|
|
||||||
else:
|
|
||||||
self.testo.set("(x1,y1),(x2,y2),...")
|
|
||||||
|
|
||||||
def disegna(self):
|
|
||||||
"""
|
|
||||||
Disegna il grafico della funzione o dei dati inseriti
|
|
||||||
"""
|
|
||||||
|
|
||||||
#Converte la funzione in modo che possa essere interpretata da eval().
|
|
||||||
funzione = re.sub(
|
|
||||||
"([\+-\-]?\d+)(x)",
|
|
||||||
"\\1*x",
|
|
||||||
self.casella1.get().replace("^", "**")
|
|
||||||
)
|
|
||||||
funzione = re.sub(
|
|
||||||
"(\|)(.+)(\|)",
|
|
||||||
"abs(\\2)",
|
|
||||||
funzione
|
|
||||||
)
|
|
||||||
funzione = re.sub(
|
|
||||||
"(.+)(\!)",
|
|
||||||
"factorial(\\1)",
|
|
||||||
funzione
|
|
||||||
)
|
|
||||||
|
|
||||||
#Legge l'intervallo inserito.
|
|
||||||
try:
|
|
||||||
intervallo = eval(self.casella2.get())
|
|
||||||
except SyntaxError:
|
|
||||||
inizio = -self.grafico.X
|
|
||||||
fine = self.grafico.X
|
|
||||||
else:
|
|
||||||
inizio = float(intervallo[0])
|
|
||||||
fine = float(intervallo[1])
|
|
||||||
|
|
||||||
#Legge il colore inserito.
|
|
||||||
colore = self.casella3.get()
|
|
||||||
if colore == "":
|
|
||||||
colore = "orange"
|
|
||||||
|
|
||||||
#Disegna il grafico in base al tipo inserito.
|
|
||||||
if self.tipo.get() == "normale":
|
|
||||||
funzione = eval("lambda x:" + funzione)
|
|
||||||
self.grafico.disegna(funzione, inizio, fine, colore)
|
|
||||||
elif self.tipo.get() == "tratti":
|
|
||||||
funzioni = re.sub("(\[\()(.+?\))", "\\1lambda x:\\2", funzione)
|
|
||||||
funzioni = re.sub("(\[)", "(", funzioni.replace("]", ")"))
|
|
||||||
for funzione in eval(funzioni):
|
|
||||||
self.grafico.disegna(
|
|
||||||
funzione[0],
|
|
||||||
funzione[1][0],
|
|
||||||
funzione[1][1],
|
|
||||||
colore
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
funzione = grafico.punti(eval(self.casella1.get()))
|
|
||||||
self.grafico.disegna(
|
|
||||||
funzione,
|
|
||||||
punti[0][0],
|
|
||||||
punti[len(punti) - 1][1],
|
|
||||||
colore
|
|
||||||
)
|
|
||||||
|
|
||||||
def vuota(self):
|
|
||||||
"""
|
|
||||||
Rimuove tutti i dati inseriti.
|
|
||||||
"""
|
|
||||||
self.casella1.delete(0, "end")
|
|
||||||
self.casella2.delete(0, "end")
|
|
||||||
self.casella3.delete(0, "end")
|
|
||||||
self.finestra.withdraw()
|
|
||||||
|
|
||||||
def salva(self):
|
|
||||||
"""
|
|
||||||
Salva il grafico in formato svg.
|
|
||||||
"""
|
|
||||||
opzioni = {
|
|
||||||
"parent": self.frame,
|
|
||||||
"defaultextension": ".svg",
|
|
||||||
"initialfile": "grafico.svg",
|
|
||||||
"title": "Salva il grafico"
|
|
||||||
}
|
|
||||||
file = tkinter.filedialog.asksaveasfilename(**opzioni)
|
|
||||||
canvas2svg.saveall(file, self.grafico.canvas)
|
|
||||||
|
|
||||||
finestra = tkinter.Tk()
|
|
||||||
app = Applicazione(finestra)
|
|
||||||
app.mainloop()
|
|
102
grafico.py
102
grafico.py
@ -1,102 +0,0 @@
|
|||||||
import turtle
|
|
||||||
|
|
||||||
|
|
||||||
def punti(tupla):
|
|
||||||
"""
|
|
||||||
Data una tupla del tipo ((x_1, y_1), (x_2, y_2), (x_n, y_n),...)
|
|
||||||
restituisce una funzione f(x_n): y=y_n.
|
|
||||||
"""
|
|
||||||
return lambda x: dict(tupla)[float(x)]
|
|
||||||
|
|
||||||
|
|
||||||
class Varie():
|
|
||||||
"""
|
|
||||||
Funzioni varie per turtle.
|
|
||||||
"""
|
|
||||||
def vai(self, x, y):
|
|
||||||
"""
|
|
||||||
Sposta il cursore al punto (x, y) senza tracciare una linea.
|
|
||||||
"""
|
|
||||||
self.pu()
|
|
||||||
self.goto(x, y)
|
|
||||||
self.pd()
|
|
||||||
|
|
||||||
|
|
||||||
class Freccia(turtle.Pen, Varie):
|
|
||||||
"""
|
|
||||||
Cursore di turtle personalizzato.
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
|
||||||
super(Freccia, self).__init__()
|
|
||||||
self.speed(0)
|
|
||||||
self.shape("triangle")
|
|
||||||
self.shapesize(0.5)
|
|
||||||
|
|
||||||
|
|
||||||
class Grafico(turtle.Pen, Varie):
|
|
||||||
|
|
||||||
def __init__(self, X=10, Y=10):
|
|
||||||
"""
|
|
||||||
Inizializzazione del grafico
|
|
||||||
Fornire le dimensione degli assi se necessario.
|
|
||||||
"""
|
|
||||||
super(Grafico, self).__init__()
|
|
||||||
turtle.title("Grafico")
|
|
||||||
self.X = X
|
|
||||||
self.Y = Y
|
|
||||||
self.canvas = turtle.getcanvas()
|
|
||||||
self.frame = turtle._Screen._root
|
|
||||||
self.assi()
|
|
||||||
self.frecce()
|
|
||||||
|
|
||||||
def assi(self):
|
|
||||||
"""
|
|
||||||
Disegna gli assi del piano cartesiano.
|
|
||||||
"""
|
|
||||||
turtle.setworldcoordinates(
|
|
||||||
-(self.X + 2), -(self.Y + 2),
|
|
||||||
self.X + 2, self.Y + 2
|
|
||||||
)
|
|
||||||
self.hideturtle()
|
|
||||||
self.speed(0)
|
|
||||||
self.vai(-self.X, 0)
|
|
||||||
self.fd(self.X * 2)
|
|
||||||
self.vai(0, -self.Y)
|
|
||||||
self.lt(90)
|
|
||||||
self.fd(self.Y * 2)
|
|
||||||
|
|
||||||
def frecce(self):
|
|
||||||
"""
|
|
||||||
Disegna le frecce e i nomi degli assi.
|
|
||||||
"""
|
|
||||||
a = Freccia()
|
|
||||||
a.vai(self.X, 0)
|
|
||||||
a.write(" x", font=("helvetiva", 16))
|
|
||||||
b = Freccia()
|
|
||||||
b.lt(90)
|
|
||||||
b.vai(0, self.Y)
|
|
||||||
b.write(" y", font=("helvetiva", 16))
|
|
||||||
|
|
||||||
def disegna(self, funzione, inizio, fine, colore="blue"):
|
|
||||||
"""
|
|
||||||
Disegna una funzione nel piano cartesiano.
|
|
||||||
"""
|
|
||||||
medio = 2 / self.X
|
|
||||||
self.color(colore)
|
|
||||||
try:
|
|
||||||
self.vai(inizio, funzione(inizio))
|
|
||||||
except ZeroDivisionError:
|
|
||||||
self.vai(inizio, funzione(inizio + 1 * medio))
|
|
||||||
for x in range(int(inizio / medio), int(fine / medio) + 1):
|
|
||||||
x *= medio
|
|
||||||
try:
|
|
||||||
self.goto(x, funzione(x))
|
|
||||||
except ZeroDivisionError:
|
|
||||||
self.vai(x, funzione(x + 1 * medio))
|
|
||||||
|
|
||||||
def pulisci(self):
|
|
||||||
"""
|
|
||||||
Pulisce il canvas e ridisegna gli assi.
|
|
||||||
"""
|
|
||||||
self.reset()
|
|
||||||
self.assi()
|
|
Loading…
Reference in New Issue
Block a user