from tkinter import *
from math import *

def f(x):
    return x+sin(x**2 + 4*x - 5)

def tabuler(f, x_min, x_max):
    tableau = []
    delta_x = (x_max-x_min)/nb_points
    x = x_min
    while x <= x_max:
        tableau.append([x,f(x)])
        x += delta_x
    return tableau

def y_min_et_max(t):
    y_min = t[0][1]
    y_max = y_min
    for pt in t:
        if pt[1]>y_max:
            y_max = pt[1]
        if pt[1]<y_min:
            y_min = pt[1]
    return y_min, y_max

def axes(x_min, x_max, y_min, y_max):
        x1, y1 = echelle(x_min, 0, x_min, x_max, y_min, y_max) # axe 0x
        x2, y2 = echelle(x_max,0, x_min, x_max, y_min, y_max)
        can.create_line(x1, y1, x2, y2, width=1, fill='black')
        x2, y2 = echelle(0, y_min, x_min, x_max, y_min, y_max) # axe 0y
        x1, y1 = echelle(0, y_max, x_min, x_max, y_min, y_max) 
        can.create_line(x1, y1, x2, y2, width=1, fill='black')
    
def echelle(x, y, x_min, x_max, y_min, y_max):
    # change l'échelle
    a = largeur/(x_max-x_min)
    b = -a * x_min
    x1 = a*x + b
    a = hauteur/(y_min-y_max)
    b = -a * y_max
    y1 = a*y + b
    return x1, y1

def courbe(t, x_min, x_max, y_min, y_max):
    for i in range(len(t)):
        if i<len(t)-1:
            x1, y1 = echelle(t[i][0], t[i][1], x_min, x_max, y_min, y_max)
            x2, y2 = echelle(t[i+1][0], t[i+1][1], x_min, x_max, y_min, y_max)
            can.create_line(x1, y1, x2, y2, width=2, fill='blue')

def graduer_x(x_min, x_max, y_min, y_max):
    diff = x_max - x_min
    nb_ticks = diff
    while nb_ticks < 15:
        nb_ticks *= 2
    while nb_ticks > 25:
        nb_ticks = (nb_ticks+1)//2
    #nb_ticks += 1
    delta_x = diff / nb_ticks
    x = 0
    x1 = 0
    while x1 < largeur:
        x1, y1 = echelle(x, 0, x_min, x_max, y_min, y_max)
        can.create_line(x1, 0, x1, hauteur, width=1, fill='gray75')
        can.create_line(x1, y1-5, x1, y1+5, width=1, fill='black')
        if x == int(x) and x!=0:
            can.create_text(x1,y1+12,text=str(int(x)))
        x += delta_x
    x = 0
    x1 = 10000
    while x1 > 0:
        x1, y1 = echelle(x, 0, x_min, x_max, y_min, y_max)
        can.create_line(x1, 0, x1, hauteur, width=1, fill='gray75')
        can.create_line(x1, y1-5, x1, y1+5, width=1, fill='black')
        if x == int(x) and x!=0:
            can.create_text(x1,y1+12,text=str(int(x)))
        x -= delta_x
    
def graduer_y(x_min, x_max, y_min, y_max):
    diff = y_max - y_min
    nb_ticks = diff
    while nb_ticks < 15:
        nb_ticks *= 2
    while nb_ticks > 25:
        nb_ticks = (nb_ticks+1)//2
    delta_y = diff / nb_ticks
    y = 0
    y1 = 100000
    while y1 > 0:
        x1, y1 = echelle(0, y, x_min, x_max, y_min, y_max)
        can.create_line(0, y1, largeur, y1, width=1, fill='gray75')
        can.create_line(x1-5, y1, x1+5, y1, width=1, fill='black')
        if y == int(y) and y!=0:
            can.create_text(x1+12,y1,text=str(int(y)))
        y += delta_y
    y = 0
    y1 = 0
    while y1 < hauteur:
        x1, y1 = echelle(0, y, x_min, x_max, y_min, y_max)
        can.create_line(0, y1, largeur, y1, width=1, fill='gray75')
        can.create_line(x1-5, y1, x1+5, y1, width=1, fill='black')
        if y == int(y) and y!=0:
            can.create_text(x1+12,y1,text=str(int(y)))
        y -= delta_y
    
def reinit():
    x_min = -6
    x_max = 3
    tab = []
    tab = tabuler(f, x_min, x_max)
    y_min, y_max = y_min_et_max(tab)
    #print(y_min, y_max)
    a1,b1 = echelle(x_max, y_max, x_min, x_max, y_min, y_max)
    #print(a1,b1)
    graduer_x(x_min, x_max, y_min, y_max)
    graduer_y(x_min, x_max, y_min, y_max)
    axes(x_min, x_max, y_min, y_max)
    courbe(tab, x_min, x_max, y_min, y_max)

hauteur = 600
largeur = 4*hauteur//3
nb_points = largeur
fenetre = Tk()
fenetre.title("Mon traceur de courbe")

can = Canvas(fenetre, bg='white', width=largeur, height=hauteur)
can.pack(side=LEFT)

reinit()


