#!/usr/bin/env python3
#coding: utf8 
import os
import numpy as np
from tkinter import *
from tkinter.messagebox import *
from random import *
from scipy.integrate import odeint

global RunAll
global RunIter

RunAll=True
RunIter=False
IsColl=False

def StartStop():
  global RunIter
  RunIter=not RunIter
  if RunIter:
    StartButton["text"]="Stop"
  else:
    StartButton["text"]="Restart"
    
def StopAll():
  global RunAll
  RunAll=False


root=Tk()
root.title("Spring Pendulum")
cw=800
ch=640
pict=Canvas(root,width=cw,height=ch,background="#ffffff")
pict.grid(row=1,column=0)

toolbar=Frame(root)
toolbar.grid(row=0,column=0, sticky=W)


StartButton=Button(toolbar,text="Start",command=StartStop)
StartButton.grid(row=0,column=0)

L1=Label(toolbar,text="Length")
L1.grid(row=0,column=1)
E1 = Entry(toolbar,bd =5,width=5,textvariable="200")
E1.grid(row=0,column=2)

L2=Label(toolbar,text="Hooke")
L2.grid(row=0,column=3)
E2 = Entry(toolbar,bd =5,width=5,textvariable="10.0")
E2.grid(row=0,column=4)

CloseButton=Button(toolbar, text="Close", command=StopAll)
CloseButton.grid(row=0,column=5)

cycle_period=20 #milliseconds

# ...................................................................... Origin
Ox=cw/2
Oy=ch/2
prad=3
# ..................................................................... gravity
G=9.8
# .............................................................................
attr=0.0
# .................................................................... pendulum
L=200
rad=12
m=10.0
Hooke=10.0
attr=0.0
pColor="red"
E1.insert(0,str(L))
E2.insert(0,str(Hooke))
# .................................................................... function
def f(y, t, params):
  xx,vx,yy,vy = y                       # unpack current values of y
  L,m,G,Hooke,visc = params                   # unpack parameters
  deltax=xx-Ox
  deltay=yy-Oy
  length=np.sqrt(deltax**2+deltay**2)
  stretch=length-L
  theta=np.arctan2(deltax,deltay)
  force=-Hooke*stretch
  fx=force*np.sin(theta)
  fy=force*np.cos(theta)
  ax=(fx/m)
  ay=(fy/m)+G
  derivs=[vx,ax,vy,ay]
  return derivs
# .................................................................. viscosity
visc=0.0
#.............................................................. initial values
xx=Ox+1.1*L
vx=0.0
yy=Oy
vy=0.0
y=[xx,vx,yy,vy]
# .................................................................. parameters
params=[L,m,G,Hooke,attr]
# .............................................................................
#t=np.arange(0.0,1.5,1.0)
t=[0.0,0.1]
# ........................................................................ loop
while RunAll:
  # ............................................................. draw pendulum
  pict.delete(ALL)
  pict.create_oval(Ox-L,Oy-L,Ox+L,Oy+L,fill="white",outline="green",width=1)
  pict.create_line(0,Oy,cw,Oy,fill="green")
  pict.create_oval(Ox-prad,Oy-prad,Ox+prad,Oy+prad,fill="black")
  pict.create_line(Ox,Oy,xx,yy,fill="black")
  pict.create_oval(xx-rad,yy-rad,xx+rad,yy+rad,fill=pColor)
  pict.update()
  pict.after(cycle_period)
  if RunIter:
    # ............................................................... next step
    psoln = odeint(f,y,t,args=(params,))
    xx=psoln[1,0]
    vx=psoln[1,1]
    yy=psoln[1,2]
    vy=psoln[1,3]
    # ............................................................................
    y=[xx,vx,yy,vy]
  else:
    try:
      L=float(E1.get())
    except ValueError:
      pass
    try:
      Hooke=float(E2.get())
    except ValueError:
      pass
    params[0]=L
    params[3]=Hooke
  #----------------------------------------------------------------------------
root.destroy()
root.mainloop()
  