#### Programmer par Romain Joly - Institut Fourier ####

from math import *
from tkinter import *


################################################################
######### Introduction #########################################

# Un arbre
#segments=[[[400,500], [400,50]]] 
#liste_transfo=[[0.5,1],[0.5,0.8+0.4j],[0.5,0.9-0.2j]] 
def arbre():
    global segments, liste_transfo,itemax,reperes_seg,etape,etapes_faites
    segments=[[[400,500], [400,50]]] 
    liste_transfo=[[0.5,1],[0.5,0.8+0.4j],[0.5,0.9-0.2j]]
    dessin_etapes.set(True)
    itemax=int((log(10000)-log(len(segments)))/log(len(liste_transfo)))
    reperes_seg=[0,len(segments)]
    for i in range(itemax+1):
        repere=(reperes_seg[-1]+(reperes_seg[-1]-reperes_seg[-2])*len(liste_transfo))
        reperes_seg.append(repere)
    etape=0
    etapes_faites=0
    dessin.delete(ALL)
    dessine(segments)

# Une foret
#segments=[[[100,500],[100,300]],[[200,500], [200,50]],[[400,500],[450,150]],[[700,500],[700,100]]] 
#liste_transfo=[[0.4,1],[0.4,0.8+0.4j],[0.5,0.95-0.25j]] 
def foret():
    global segments, liste_transfo,itemax,reperes_seg,etape,etapes_faites
    segments=[[[100,500],[100,300]],[[200,500], [200,50]],[[400,500],[450,150]],[[700,500],[700,100]]] 
    liste_transfo=[[0.4,1],[0.4,0.8+0.4j],[0.5,0.95-0.25j]]
    dessin_etapes.set(True)
    itemax=int((log(10000)-log(len(segments)))/log(len(liste_transfo)))
    reperes_seg=[0,len(segments)]
    for i in range(itemax+1):
        repere=(reperes_seg[-1]+(reperes_seg[-1]-reperes_seg[-2])*len(liste_transfo))
        reperes_seg.append(repere)
    etape=0
    etapes_faites=0
    dessin.delete(ALL)
    dessine(segments)

# Flocon de Von Koch
#segments=[[[50,450], [950,450]]]
#liste_transfo=[[0,1/3],[1/3,1/2-1j/(2*sqrt(3))],[1/2-1j/(2*sqrt(3)),2/3],[2/3,1]] 
def flocon():
    global segments, liste_transfo,itemax,reperes_seg,etape,etapes_faites
    segments=[[[50,450], [950,450]]]
    liste_transfo=[[0,1/3],[1/3,1/2-1j/(2*sqrt(3))],[1/2-1j/(2*sqrt(3)),2/3],[2/3,1]] 
    dessin_etapes.set(False)
    itemax=int((log(10000)-log(len(segments)))/log(len(liste_transfo)))
    reperes_seg=[0,len(segments)]
    for i in range(itemax+1):
        repere=(reperes_seg[-1]+(reperes_seg[-1]-reperes_seg[-2])*len(liste_transfo))
        reperes_seg.append(repere)
    etape=0
    etapes_faites=0
    dessin.delete(ALL)
    dessine(segments)

# le dragon
segments=[[[260,170], [740,170]]]
liste_transfo=[[0,0.5+0.5j],[1,0.5+0.5j]] 
def dragon():
    global segments, liste_transfo,itemax,reperes_seg,etape,etapes_faites
    segments=[[[260,170], [740,170]]]
    liste_transfo=[[0,0.5+0.5j],[1,0.5+0.5j]] 
    dessin_etapes.set(False)
    itemax=int((log(10000)-log(len(segments)))/log(len(liste_transfo)))
    reperes_seg=[0,len(segments)]
    for i in range(itemax+1):
        repere=(reperes_seg[-1]+(reperes_seg[-1]-reperes_seg[-2])*len(liste_transfo))
        reperes_seg.append(repere)
    etape=0
    etapes_faites=0
    dessin.delete(ALL)
    dessine(segments)

# Tapis de Sierpinski
#segments=[[[270,450],[500,450-460*sqrt(3)/2]],[[500,450-460*sqrt(3)/2],[730,450]],[[730,450],[270,450]]]
#liste_transfo=[[0,0.5],[0.5,0.25+1j*sqrt(3)/4],[0.25+1j*sqrt(3)/4,0]] 
def tapis():
    global segments, liste_transfo,itemax,reperes_seg,etape,etapes_faites
    segments=[[[270,450],[500,450-460*sqrt(3)/2]],[[500,450-460*sqrt(3)/2],[730,450]],[[730,450],[270,450]]]
    liste_transfo=[[0,0.5],[0.5,0.25+1j*sqrt(3)/4],[0.25+1j*sqrt(3)/4,0]] 
    dessin_etapes.set(False)
    itemax=int((log(10000)-log(len(segments)))/log(len(liste_transfo)))
    reperes_seg=[0,len(segments)]
    for i in range(itemax+1):
        repere=(reperes_seg[-1]+(reperes_seg[-1]-reperes_seg[-2])*len(liste_transfo))
        reperes_seg.append(repere)
    etape=0
    etapes_faites=0
    dessin.delete(ALL)
    dessine(segments)



