You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1047 lines
36 KiB
Python
1047 lines
36 KiB
Python
2 years ago
|
#!/usr/bin/env python3
|
||
|
from tkinter import *
|
||
|
from numpy import *
|
||
|
from struct import *
|
||
|
import getopt
|
||
|
import sys
|
||
|
from tkinter import filedialog as fd
|
||
|
from tkinter import messagebox as ms
|
||
|
#####################################################################
|
||
|
#
|
||
|
# rimbalzi.py 2022.06.08 Sergio Steffe' Pisa
|
||
|
# port in pyton del programma rimbalzi per Mac in Tthink-C del 1993,
|
||
|
# scritto come esercizio di python del corso di
|
||
|
# Algoritmi di Spettrografia del Prof. Giovanni Moruzzi 2021/22.
|
||
|
#
|
||
|
#
|
||
|
####################################################################
|
||
|
# versioni:
|
||
|
# versione 1.0: 2022.06.08 versione iniziale
|
||
|
# versione 1.1: 2022.06.16
|
||
|
# pulizia dal software delle righe usate per il debugging
|
||
|
# aggiunti tasti SaveAll e LoadAll, aggiornato help
|
||
|
# aggiunta scalatura dei dati dei files tra -s e -b e normale
|
||
|
# aggiunte finestre apertura files e segnalazione errori io files
|
||
|
# aggiunta logica per disabilitare/abilitare i bottoni
|
||
|
# il Fast puo' dare lampeggiamenti del disegno sul canvas
|
||
|
# versione 1.2: 2022.06.22
|
||
|
# corretto errore in riga 580 di calcola: era scritto denom=yyas*xxs invece di +
|
||
|
# essendo un fattore di normalizzazione saltavano fuori errori solo nelle rare
|
||
|
# condizioni in cui veniva denom=0 !
|
||
|
# versione 1.3: 2022.07.01
|
||
|
# corretto misprints qui e li, ingranditi i punti di ancora
|
||
|
# versione 1.3c: 2022.07.01
|
||
|
# versione per cellulari: effetto ottico per confermare il grab e punti piu' grossi.
|
||
|
#
|
||
|
###################################################################
|
||
|
# rimbalzi accetta i flag -s (small) -b (big) -S (Slow) -F (Fast) -v (versione) e -h (help)
|
||
|
#
|
||
|
def main(argv):
|
||
|
global big,small,Slow,Fast
|
||
|
try:
|
||
|
opts,args = getopt.getopt(argv,"bhsSFv")
|
||
|
except getopt.GetoptError:
|
||
|
print ('rimbalzi:\n\
|
||
|
unknown option !\n\
|
||
|
-b big\n\
|
||
|
-s small\n\
|
||
|
-S Slow\n\
|
||
|
-F Fast\n\
|
||
|
-v version\n\
|
||
|
-h help\n')
|
||
|
exit(1)
|
||
|
big=False
|
||
|
small=False
|
||
|
Slow=False
|
||
|
Fast=False
|
||
|
for opt,arg in opts:
|
||
|
if opt == '-h':
|
||
|
print ('rimbalzi:\n\
|
||
|
-b big\n\
|
||
|
-s small\n\
|
||
|
-S Slow\n\
|
||
|
-F Fast\n\
|
||
|
-v version\n\
|
||
|
-h help\n')
|
||
|
exit()
|
||
|
elif opt in ('-b'):
|
||
|
big=True
|
||
|
elif opt in ('-s'):
|
||
|
small=True
|
||
|
elif opt in ('-S'):
|
||
|
Slow=True
|
||
|
elif opt in ('-F'):
|
||
|
Fast=True
|
||
|
elif opt in ('-v'):
|
||
|
print('rimbalzi 1.3c 2022.07.01\n')
|
||
|
exit()
|
||
|
#----------------------------------------
|
||
|
if __name__ == "__main__":
|
||
|
main(sys.argv[1:])
|
||
|
#---------------------------------------
|
||
|
#
|
||
|
# senza la parte con le chiamate a getopt occorre definire tra le globali anche
|
||
|
# big=False/True e small=False/True e Slow=False/True
|
||
|
#
|
||
|
# globali
|
||
|
RunAll=True
|
||
|
IsSetup=True # nel setup si possono modificare le posizioni
|
||
|
RunMotion=False # nel runmotion non si possono modificare le posizioni
|
||
|
GetData=False # per inserimento diretto numeri nelle finestre
|
||
|
CenterGrabbed=RadiusGrabbed=PointGrabbed=VectorGrabbed=False # per modificare graficamente le posizioni
|
||
|
IsLoadedall=False # i dati e le traiettorie sono stati caricati da file.
|
||
|
IsLoaded=False # i dati iniziali sono stati caricati da file
|
||
|
# due canvas e una zona comandi e finestre dati
|
||
|
# canvas cerchi
|
||
|
# quadrato di lato cl; il centro e' Ox,Oy; il cerchio fisso ha lato CR=cl/2
|
||
|
# se x,y sono coordinate naturali, vanno disegnate in Ox+x,Oy-y ! e analogamente vanno convertiti gli eventi.
|
||
|
#
|
||
|
cl=800 # per canvas cerchi, quadrata, di lato cl
|
||
|
if big:
|
||
|
cl=1200
|
||
|
if small:
|
||
|
cl=400
|
||
|
CR=cl/2 # raggio cerchio fisso inscritto
|
||
|
Ox=400 # centro del canvasc
|
||
|
Oy=400 # centro del canvasc
|
||
|
if big:
|
||
|
Ox=600
|
||
|
Oy=600
|
||
|
if small:
|
||
|
Ox=200
|
||
|
Oy=200
|
||
|
c1=cl/5 # lunghezza vettore iniziale
|
||
|
cpp=5 # spaziature per le scritte su canvasf
|
||
|
cp=20 # raggio punti degli handle 5 normalmente, 20 sul cellulare
|
||
|
# per canvas fasi : due quadrati 400x400 per rappresentare 0~180 x -90~+90 posizione e angolo rimbalzo.
|
||
|
fw=400
|
||
|
fh=800 #fh=cl
|
||
|
#
|
||
|
if big:
|
||
|
fw=600
|
||
|
fh=1200 #fh=cl
|
||
|
if small:
|
||
|
fw=200
|
||
|
fh=400 #fh=cl
|
||
|
#----------------------
|
||
|
Cr=cl/4 #raggio cerchio interno
|
||
|
Ca=cl/8 #centro cerchio interno
|
||
|
X0=x0=-cl/4 #punto iniziale (copia fissa e copia operativa)
|
||
|
Y0=y0=-cl/4 #punto iniziale (copia fissa e copia operativa)
|
||
|
xx=0 #variabili per il calcolo del rimbalzo
|
||
|
yy=0 #variabili per il calcolo del rimbalzo
|
||
|
angolo=0
|
||
|
angolov=0
|
||
|
#X0,Y0,VX0,VY0 sono quelli del save e load e appaiono nelle caselle.
|
||
|
#x0,y0,vx0,vy0 sono usati nei calcoli e cambiano man mano,
|
||
|
# e sono usati da start e restart.
|
||
|
vx0=30 #velocita iniziale
|
||
|
vy0=30 #velocita iniziale
|
||
|
# normalizzazione velocita
|
||
|
vs=sqrt(vx0*vx0+vy0*vy0)
|
||
|
VX0=vx0=vx0/vs
|
||
|
VY0=vy0=vy0/vs
|
||
|
#
|
||
|
rr=[] #punti di rimbalzo nel canvas cerchi - coppie x,y
|
||
|
ff=[] #punti di rimbalzo nel canvas fasi - coppie angolo, angolov
|
||
|
rextern=0 # numero di rimbalzi su cerchio esterno
|
||
|
rintern=0 # numero di rimbalzi su cerchio interno
|
||
|
#
|
||
|
ttt=0 # tempo effetto grab
|
||
|
# ............................................................ InRange
|
||
|
def InRange(xmin,x,xmax):
|
||
|
if x>=xmax:
|
||
|
return xmax
|
||
|
if x<=xmin:
|
||
|
return xmin
|
||
|
return x
|
||
|
# ................................................. Start/Stop motion
|
||
|
def StartStop():
|
||
|
global RunMotion,IsSetup,IsLoadedall,IsLoaded
|
||
|
RunMotion=not RunMotion
|
||
|
if RunMotion:
|
||
|
StartButton["text"]="Stop"
|
||
|
else:
|
||
|
if IsSetup:
|
||
|
StartButton["text"]="Start"
|
||
|
else:
|
||
|
StartButton["text"]="Restart"
|
||
|
|
||
|
# ...................................................... Exit program
|
||
|
def StopAll():
|
||
|
global RunAll
|
||
|
RunAll=False
|
||
|
#........................................................
|
||
|
def Setup():
|
||
|
global IsSetup,rr,ff,RunMotion,x0,y0,xx,yy,vx0,vy0,rr,ff,rextern,rintern,cl,X0,Y0,VX0,VY0,IsLoadedall,IsLoaded
|
||
|
IsLoaded=False
|
||
|
IsLoadedall=False
|
||
|
if RunMotion==False:
|
||
|
IsSetup=True
|
||
|
xx=0
|
||
|
yy=0
|
||
|
x0=X0 #riinizializzazione valori operativi
|
||
|
y0=Y0
|
||
|
vx0=VX0
|
||
|
vy0=VY0
|
||
|
rr=[]
|
||
|
ff=[]
|
||
|
rextern=0
|
||
|
rintern=0
|
||
|
#
|
||
|
Entryrext.delete(0,END)
|
||
|
Entryrint.delete(0,END)
|
||
|
Entryrtot.delete(0,END)
|
||
|
Entryrrapp.delete(0,END)
|
||
|
#
|
||
|
StartButton["text"]="Start"
|
||
|
#.......................................................
|
||
|
def Help():
|
||
|
newWindow=Toplevel(root)
|
||
|
newWindow.title("Help")
|
||
|
newWindow.geometry("600x600")
|
||
|
Label(newWindow,text="Rimbalzi in una corona circolare asimmetrica. v.1.1\n\
|
||
|
\n\
|
||
|
Nella fase di SETUP, usando il mouse (cursore blu) sui punti neri, si puo' spostare\n\
|
||
|
il centro del cerchio interno e cambiarne il raggio e posizionare\n\
|
||
|
il vettore iniziale su cui iniziera' a muoversi un punto.\n\
|
||
|
In alternativa, invece di fissare punto e vettore iniziale, si puo' scegliere\n\
|
||
|
una 'fase' di partenza (cursore rosso) e in tal caso appena si clicca il\n\
|
||
|
programma effettua uno START partendo dal punto della circonferenza scelto e con\n\
|
||
|
l'angolo scelto con la normale al cerchio.(preview in verde mentre si muove il cursore)\n\
|
||
|
All'apertura il programma e' nel modo di SETUP\n\
|
||
|
\n\
|
||
|
Allo START il punto inizia a rimbalzare elasticamente sulle due circonferenze.\n\
|
||
|
Si puo' fermare con STOP e rilanciare con RESTART, ma se si chiama il SETUP\n\
|
||
|
i dati dei rimbalzi vengono cancellati e riinizializzati.\n\
|
||
|
\n\
|
||
|
SAVE salva i dati di partenza (centro e raggio del cerchio interno Ca e Cr, \n\
|
||
|
e posizione e velocita' iniziale del punto, X0,Y0,VX0,VY0) nel file \n\
|
||
|
rimbalzi-data.txt in formato binario, e LOAD li carica da detto file.\n\
|
||
|
\n\
|
||
|
E' possibile durante il SETUP immettere direttamente questi dati da tastiera,\n\
|
||
|
ma occorre dare un ENTER per farli accettare dal programma\n\
|
||
|
\n\
|
||
|
SAVEALL salva tutto nel file rimbalzi-alldata.txt in formato binario,\n\
|
||
|
e LOADALL li carica da detto file. (tasti non disponibili nel formato small (-s))\n\
|
||
|
\n\
|
||
|
Nella parte di sinistra si vedono i cerchi e le traiettorie del punto\n\
|
||
|
in movimento. Nella parte di destra sia per il cerchio EXTerno che per\n\
|
||
|
quello INTerno sono segnati i punti di contatto sul cerchio (tra 0 e 360 gradi)\n\
|
||
|
e l'angolo di rimbalzo rispetto la normale (tra -90 e +90 gradi).\n\
|
||
|
\n\
|
||
|
Questo programma e' il port in python3 con tkinter dell'analogo programma\n\
|
||
|
scritto per il macintosh nel 1993 in Tkink-C.\n\
|
||
|
\n\
|
||
|
Sergio Steffe' Pisa 16/6/2022 ").pack()
|
||
|
#......................................................Save CR,Cr,Ca,X0,Y0,VX0,VY0
|
||
|
def Save():
|
||
|
global CR,Cr,Ca,X0,Y0,VX0,VY0
|
||
|
try:
|
||
|
hnd=fd.asksaveasfile(mode="wb")
|
||
|
s=pack("7d",CR,Cr,Ca,X0,Y0,VX0,VY0)
|
||
|
hnd.write(s)
|
||
|
except :
|
||
|
ms.showerror(title='errore',message='non ho potuto salvare i dati')
|
||
|
# uuu=sys.exc_info()[0]
|
||
|
# ms.showerror(title='errore',message=uuu)
|
||
|
finally:
|
||
|
hnd.close()
|
||
|
#.......................................................Load CR,Cr,Ca,X0,Y0,VX0,VY0
|
||
|
def Load():
|
||
|
global CR,Cr,Ca,x0,y0,vx0,vy0,CR,X0,Y0,VX0,VY0,IsLoaded,rr,ff,rextern,rintern,RunMotion,IsLoaded,IsSetup,IsLoadedall
|
||
|
filename=fd.askopenfilename()
|
||
|
if len(filename)==0:
|
||
|
return None
|
||
|
try:
|
||
|
hnd=open(filename,"rb")
|
||
|
s=hnd.read(7*8) # 8 bytes ogni numero, 7 numeri
|
||
|
xin=array(unpack('d'*7, s))
|
||
|
# ora vanno controllati i limiti per ciascuna variabile:
|
||
|
# se fuori limiti viene fatta una scelta diversa.
|
||
|
CRR=xin[0] # serve per scalare i dati al CR effettivo (che varia a seconda di Small, Medium o Big)
|
||
|
if CRR==0:
|
||
|
ms.showerror(title='errore',message='CR=0 ! Dati inconsistenti.')
|
||
|
return None
|
||
|
z=CR/CRR # fattore di scala: con CR tra 200 e 600 puo' andare da 3 a 1/3
|
||
|
if (z<0.2)or(z>5):
|
||
|
ms.showerror(title='errore',message='fattore di scala inconsistente.')
|
||
|
return None
|
||
|
Crr=xin[1]*z
|
||
|
Crrr=InRange(0,Crr,CR*0.98) # non vogliamo cerchi quasi uguali
|
||
|
Caa=xin[2]*z
|
||
|
Ca=InRange(Crrr-CR,Caa,CR-Crrr)
|
||
|
Cr=InRange(0,Crr,min(CR-Ca,CR+Ca))
|
||
|
EntryCa.delete(0,END)
|
||
|
EntryCa.insert(0,'{:.5f}'.format(Ca))
|
||
|
EntryCr.delete(0,END)
|
||
|
EntryCr.insert(0,'{:.5f}'.format(Cr))
|
||
|
x0u=(xin[3])*z
|
||
|
y0u=(xin[4])*z
|
||
|
# controllare nan error !
|
||
|
su=sqrt(x0u*x0u+y0u*y0u)
|
||
|
if (su>1200)or(su<300):
|
||
|
ms.showerror(title='errore',message='punto iniziale inconsistente.')
|
||
|
return None
|
||
|
if su>CR:
|
||
|
x0u=x0u*CR/su
|
||
|
y0u=y0u*CR/su
|
||
|
su=sqrt(x0u*x0u+(y0u-Ca)*(y0u-Ca))
|
||
|
if su<Cr:
|
||
|
x0u=x0u*Cr/su
|
||
|
y0u=Ca+(y0u-Ca)*Cr/su
|
||
|
X0=x0=x0u
|
||
|
Y0=y0=y0u
|
||
|
vx0=xin[5]
|
||
|
vy0=xin[6]
|
||
|
su=sqrt(vx0*vx0+vy0*vy0)
|
||
|
if su==0:
|
||
|
VX0=vx0=1/sqrt(2)
|
||
|
VY0=vy0=1/sqrt(2)
|
||
|
su=1
|
||
|
else:
|
||
|
VX0=vx0=vx0/su
|
||
|
VY0=vy0=vy0/su
|
||
|
rr=[]
|
||
|
ff=[]
|
||
|
rextern=rintern=0
|
||
|
IsLoaded=True
|
||
|
IsLoadedall=False
|
||
|
IsSetup=True
|
||
|
RunMotion=False
|
||
|
StartButton["text"]="Start"
|
||
|
except :
|
||
|
ms.showerror(title='errore',message='non ho potuto leggere i dati')
|
||
|
finally :
|
||
|
hnd.close()
|
||
|
#....................................................... SaveAll
|
||
|
def SaveAll():
|
||
|
global CR,Ca,Cr,X0,Y0,VX0,VY0,rr,ff,angolo,angolov,rextern,rintern,x0,y0,vx0,vy0
|
||
|
#filename=fd.askdirectory()
|
||
|
#filename=fd.asksaveasfile()
|
||
|
#hnd=open(filename,"wb")
|
||
|
try:
|
||
|
hnd=fd.asksaveasfile(mode="wb")
|
||
|
s=pack("13d",CR,Cr,Ca,X0,Y0,VX0,VY0,x0,y0,vx0,vy0,angolo,angolov)
|
||
|
hnd.write(s)
|
||
|
nr=len(rr)
|
||
|
nf=len(ff)
|
||
|
s=pack("4i",rextern,rintern,nr,nf)
|
||
|
hnd.write(s)
|
||
|
s=pack(nr*"d",*rr)
|
||
|
hnd.write(s)
|
||
|
s=pack(nf*"d",*ff)
|
||
|
hnd.write(s)
|
||
|
except:
|
||
|
ms.showerror(title='errore',message='non ho potuto salvare i dati')
|
||
|
finally:
|
||
|
hnd.close()
|
||
|
#....................................................... LoadAll
|
||
|
def LoadAll():
|
||
|
global CR,Ca,Cr,X0,Y0,VX0,VY0,rr,ff,angolo,angolov,rextern,rintern,x0,y0,vx0,vy0,RunMotion,IsSetup,IsLoadedall,RunMotion
|
||
|
filename=fd.askopenfilename()
|
||
|
if len(filename)==0:
|
||
|
return None
|
||
|
try:
|
||
|
hnd=open(filename,"rb")
|
||
|
s=hnd.read(13*8) # 8 bytes ogni numero double real, 13 numeri
|
||
|
xin=array(unpack('d'*13, s))
|
||
|
CRR=xin[0]
|
||
|
if CRR==0:
|
||
|
ms.showerror(title='errore',message='CR=0 ! Dati inconsistenti')
|
||
|
return
|
||
|
z=CR/CRR # fattore di scala. Supponiamo inoltre che fh=cl cosi vale sia per rr che per ff
|
||
|
# qui andrebbe controllata la coerenza dei dati
|
||
|
Cr=xin[1]*z
|
||
|
Ca=xin[2]*z
|
||
|
X0=xin[3]*z
|
||
|
Y0=xin[4]*z
|
||
|
VX0=xin[5]
|
||
|
VY0=xin[6]
|
||
|
x0 = xin[7]*z
|
||
|
y0 = xin[8]*z
|
||
|
vx0 = xin[9]
|
||
|
vy0 = xin[10]
|
||
|
angolo = xin[11]
|
||
|
angolov = xin[12]
|
||
|
s=hnd.read(4*4)
|
||
|
xin=array(unpack('i'*4, s))
|
||
|
rextern = int(xin[0])
|
||
|
rintern = int(xin[1])
|
||
|
nr= int(xin[2])
|
||
|
nf= int(xin[3])
|
||
|
s=hnd.read(nr*8)
|
||
|
rr=list(unpack('d'*nr,s))
|
||
|
s=hnd.read(nf*8)
|
||
|
ff=list(unpack('d'*nf,s))
|
||
|
#problema: porebbe capitare angolo=angolov=rextern=rintern=nr=nf=0 se non e' stato fatto un run dopo il setup
|
||
|
#
|
||
|
if nr>=2:
|
||
|
IsLoadedall=True
|
||
|
IsSetup=False
|
||
|
StartButton["text"]="Restart"
|
||
|
#vanno riscalati rr e ff !
|
||
|
for i in range(len(ff)):
|
||
|
ff[i]=ff[i]*z
|
||
|
for i in range(len(rr)):
|
||
|
rr[i]=rr[i]*z
|
||
|
else:
|
||
|
IsLoaded=True
|
||
|
IsSetup=True
|
||
|
StartButton["text"]="Start"
|
||
|
RunMotion=False
|
||
|
rr=[]
|
||
|
ff=[]
|
||
|
rextern=rintern=angolo=angolov=0
|
||
|
except:
|
||
|
ms.showerror(title='errore',message='non ho potuto caricare i dati')
|
||
|
# contyrollare di non aver sporcato dei dati ...
|
||
|
finally:
|
||
|
hnd.close()
|
||
|
# ...................................................... Read entries
|
||
|
def ReadData(*arg):
|
||
|
global GetData,IsSetup
|
||
|
if IsSetup:
|
||
|
GetData=True
|
||
|
#........................................................Grab center
|
||
|
def GrabSome(event):
|
||
|
global CenterGrabbed,RadiusGrabbed,PointGrabbed,VectorGrabbed,Ox,Oy,Ca,Cr,x0,y0,vx0,vy0,IsSetup,cp,ttt
|
||
|
if IsSetup:
|
||
|
CenterGrabbed=((Ox-event.x)**2+(Oy-Ca -event.y)**2)<cp*cp
|
||
|
ttt=3
|
||
|
if not CenterGrabbed:
|
||
|
RadiusGrabbed=((Ox-event.x+Cr/sqrt(2))**2+(Oy-Ca-event.y+Cr/sqrt(2))**2)<cp*cp
|
||
|
if not RadiusGrabbed:
|
||
|
PointGrabbed=((Ox+x0-event.x)**2+(Oy-y0-event.y))**2 <cp*cp
|
||
|
if not PointGrabbed:
|
||
|
VectorGrabbed=((Ox+x0-event.x+vx0*c1)**2 + (Oy-y0+-event.y-vy0*c1)**2)<cp*cp
|
||
|
#........................................................Release center
|
||
|
def ReleaseSome(event):
|
||
|
global CenterGrabbed,RadiusGrabbed,PointGrabbed,VectorGrabbed
|
||
|
CenterGRabbed=False
|
||
|
RadiusGrabbed=False
|
||
|
PointGrabbed=False
|
||
|
VectorGrabbed=False
|
||
|
MouseChange=True
|
||
|
#........................................................
|
||
|
def DragSome(event):
|
||
|
global CenterGrabbed,RadiusGrabbed,PointGrabbed,VectorGrabbed,Ox,Oy,Ca,Cr,x0,y0,vx0,vy0,c1,X0,Y0,VX0,VY0,IsSetup,CR
|
||
|
if IsSetup:
|
||
|
if CenterGrabbed:
|
||
|
Caa=Oy-event.y
|
||
|
Ca=InRange(Cr-CR,Caa,CR-Cr)
|
||
|
EntryCa.delete(0,END)
|
||
|
EntryCa.insert(0,'{:.5f}'.format(Ca/CR))
|
||
|
if RadiusGrabbed:
|
||
|
Crr=sqrt((Ox-event.x)**2+(Oy-event.y-Ca)**2)
|
||
|
Cr=InRange(0,Crr,min(CR-Ca,CR+Ca))
|
||
|
EntryCr.delete(0,END)
|
||
|
EntryCr.insert(0,'{:.5f}'.format(Cr/CR))
|
||
|
if PointGrabbed:
|
||
|
x0u=event.x-Ox
|
||
|
y0u=Oy-event.y
|
||
|
su=sqrt(x0u*x0u+y0u*y0u)
|
||
|
if su>CR:
|
||
|
x0u=x0u*CR/su
|
||
|
y0u=y0u*CR/su
|
||
|
su=sqrt(x0u*x0u+(y0u-Ca)*(y0u-Ca))
|
||
|
if su<Cr:
|
||
|
x0u=x0u*Cr/su
|
||
|
y0u=Ca+(y0u-Ca)*Cr/su
|
||
|
X0=x0=x0u
|
||
|
Y0=y0=y0u
|
||
|
Entryx0.delete(0,END)
|
||
|
Entryx0.insert(0,'{:.5f}'.format(x0/CR))
|
||
|
Entryy0.delete(0,END)
|
||
|
Entryy0.insert(0,'{:.5f}'.format(y0/CR))
|
||
|
if VectorGrabbed:
|
||
|
evx=InRange(0,event.x,2*Ox)
|
||
|
evy=InRange(0,event.y,2*Oy)
|
||
|
vx0=evx-x0-Ox
|
||
|
vy0=Oy-y0-evy
|
||
|
c1=sqrt(vx0*vx0+vy0*vy0)
|
||
|
VX0=vx0=vx0/c1
|
||
|
VY0=vy0=vy0/c1
|
||
|
Entryvx0.delete(0,END)
|
||
|
Entryvx0.insert(0,'{:.5f}'.format(vx0))
|
||
|
Entryvy0.delete(0,END)
|
||
|
Entryvy0.insert(0,'{:.5f}'.format(vy0))
|
||
|
#.......................................................
|
||
|
def Clicca(event):
|
||
|
global x0,y0,vx0,vy0,fw,fh,CR,Cr,Ca,IsSetup,Cinterno,RunMotion,rintern,rextern,X0,Y0,VX0,VY0,CR
|
||
|
if IsSetup:
|
||
|
# partenza da punto scelto su canvasf
|
||
|
ff.append(event.x)
|
||
|
ff.append(event.y)
|
||
|
if event.y > fw:
|
||
|
Cinterno=True
|
||
|
rintern=1
|
||
|
rextern=0
|
||
|
aavv=event.y-fw
|
||
|
aaff=event.x*2*pi/fw
|
||
|
aavv=(aavv-fw/2)*pi/fw
|
||
|
x0=Cr*sin(aaff)
|
||
|
y0=Ca+Cr*cos(aaff)
|
||
|
vx0=sin(aaff+aavv)
|
||
|
vy0=cos(aaff+aavv)
|
||
|
rintern=1
|
||
|
rextern=0
|
||
|
else:
|
||
|
Cinterno=False
|
||
|
rintern=0
|
||
|
rextern=1
|
||
|
aavv=event.y
|
||
|
aaff=event.x*2*pi/fw
|
||
|
aavv=(aavv-fw/2)*pi/fw
|
||
|
x0=CR*sin(aaff)
|
||
|
y0=CR*cos(aaff)
|
||
|
vx0=-sin(aaff+aavv)
|
||
|
vy0=-cos(aaff+aavv)
|
||
|
rr.append(Ox+x0)
|
||
|
rr.append(Oy-y0)
|
||
|
X0=x0
|
||
|
Y0=y0
|
||
|
VX0=vx0
|
||
|
VY0=vy0
|
||
|
IsSetup=False
|
||
|
RunMotion=True
|
||
|
StartButton["text"]="Stop"
|
||
|
#------------------------------------------------------
|
||
|
def Mostra(event):
|
||
|
global fw,fh,IsSetup,Cinterno,RunMotion,CR,Ca,Cr,x1,y1,vx1,vy1,cp
|
||
|
if event.y > fw:
|
||
|
aavv=event.y-fw
|
||
|
cinterno=True
|
||
|
else:
|
||
|
aavv=event.y
|
||
|
cinterno=False
|
||
|
aaff=event.x*360/fw
|
||
|
aavv=(aavv-fw/2)*180/fw
|
||
|
Entryposang.delete(0,END)
|
||
|
Entryposang.insert(0,'{:.5f}'.format(aaff))
|
||
|
Entryvelang.delete(0,END)
|
||
|
Entryvelang.insert(0,'{:.5f}'.format(aavv))
|
||
|
# qui mostro il punto partenza e il vettore nel canvas dei cerchi
|
||
|
# ma solo nel SETUP:
|
||
|
if IsSetup:
|
||
|
if cinterno:
|
||
|
x1=Ox+Cr*sin(aaff*pi/180)
|
||
|
y1=Oy-Ca-Cr*cos(aaff*pi/180)
|
||
|
x2=Ox+(Cr+CR*0.1)*sin(aaff*pi/180)
|
||
|
y2=Oy-Ca-(Cr+CR*0.1)*cos(aaff*pi/180)
|
||
|
x3=Ox+Cr*sin(aaff*pi/180)+CR*0.1*sin(aaff*pi/180+aavv*pi/180)
|
||
|
y3=Oy-Ca-Cr*cos(aaff*pi/180)- CR*0.1*cos(aaff*pi/180+aavv*pi/180)
|
||
|
else:
|
||
|
x1=Ox+CR*sin(aaff*pi/180)
|
||
|
y1=Oy-CR*cos(aaff*pi/180)
|
||
|
x2=Ox+CR*sin(aaff*pi/180)*0.9
|
||
|
y2=Oy-CR*cos(aaff*pi/180)*0.9
|
||
|
x3=Ox+CR*sin(aaff*pi/180)-CR*0.1*sin(aaff*pi/180+aavv*pi/180)
|
||
|
y3=Oy-CR*cos(aaff*pi/180)+CR*0.1*cos(aaff*pi/180+aavv*pi/180)
|
||
|
# canvasc.create_oval(x1-cp,y1-cp,x1+cp,y1+cp,fill="green") evidenzia il punto del cerchio
|
||
|
canvasc.create_line(x1,y1,x2,y2,fill="red") # perpendicolare
|
||
|
canvasc.create_line(x1,y1,x3,y3,fill="green",arrow=LAST)
|
||
|
#.......................................................
|
||
|
def calcola():
|
||
|
global x0,y0,vx0,vy0,CR,Cr,Ca,xx,yy,vxx,vyy,Cinterno,fw,angolo,angolov,rextern,rintern
|
||
|
# posizione iniziale x0,y0, velocita iniziale vx0 vy0
|
||
|
# CR raggio esterno, Cr raggio interno, Ca posizione centro interno
|
||
|
# punto di rimbalzo xx,yy con velocita vxx,vyy
|
||
|
# Cinterno = True se rimbalza sul cerchio interno e non esterno
|
||
|
# Il calcolo del rimbalzo non usa la trigonometria, che serve solo a visualizzare le fasi
|
||
|
#print(x0,y0,vx0,vy0,CR,Cr,Ca)
|
||
|
vs=sqrt(vx0*vx0+vy0*vy0)
|
||
|
provv1=(x0*vx0+y0*vy0)/vs
|
||
|
delta1=provv1*provv1-x0*x0-y0*y0+CR*CR
|
||
|
t1= -provv1+sqrt(delta1)
|
||
|
t2= -provv1-sqrt(delta1)
|
||
|
tm12=max(t1,t2)
|
||
|
tm=tm12
|
||
|
# istante contatto circonferenza esterna se non esistesse interna
|
||
|
alfa=0
|
||
|
Cinterno=False
|
||
|
#
|
||
|
provv2=provv1-Ca*vy0/vs
|
||
|
delta2=provv2*provv2-x0*x0-y0*y0-Ca*Ca+2*y0*Ca+Cr*Cr
|
||
|
if delta2 > 0 : # la retta interseca la circonferenza interna
|
||
|
t3=-provv2+sqrt(delta2)
|
||
|
t4=-provv2-sqrt(delta2)
|
||
|
if ((t3<0) or (t4<0)) : # ma a tempi negativi - rimbalzo su circonferenza esterna
|
||
|
alfa=0
|
||
|
tm=tm12
|
||
|
else:
|
||
|
tm34=min(t3,t4)
|
||
|
if (tm34<0): # accade solo se sto partendo dalla circonferenza interna
|
||
|
alfa=0
|
||
|
tm=tm12
|
||
|
else:
|
||
|
alfa=Ca
|
||
|
Cinterno=True
|
||
|
tm=tm34
|
||
|
if delta2==0 :
|
||
|
alfa=0
|
||
|
tm=tm12
|
||
|
xx=x0+vx0*tm/vs
|
||
|
yy=y0+vy0*tm/vs
|
||
|
yya=yy-alfa
|
||
|
yyas=yya*yya
|
||
|
xxs=xx*xx
|
||
|
denom=yyas+xxs
|
||
|
vyy=(vy0*(xxs-yyas)-2*vx0*xx*yya)/denom/vs
|
||
|
vxx=(vx0*(yyas-xxs)-2*vy0*xx*yya)/denom/vs
|
||
|
denom=sqrt(vxx*vxx+vyy*vyy)
|
||
|
vxx=vxx/denom
|
||
|
vyy=vyy/denom
|
||
|
# calcolo fasi : in alto cerchio esterno, in basso cerchio interno
|
||
|
if Cinterno:
|
||
|
angolo=arctan2(xx,yy-Ca)
|
||
|
else:
|
||
|
angolo=arctan2(xx,yy)
|
||
|
if angolo <0:
|
||
|
angolo=angolo+2*pi
|
||
|
# ora angolo sta tra 0 e 2*pi e rappresenta il punto di rimbalzo.
|
||
|
angolov=arctan2(vxx,vyy)-angolo
|
||
|
angolov=arcsin(sin(angolov))
|
||
|
# ora angolov sta tra -pi/2 e +pi/2
|
||
|
# va cambiato segno di angolov esterno (perche esterno punta dentro)
|
||
|
if Cinterno==False:
|
||
|
angolov=-angolov
|
||
|
if Cinterno:
|
||
|
angolov=(angolov+pi/2)*fw/pi + fw
|
||
|
else:
|
||
|
angolov=(angolov+pi/2)*fw/pi
|
||
|
angolo=angolo*fw/(2*pi)
|
||
|
# angolov ora sta tra 0 e fw per cerchio esterno, tra fw e 2*fw per cerchio interno
|
||
|
# angolo sta tra 0 e fw
|
||
|
# aggiorno il numero dei rimbalzi fatti
|
||
|
if Cinterno:
|
||
|
rintern=rintern+1
|
||
|
else:
|
||
|
rextern=rextern+1
|
||
|
###########################################################################
|
||
|
#
|
||
|
# ................................................ Create root window
|
||
|
root=Tk()
|
||
|
root.title("rimbalzi")
|
||
|
root.resizable(width=False,height=False)
|
||
|
root.bind('<Return>',ReadData) #occorre dare un ENTER per fare leggere i dati
|
||
|
# ......................................... Add canvas to root window
|
||
|
# ..................canvasc per i cerchi e canvasf per le fasi
|
||
|
canvasc=Canvas(root, width=cl, height=cl, background='white')
|
||
|
canvasc.grid(row=0,column=0)
|
||
|
# ..................................................... mouse buttons
|
||
|
canvasc.bind("<Button-1>",GrabSome)
|
||
|
canvasc.bind("<B1-Motion>",DragSome)
|
||
|
canvasc.bind("<ButtonRelease-1>",ReleaseSome)
|
||
|
#
|
||
|
canvasf=Canvas(root, width=fw, height=fh, background='white')
|
||
|
canvasf.grid(row=0,column=1)
|
||
|
#
|
||
|
canvasf.bind("<Button-1>",Clicca)
|
||
|
canvasf.bind("<Motion>",Mostra)
|
||
|
#
|
||
|
toolbar=Frame(root)
|
||
|
toolbar.grid(row=0,column=2,sticky=N)
|
||
|
# ................................................... Toolbar buttons
|
||
|
SetupButton=Button(toolbar,text="Setup",command=Setup,width=7)
|
||
|
SetupButton.grid(row=0,column=0)
|
||
|
StartButton=Button(toolbar,text="Start",command=StartStop,width=7)
|
||
|
StartButton.grid(row=0,column=1)
|
||
|
SaveButton=Button(toolbar, text="Save", command=Save,width=7)
|
||
|
SaveButton.grid(row=1,column=0)
|
||
|
LoadButton=Button(toolbar, text="Load", command=Load,width=7)
|
||
|
LoadButton.grid(row=1,column=1)
|
||
|
# nella versione small non c'e' spazio per i distanziatori
|
||
|
if small==False:
|
||
|
Labspazio1=Label(toolbar,text=" ")
|
||
|
Labspazio1.grid(row=2,column=0)
|
||
|
#
|
||
|
# ........................................ Toolbar labels and entries
|
||
|
LabCr=Label(toolbar,text="Cr/CR")
|
||
|
LabCr.grid(row=3,column=0)
|
||
|
EntryCr=Entry(toolbar,bd=5,width=10)
|
||
|
EntryCr.grid(row=3,column=1)
|
||
|
#
|
||
|
LabCa=Label(toolbar,text="Ca/CR")
|
||
|
LabCa.grid(row=4,column=0)
|
||
|
EntryCa=Entry(toolbar,bd=5,width=10)
|
||
|
EntryCa.grid(row=4,column=1)
|
||
|
#
|
||
|
Labx0=Label(toolbar,text="X0/CR")
|
||
|
Labx0.grid(row=5,column=0)
|
||
|
Entryx0=Entry(toolbar,bd=5,width=10)
|
||
|
Entryx0.grid(row=5,column=1)
|
||
|
#
|
||
|
Laby0=Label(toolbar,text="Y0/CR")
|
||
|
Laby0.grid(row=6,column=0)
|
||
|
Entryy0=Entry(toolbar,bd=5,width=10)
|
||
|
Entryy0.grid(row=6,column=1)
|
||
|
#
|
||
|
Labvx0=Label(toolbar,text="VX0")
|
||
|
Labvx0.grid(row=7,column=0)
|
||
|
Entryvx0=Entry(toolbar,bd=5,width=10)
|
||
|
Entryvx0.grid(row=7,column=1)
|
||
|
#
|
||
|
Labvy0=Label(toolbar,text="VY0")
|
||
|
Labvy0.grid(row=8,column=0)
|
||
|
Entryvy0=Entry(toolbar,bd=5,width=10)
|
||
|
Entryvy0.grid(row=8,column=1)
|
||
|
# nella versione small non c'e' spazio per i distanziatori
|
||
|
if small==False:
|
||
|
Labspazio2=Label(toolbar,text=" ")
|
||
|
Labspazio2.grid(row=9,column=0)
|
||
|
#
|
||
|
CloseButton=Button(toolbar, text="Quit", command=StopAll,width=7)
|
||
|
CloseButton.grid(row=10,column=0)
|
||
|
HelpButton=Button(toolbar, text="Help", command=Help,width=7)
|
||
|
HelpButton.grid(row=10,column=1)
|
||
|
# nella versione small non c'e' spazio per i distanziatori
|
||
|
if small==False:
|
||
|
Labspazio3=Label(toolbar,text=" ")
|
||
|
Labspazio3.grid(row=11,column=0)
|
||
|
#
|
||
|
Labrext=Label(toolbar,text="rimb. ext")
|
||
|
Labrext.grid(row=12,column=0)
|
||
|
Entryrext=Entry(toolbar,bd=5,width=10)
|
||
|
Entryrext.grid(row=12,column=1)
|
||
|
Labrint=Label(toolbar,text="rimb. int")
|
||
|
Labrint.grid(row=13,column=0)
|
||
|
Entryrint=Entry(toolbar,bd=5,width=10)
|
||
|
Entryrint.grid(row=13,column=1)
|
||
|
#
|
||
|
Labrtot=Label(toolbar,text="rimb. tot")
|
||
|
Labrtot.grid(row=14,column=0)
|
||
|
Entryrtot=Entry(toolbar,bd=5,width=10)
|
||
|
Entryrtot.grid(row=14,column=1)
|
||
|
Labrrapp=Label(toolbar,text="rimb. int %")
|
||
|
Labrrapp.grid(row=15,column=0)
|
||
|
Entryrrapp=Entry(toolbar,bd=5,width=10)
|
||
|
Entryrrapp.grid(row=15,column=1)
|
||
|
# nella versione small non c'e' spazio per i distanziatori
|
||
|
if small==False:
|
||
|
Labspazio4=Label(toolbar,text=" ")
|
||
|
Labspazio4.grid(row=16,column=0)
|
||
|
#
|
||
|
Labposang=Label(toolbar,text="posiz. angolare")
|
||
|
Labposang.grid(row=17,column=0)
|
||
|
Entryposang=Entry(toolbar,bd=5,width=6)
|
||
|
Entryposang.grid(row=17,column=1)
|
||
|
Labvelang=Label(toolbar,text="angolo rimbalzo")
|
||
|
Labvelang.grid(row=18,column=0)
|
||
|
Entryvelang=Entry(toolbar,bd=5,width=6)
|
||
|
Entryvelang.grid(row=18,column=1)
|
||
|
#
|
||
|
# nella versione small non c'e' spazio per questi bottoni
|
||
|
if small==False:
|
||
|
Labspazio5=Label(toolbar,text=" ")
|
||
|
Labspazio5.grid(row=19,column=0)
|
||
|
#
|
||
|
SaveAllButton=Button(toolbar, text="SaveAll", command=SaveAll,width=7)
|
||
|
SaveAllButton.grid(row=20,column=0)
|
||
|
LoadAllButton=Button(toolbar, text="LoadAll", command=LoadAll,width=7)
|
||
|
LoadAllButton.grid(row=20,column=1)
|
||
|
#
|
||
|
# scrittura valori iniziali
|
||
|
EntryCa.insert(0,'{:.5f}'.format(Ca/CR))
|
||
|
EntryCr.insert(0,'{:.5f}'.format(Cr/CR))
|
||
|
Entryx0.insert(0,'{:.5f}'.format(X0/CR))
|
||
|
Entryy0.insert(0,'{:.5f}'.format(Y0/CR))
|
||
|
Entryvx0.insert(0,'{:.5f}'.format(VX0))
|
||
|
Entryvy0.insert(0,'{:.5f}'.format(VY0))
|
||
|
#......................................................... Variables
|
||
|
delay=20 #milliseconds
|
||
|
if Slow:
|
||
|
delay=200
|
||
|
if Fast:
|
||
|
delay=5
|
||
|
while RunAll:
|
||
|
# .............................................. Draw on canvas ---- Main Loop
|
||
|
#
|
||
|
# codiche che abilita o disabilita i bottoni a secondo delle variabili
|
||
|
if RunMotion:
|
||
|
# mentre gira non voglio poter entrare in setup, save, saveall, load, loadall : restano lo stop, lo help e il quit
|
||
|
SetupButton['state']=DISABLED
|
||
|
SaveButton['state']=DISABLED
|
||
|
SaveAllButton['state']=DISABLED
|
||
|
LoadButton['state']=DISABLED
|
||
|
LoadAllButton['state']=DISABLED
|
||
|
else:
|
||
|
SetupButton['state']=NORMAL
|
||
|
SaveButton['state']=NORMAL
|
||
|
SaveAllButton['state']=NORMAL
|
||
|
LoadButton['state']=NORMAL
|
||
|
LoadAllButton['state']=NORMAL
|
||
|
|
||
|
if IsLoadedall or IsLoaded:
|
||
|
canvasf.delete(ALL)
|
||
|
canvasc.delete(ALL)
|
||
|
# canvasc.create_oval(Ox-cp,Oy-Ca-cp,Ox+cp,Oy-Ca+cp,fill="black") # centro cerchio interno, mobile
|
||
|
# canvasc.create_oval(Ox-cp+Cr/sqrt(2),Oy-Ca-cp+Cr/sqrt(2),Ox+cp+Cr/sqrt(2),Oy-Ca+cp+Cr/sqrt(2),fill="black") # maniglia per cambiare raggio
|
||
|
# canvasc.create_oval(Ox+x0-cp,Oy-y0-cp,Ox+x0+cp,Oy-y0+cp,fill="black") # maniglia per spostare il punto di partenza
|
||
|
# canvasc.create_oval(Ox+x0-cp+vx0*c1,Oy-y0-cp-vy0*c1,Ox+x0+cp+vx0*c1,Oy-y0+cp-vy0*c1,fill="black") # maniglia per spostare il vettore di partenza
|
||
|
if IsLoaded:
|
||
|
canvasc.create_line(Ox+x0,Oy-y0,Ox+x0+vx0*c1,Oy-y0-vy0*c1,arrow=LAST) # freccia del vettore iniziale
|
||
|
canvasc.config(cursor="target blue") #cursore tondo blu sul canvas dei cerchi
|
||
|
canvasf.config(cursor="target red") #cursore tondo rosso sul canvas delle fasi
|
||
|
|
||
|
if IsSetup:
|
||
|
canvasf.delete(ALL)
|
||
|
canvasc.delete(ALL)
|
||
|
if CenterGrabbed: #effetto ottico quando si ottiene il grab
|
||
|
if ttt==1:
|
||
|
canvasc.create_oval(Ox-2*cp,Oy-Ca-2*cp,Ox+2*cp,Oy-Ca+2*cp,fill="blue") # centro cerchio interno, mobile blue
|
||
|
ttt=0
|
||
|
if ttt==2:
|
||
|
canvasc.create_oval(Ox-4*cp,Oy-Ca-4*cp,Ox+4*cp,Oy-Ca+4*cp,fill="blue") #
|
||
|
ttt=1
|
||
|
if ttt==3:
|
||
|
canvasc.create_oval(Ox-5*cp,Oy-Ca-5*cp,Ox+5*cp,Oy-Ca+5*cp,fill="blue") #
|
||
|
ttt=2
|
||
|
canvasc.create_oval(Ox-cp,Oy-Ca-cp,Ox+cp,Oy-Ca+cp,fill="black") # centro cerchio interno, mobile nero
|
||
|
if RadiusGrabbed: #effetto ottico quando si ottiene il grab
|
||
|
if ttt==1:
|
||
|
canvasc.create_oval(Ox-2*cp+Cr/sqrt(2),Oy-Ca-2*cp+Cr/sqrt(2),Ox+2*cp+Cr/sqrt(2),Oy-Ca+2*cp+Cr/sqrt(2),fill="blue") # maniglia per cambiare raggio blue
|
||
|
ttt=0
|
||
|
if ttt==2:
|
||
|
canvasc.create_oval(Ox-4*cp+Cr/sqrt(2),Oy-Ca-4*cp+Cr/sqrt(2),Ox+4*cp+Cr/sqrt(2),Oy-Ca+4*cp+Cr/sqrt(2),fill="blue") #
|
||
|
ttt=1
|
||
|
if ttt==3:
|
||
|
canvasc.create_oval(Ox-5*cp+Cr/sqrt(2),Oy-Ca-5*cp+Cr/sqrt(2),Ox+5*cp+Cr/sqrt(2),Oy-Ca+5*cp+Cr/sqrt(2),fill="blue") #
|
||
|
ttt=2
|
||
|
canvasc.create_oval(Ox-cp+Cr/sqrt(2),Oy-Ca-cp+Cr/sqrt(2),Ox+cp+Cr/sqrt(2),Oy-Ca+cp+Cr/sqrt(2),fill="black") # maniglia per cambiare raggio nero
|
||
|
if PointGrabbed: #effetto ottico quando si ottiene il grab
|
||
|
if ttt==1:
|
||
|
canvasc.create_oval(Ox+x0-2*cp,Oy-y0-2*cp,Ox+x0+2*cp,Oy-y0+2*cp,fill="blue") # maniglia per spostare il punto di partenza blu
|
||
|
ttt=0
|
||
|
if ttt==2:
|
||
|
canvasc.create_oval(Ox+x0-4*cp,Oy-y0-4*cp,Ox+x0+4*cp,Oy-y0+4*cp,fill="blue") #
|
||
|
ttt=1
|
||
|
if ttt==3:
|
||
|
canvasc.create_oval(Ox+x0-5*cp,Oy-y0-5*cp,Ox+x0+5*cp,Oy-y0+5*cp,fill="blue") #
|
||
|
ttt=2
|
||
|
canvasc.create_oval(Ox+x0-cp,Oy-y0-cp,Ox+x0+cp,Oy-y0+cp,fill="black") # maniglia per spostare il punto di partenza nero
|
||
|
if VectorGrabbed: #effetto ottico quando si ottiene il grab
|
||
|
if ttt==1:
|
||
|
canvasc.create_oval(Ox+x0-2*cp+vx0*c1,Oy-y0-2*cp-vy0*c1,Ox+x0+2*cp+vx0*c1,Oy-y0+2*cp-vy0*c1,fill="blue") # maniglia per spostare il vettore di partenza blu
|
||
|
ttt=0
|
||
|
if ttt==2:
|
||
|
canvasc.create_oval(Ox+x0-4*cp+vx0*c1,Oy-y0-4*cp-vy0*c1,Ox+x0+4*cp+vx0*c1,Oy-y0+4*cp-vy0*c1,fill="blue") #
|
||
|
ttt=1
|
||
|
if ttt==3:
|
||
|
canvasc.create_oval(Ox+x0-5*cp+vx0*c1,Oy-y0-5*cp-vy0*c1,Ox+x0+5*cp+vx0*c1,Oy-y0+5*cp-vy0*c1,fill="blue") #
|
||
|
ttt=2
|
||
|
|
||
|
canvasc.create_oval(Ox+x0-cp+vx0*c1,Oy-y0-cp-vy0*c1,Ox+x0+cp+vx0*c1,Oy-y0+cp-vy0*c1,fill="black") # maniglia per spostare il vettore di partenza
|
||
|
|
||
|
canvasc.create_line(Ox+x0,Oy-y0,Ox+x0+vx0*c1,Oy-y0-vy0*c1,arrow=LAST) # freccia del vettore iniziale
|
||
|
canvasc.config(cursor="target blue") #cursore tondo blu sul canvas dei cerchi
|
||
|
canvasf.config(cursor="target red") #cursore tondo rosso sul canvas delle fasi
|
||
|
if GetData: #input dei dati permesso solo nella fase di SETUP
|
||
|
# va controllato che i dati siano consistenti
|
||
|
try:
|
||
|
eCa=float(EntryCa.get())
|
||
|
except ValueError:
|
||
|
pass
|
||
|
try:
|
||
|
eCr=float(EntryCr.get())
|
||
|
except ValueError:
|
||
|
pass
|
||
|
try:
|
||
|
ex0=float(Entryx0.get())
|
||
|
except ValueError:
|
||
|
pass
|
||
|
try:
|
||
|
ey0=float(Entryy0.get())
|
||
|
except ValueError:
|
||
|
pass
|
||
|
try:
|
||
|
evx0=float(Entryvx0.get())
|
||
|
except ValueError:
|
||
|
pass
|
||
|
try:
|
||
|
evy0=float(Entryvy0.get())
|
||
|
except ValueError:
|
||
|
pass
|
||
|
Ca=InRange(Cr-CR,eCa,CR-Cr)
|
||
|
Cr=InRange(0,eCr,min(CR-Ca,CR+Ca))
|
||
|
su=sqrt(ex0*ex0+ey0*ey0)
|
||
|
if su>CR:
|
||
|
ex0=ex0*CR/su
|
||
|
ey0=ey0*CR/su
|
||
|
su=sqrt(ex0*ex0+(ey0-Ca)*(ey0-Ca))
|
||
|
if su<Cr:
|
||
|
ex0=ex0*Cr/su
|
||
|
ey0=Ca+(ey0-Ca)*Cr/su
|
||
|
x0=X0=ex0
|
||
|
y0=Y0=ey0
|
||
|
if (evx0*evx0+evy0*evy0==0):
|
||
|
evx0=evy0=1.0
|
||
|
su=sqrt(evx0*evx0+evy0*evy0)
|
||
|
vx0=VX0=evx0/su
|
||
|
vy0=VY0=evy0/su
|
||
|
# ................................ Write variable values into entries
|
||
|
EntryCa.delete(0,END)
|
||
|
EntryCa.insert(0,'{:.5f}'.format(Ca/CR))
|
||
|
EntryCr.delete(0,END)
|
||
|
EntryCr.insert(0,'{:.5f}'.format(Cr/CR))
|
||
|
Entryx0.delete(0,END)
|
||
|
Entryx0.insert(0,'{:.5f}'.format(X0/CR))
|
||
|
Entryy0.delete(0,END)
|
||
|
Entryy0.insert(0,'{:.5f}'.format(Y0/CR))
|
||
|
Entryvx0.delete(0,END)
|
||
|
Entryvx0.insert(0,'{:.5f}'.format(VX0))
|
||
|
Entryvy0.delete(0,END)
|
||
|
Entryvy0.insert(0,'{:.5f}'.format(VY0))
|
||
|
GetData=False #fine della fase di letture dei dati
|
||
|
#
|
||
|
if RunMotion:
|
||
|
if IsSetup or IsLoaded:
|
||
|
IsSetup = False # se si clicca il cursore rosso durante il setup, IsSetup e RunMotion sono entrambi True!
|
||
|
IsLoaded = False # anche se si passa a dare Load e poi Start
|
||
|
rr.append(Ox+x0)
|
||
|
rr.append(Oy-y0)
|
||
|
calcola()
|
||
|
rr.append(Ox+xx)
|
||
|
rr.append(Oy-yy)
|
||
|
ff.append(angolo)
|
||
|
ff.append(angolov)
|
||
|
x0=xx
|
||
|
y0=yy
|
||
|
vx0=vxx
|
||
|
vy0=vyy
|
||
|
canvasc.delete(ALL) ##########################################################<<<<<<<<<<<<<<<<<<<<
|
||
|
canvasc.create_line(rr)
|
||
|
# questo e' comando che disegna tutte le traiettorie del rimbalzo !
|
||
|
Entryrext.delete(0,END)
|
||
|
Entryrext.insert(0,'{:10d}'.format(rextern))
|
||
|
Entryrint.delete(0,END)
|
||
|
Entryrint.insert(0,'{:10d}'.format(rintern))
|
||
|
Entryrtot.delete(0,END)
|
||
|
Entryrtot.insert(0,'{:10d}'.format(rintern+rextern))
|
||
|
Entryrrapp.delete(0,END)
|
||
|
Entryrrapp.insert(0,'{:.8f}'.format(rintern/(rintern+rextern)))
|
||
|
EntryCa.delete(0,END)
|
||
|
EntryCa.insert(0,'{:.5f}'.format(Ca/CR))
|
||
|
EntryCr.delete(0,END)
|
||
|
EntryCr.insert(0,'{:.5f}'.format(Cr/CR))
|
||
|
Entryx0.delete(0,END)
|
||
|
Entryx0.insert(0,'{:.5f}'.format(X0/CR))
|
||
|
Entryy0.delete(0,END)
|
||
|
Entryy0.insert(0,'{:.5f}'.format(Y0/CR))
|
||
|
Entryvx0.delete(0,END)
|
||
|
Entryvx0.insert(0,'{:.5f}'.format(VX0))
|
||
|
Entryvy0.delete(0,END)
|
||
|
Entryvy0.insert(0,'{:.5f}'.format(VY0))
|
||
|
#
|
||
|
canvasf.delete(ALL) ##########################################################<<<<<<<<<<<<<<<<<<<<
|
||
|
i=0
|
||
|
while i < len(ff):
|
||
|
canvasf.create_oval(ff[i],ff[i+1],ff[i],ff[i+1]) # sembra sia il solo modo per disegnare un singolo punto in tkinter !
|
||
|
i=i+2
|
||
|
canvasf.create_oval(ff[len(ff)-2]-cp,ff[len(ff)-1]-cp,ff[len(ff)-2]+cp,ff[len(ff)-1]+cp,fill="yellow") #il punto attuale evidenziato in giallo
|
||
|
# ora vanno disegnati i vari elementi geometrici sui due canvas !
|
||
|
#
|
||
|
canvasc.create_oval(1,1,2*CR,2*CR,outline="red") # cerchio esterno, fisso
|
||
|
# tics per il cerchio esterno, ogni 45 gradi
|
||
|
for i in range(0,8):
|
||
|
f=i*pi/4
|
||
|
canvasc.create_line(Ox+CR*cos(f),Oy-CR*sin(f),Ox+CR*cos(f)*0.96,Oy-CR*sin(f)*0.96,fill="red")
|
||
|
canvasc.create_text(Ox+CR*0.95,Oy,text='90',font=('Times','12', 'italic'))
|
||
|
canvasc.create_text(Ox,Oy+CR*0.95,text='180',font=('Times','12', 'italic'))
|
||
|
canvasc.create_text(Ox-CR*0.95,Oy,text='270',font=('Times','12', 'italic'))
|
||
|
canvasc.create_text(Ox,Oy-CR*0.95,text='0-360',font=('Times','12', 'italic'))
|
||
|
canvasc.create_oval(Ox-Cr,Oy-Ca-Cr,Ox+Cr,Oy-Ca+Cr,outline="red") # cerchio interno, mobile
|
||
|
for i in range(0,8):
|
||
|
f=i*pi/4
|
||
|
canvasc.create_line(Ox+Cr*cos(f),Oy-Ca-Cr*sin(f),Ox+Cr*cos(f)*1.06,Oy-Ca-Cr*sin(f)*1.06,fill="red")
|
||
|
# canvas delle fasi
|
||
|
canvasf.create_line(0,fw,fw,fw,fill="red") # separatore tra le due fasi
|
||
|
canvasf.create_line(1,0,1,2*fw,fill="red")
|
||
|
canvasf.create_line(fw,0,fw,2*fw,fill="red")
|
||
|
canvasf.create_line(1,1,fw,1,fill="red")
|
||
|
canvasf.create_line(1,2*fw,fw,2*fw,fill="red")
|
||
|
canvasf.create_text(20,20,text='EXT',font=('Times','12', 'italic')) # circonferenza esterna
|
||
|
canvasf.create_text(20,20+fw,text='INT',font=('Times','12', 'italic')) # circonferenza interna
|
||
|
# tics e scala per il punto sulle circonferenze
|
||
|
canvasf.create_text(3*cpp,fw-3*cpp,text='0',font=('Times','12', 'italic'))
|
||
|
canvasf.create_line(fw/2,0,fw/2,2*fw,fill="blue")
|
||
|
canvasf.create_text(fw/2,fw-3*cpp,text='180',font=('Times','12', 'italic'))
|
||
|
canvasf.create_line(fw/4,0,fw/4,2*fw,fill="blue")
|
||
|
canvasf.create_text(fw/4,fw-3*cpp,text='90',font=('Times','12', 'italic'))
|
||
|
canvasf.create_line(3*fw/4,0,3*fw/4,2*fw,fill="blue")
|
||
|
canvasf.create_text(3*fw/4,fw-3*cpp,text='270',font=('Times','12', 'italic'))
|
||
|
canvasf.create_text(fw-4*cpp,fw-3*cpp,text='360',font=('Times','12', 'italic'))
|
||
|
# tics e scala per l'angolo di rimbalzo rispetto la normale delle circonferenze
|
||
|
canvasf.create_line(0,fw/2,fw,fw/2,fill="blue")
|
||
|
canvasf.create_text(7*cpp,fw/2,text='0',font=('Times','12', 'italic'))
|
||
|
canvasf.create_line(0,fw+fw/2,fw,fw+fw/2,fill="blue")
|
||
|
canvasf.create_text(7*cpp,fw+fw/2,text='0',font=('Times','12', 'italic'))
|
||
|
#
|
||
|
canvasf.create_line(0,fw/4,fw,fw/4,fill="blue")
|
||
|
canvasf.create_text(7*cpp,fw/4-2*cpp,text='-45',font=('Times','12', 'italic'))
|
||
|
canvasf.create_line(0,fw+fw/4,fw,fw+fw/4,fill="blue")
|
||
|
canvasf.create_text(7*cpp,fw+fw/4-2*cpp,text='-45',font=('Times','12', 'italic'))
|
||
|
#
|
||
|
canvasf.create_line(0,3*fw/4,fw,3*fw/4,fill="blue")
|
||
|
canvasf.create_text(7*cpp,3*fw/4-cpp,text='+45',font=('Times','12', 'italic'))
|
||
|
canvasf.create_line(0,fw+3*fw/4,fw,fw+3*fw/4,fill="blue")
|
||
|
canvasf.create_text(7*cpp,fw+3*fw/4-cpp,text='+45',font=('Times','12', 'italic'))
|
||
|
#
|
||
|
if IsLoaded:
|
||
|
EntryCa.delete(0,END)
|
||
|
EntryCa.insert(0,'{:.5f}'.format(Ca/CR))
|
||
|
EntryCr.delete(0,END)
|
||
|
EntryCr.insert(0,'{:.5f}'.format(Cr/CR))
|
||
|
Entryx0.delete(0,END)
|
||
|
Entryx0.insert(0,'{:.5f}'.format(X0/CR))
|
||
|
Entryy0.delete(0,END)
|
||
|
Entryy0.insert(0,'{:.5f}'.format(Y0/CR))
|
||
|
Entryvx0.delete(0,END)
|
||
|
Entryvx0.insert(0,'{:.5f}'.format(VX0))
|
||
|
Entryvy0.delete(0,END)
|
||
|
Entryvy0.insert(0,'{:.5f}'.format(VY0))
|
||
|
|
||
|
if IsLoadedall:
|
||
|
canvasc.create_line(rr)
|
||
|
i=0
|
||
|
while i < len(ff):
|
||
|
canvasf.create_oval(ff[i],ff[i+1],ff[i],ff[i+1]) # sembra sia il solo modo per disegnare un singolo punto in tkinter !
|
||
|
i=i+2
|
||
|
canvasf.create_oval(ff[len(ff)-2]-cp,ff[len(ff)-1]-cp,ff[len(ff)-2]+cp,ff[len(ff)-1]+cp,fill="yellow") #il punto attuale evidenziato in giallo
|
||
|
Entryrext.delete(0,END)
|
||
|
Entryrext.insert(0,'{:10d}'.format(rextern))
|
||
|
Entryrint.delete(0,END)
|
||
|
Entryrint.insert(0,'{:10d}'.format(rintern))
|
||
|
Entryrtot.delete(0,END)
|
||
|
Entryrtot.insert(0,'{:10d}'.format(rintern+rextern))
|
||
|
Entryrrapp.delete(0,END)
|
||
|
Entryrrapp.insert(0,'{:.8f}'.format(rintern/(rintern+rextern)))
|
||
|
EntryCa.delete(0,END)
|
||
|
EntryCa.insert(0,'{:.25}'.format(Ca/CR))
|
||
|
EntryCr.delete(0,END)
|
||
|
EntryCr.insert(0,'{:.25}'.format(Cr/CR))
|
||
|
Entryx0.delete(0,END)
|
||
|
Entryx0.insert(0,'{:.25}'.format(X0/CR))
|
||
|
Entryy0.delete(0,END)
|
||
|
Entryy0.insert(0,'{:.25}'.format(Y0/CR))
|
||
|
Entryvx0.delete(0,END)
|
||
|
Entryvx0.insert(0,'{:.5f}'.format(VX0))
|
||
|
Entryvy0.delete(0,END)
|
||
|
Entryvy0.insert(0,'{:.5f}'.format(VY0))
|
||
|
#
|
||
|
canvasf.update()
|
||
|
canvasc.update()
|
||
|
#................................................. Wait delay time
|
||
|
canvasc.after(delay)
|
||
|
canvasf.after(delay)
|
||
|
#-------------------------
|
||
|
root.destroy()
|
||
|
#
|
||
|
##############################################
|
||
|
# todo:
|
||
|
# reverse motion
|
||
|
# clear trajectories
|
||
|
# clear phases
|
||
|
# colorize trajectories
|
||
|
###############################################
|