itemax=int((log(10000)-log(len(segments)))/log(len(liste_transfo)))

reperes_seg=[0,len(segments)]
for i in range(itemax+1):
    repere=(reperes_seg[-1]+(reperes_seg[-1]-reperes_seg[-2])*len(liste_transfo))
    reperes_seg.append(repere)

etape=0
etapes_faites=0

################################################################
######### Fonctions ############################################

def C2V(complexe):
    return([complexe.real, complexe.imag])

def V2C(vecteur):
    return(vecteur[0]+vecteur[1]*1j)

def ajout_etape(seg):
    global liste_transfo
    seg2=[]
    for ab in seg:
        a=V2C(ab[0])
        b=V2C(ab[1])
        c=b-a
        for transfo in liste_transfo:
            seg2.append([C2V(a+transfo[0]*c), C2V(a+transfo[1]*c)])
    return seg2

def dessine(seg):
    global etape
    for ab in seg:
        a=ab[0]
        b=ab[1]
        dessin.create_line(a,b,width=1.5,fill="red")

def suivant():
    global segments, etape, reperes_seg, etapes_faites
    if etape >= (len(reperes_seg)-2):
        avertissement= Tk()
        avertissement.title("Avertissement")
        texte=Label(avertissement)
        texte["text"]="Attention : etape maximale atteinte"
        texte.pack(padx=20,pady=20)
        ferme = Button(avertissement, text ='OK', font=("Arial",15),command = avertissement.destroy)
        ferme.pack(side=BOTTOM,padx=11, pady=11)
        avertissement.mainloop()
    else:
        if etape >= etapes_faites:
            a=reperes_seg[etapes_faites]
            segments2=ajout_etape(segments[a::])
            segments=segments+segments2
            etapes_faites=etapes_faites+1
        if dessin_etapes.get()==False:
            dessin.delete(ALL)
        a=reperes_seg[etape+1]    
        etape=etape+1
        b=reperes_seg[etape+1]
        dessine(segments[a:b])

def precedent():
    global segments, etape, reperes_seg, etapes_faites
    if etape <= 0:
        avertissement= Tk()
        avertissement.title("Avertissement")
        texte=Label(avertissement)
        texte["text"]="Attention : etape minimale atteinte"
        texte.pack(padx=20,pady=20)
        ferme = Button(avertissement, text ='OK', font=("Arial",15),command = avertissement.destroy)
        ferme.pack(side=BOTTOM,padx=11, pady=11)
        avertissement.mainloop()
    else:
        dessin.delete(ALL)
        b=reperes_seg[etape]    
        etape=etape-1
        a=reperes_seg[etape]
        if dessin_etapes.get()==False:
            dessine(segments[a:b])
        else:
            dessine(segments[0:b])

        
# ouverture fenetre graphique 
fenetre = Tk()
fenetre.title("Generateur de fractales")

gauche=Frame(fenetre)
gauche.pack(expand=0,padx=10,pady=10,side=LEFT)
dessin=Canvas(gauche, background="white", width =1000, height =500, borderwidth=3, relief="raised")
dessin.pack(expand=0,padx=15,pady=15,side=TOP)

boutons=Frame(gauche)
boutons.pack(expand=0,padx=15,pady=15,side=BOTTOM)
dessin_etapes=BooleanVar()
check_etapes=Checkbutton(boutons, text="Laisser dessin etapes precedentes", variable=dessin_etapes).pack(padx=5,pady=5,side=LEFT)
bouton_suivant=Button(boutons, text="Etape suivante", command=suivant).pack(padx=5,pady=5,side=RIGHT)
bouton_precedent=Button(boutons, text="Etape precedente", command=precedent).pack(padx=5,pady=5,side=RIGHT)

droite=Frame(fenetre)
droite.pack(expand=0,padx=10,pady=10,side=RIGHT,fill=Y)
interface=LabelFrame(droite,text="Exemples",background="grey")
interface.pack(expand=0,padx=15,pady=15,side=TOP)
choix_arbre=Button(interface, text="Un arbre",command=arbre).pack(padx=10,pady=10,side=TOP)
choix_foret=Button(interface, text="Une foret",command=foret).pack(padx=10,pady=10,side=TOP)
choix_dragon=Button(interface, text="Le dragon",command=dragon).pack(padx=10,pady=10,side=TOP)
choix_flocon=Button(interface, text="Le flocon de Von Koch",command=flocon).pack(padx=10,pady=10,side=TOP)
choix_tapis=Button(interface, text="Le tapis de Sierpinskii",command=tapis).pack(padx=10,pady=10,side=TOP)

BoutonQuitter = Button(droite, text ='Quitter', font=("Arial",15),command = fenetre.destroy)
BoutonQuitter.pack(side=BOTTOM,padx=10, pady=50)

dessine(segments)


fenetre.mainloop()
