Le centre du cercle retrouvé par napoléon !


Description

Le code a pour objet de résoudre un problème classique de géométrie : retrouver le centre perdu d'un cercle en n'utilisant que le compas.
Dans la fenêtre on fait apparaître :
- un plan vert sombre dans lequel va se faire progressivement la construction géométrique
- un panneau de commande avec les boutons permettant de créer successivement les divers cercles

Un menu "pop-up" fonctionne également avec le clic droit de la souris; il comporte en plus la "PRESENTATION DU SCRIPT" et une rubrique "A propos".
A signaler enfin un widget "Scale" pour aumenter ou diminuer la dimension de la fenêtre et l'adapter ainsi à la taille de lécran de l'utilisateur.

Source / Exemple :


#########################
#! /usr/bin/env python 
# -*- coding: Latin-1 -*- 
# Python version 2.5a1
# Tk version 8.4 
# IDLE version 1.2a1

#########################################################

# <<< Le centre du cercle retrouvé par NAPOLEON >>> 

#   ( version 3 ) 

#  PRESENTATION du script : voir le texte de la fonction <<rahxephon>> ci-dessous

#########################################################

from Tkinter import* 
from math import *
from tkMessageBox import askokcancel

def pop_up(event=None) :
    " menu pop-up au clic droit de la souris"
    frame = Frame(root, relief=RIDGE)
    entry = Entry(frame, width = '21')
    menu = Menu(entry, tearoff = 0)
    menu.add_command(label ='Présentation du script', underline =0,command = rahxephon)
    menu.add_separator()
    menu.add_command(label ='cercle (O)', underline =0,command = cercle_c)
    menu.add_command(label ='Points A & B', underline =0,command = points_A_B)
    menu.add_command(label ='cercle (A)', underline =0,command = cercle_c1)
    menu.add_command(label ='cercles (B) & (C)', underline =0,command = cercles_c2_c3)
    menu.add_command(label ='cercle (D)', underline =0,command = cercle_c4)
    menu.add_command(label ='cercles (E) & (F)', underline =0,command = cercles_c5_c6)
    menu.add_separator()
    menu.add_command(label ='Quitter le jeu !', underline =0,command = quitter)
    menu.add_separator()
    menu.add_command(label ='A propos', underline =0,command = hack_sing)
    ycoord = entry.winfo_pointery()
    xcoord = entry.winfo_pointerx()
    menu.tk_popup(xcoord, ycoord)

def naruto_1(event=None) :
    global f,L,H, RO,xO,yO,xA,xB
    n=ss.get()
    f=int(n)
    L,H=90*f,60*f 
    RO,xO,yO,xA,xB=15*f,45*f,30*f,54*f,56*f
    can.configure(height=H,width=L)

def naruto_2 () :
  global flagi
  if flagi ==0: flagi = 1 ; root.title(texto1) 
  elif flagi ==1: flagi = 2 ; root.title(texto2) 
  elif flagi ==2: flagi = 3 ; root.title(texto3) 
  elif flagi ==3: flagi = 4 ; root.title(texto4) 
  elif flagi ==4: flagi = 5 ; root.title(texto5) 
  elif flagi ==5: flagi = 6 ; root.title(texto6) 
  elif flagi ==6: flagi = 7 ; root.title(texto7) 
  elif flagi ==7: flagi = 8 ; root.title(texto8) 
  elif flagi ==8: flagi = 9 ; root.title(texto9) 
  elif flagi ==9: flagi = 0 ; root.title(texto10) 
  root.after(500,naruto_2)            

def rahxephon():
    global fen1
    fen1=Tk()
    fen1.configure (bg='grey100')
    fen1.geometry("%sx%s+0+0"%(root.winfo_screenwidth(),root.winfo_screenheight()))
    fen1.overrideredirect(TRUE)
    Label(fen1,text="""\n\n\n
    PRESENTATION

    (extrait d'un article du journal Le Monde 23-30 septembre 2003)

    Sans doute savez vous facilement retrouver le centre d'un cercle avec une règle et un compas, ... et oui tracer une médiatrice demande un compas !
    Hilbert a montré que l'on ne pouvait pas le retrouver avec seulement une règle.

    Pour le retrouver avec uniquement un compas, c'est en 1797 que l'on voit apparaître Napoléon.
    Même pour les mathématiques l'empereur, c'est affaire de légende ...
    Sur une plage de l'île de beauté Napoléon équipé d'un simple compas (à défaut d'épuisette), traça un cercle (d'un trait continu).
    Quand il revint quelques minutes plus tard, le centre avait disparu. Sans s'émouvoir, et bien qu'ayant perdu l'ouverture du compas qui lui avait permis de tracer le cercle,
    l'empereur retrouva son centre, sous le regard admiratif de son entourage.
    Est-ce à ce propos que Lagrange aurait dit : " Mon Général, nous nous attendions à tout de vous, sauf à des leçons de géométrie " ?
    Autre version moins romantique : lors de la campagne d'Italie il rencontra Mascheroni, spécialiste de la géométrie du compas.
    De retour en France, il exposa à l'Académie des Sciences les résultats de ce mathématicien ainsi qu'une solution personnelle de ce problème trouvée avec son aide.

    CONSTRUCTION

    A et B sont deux points sur le cercle initial (c) dont on a perdu le centre O.
    Étape 1 : tracer le cercle (c1) de centre A passant par B. Ce cercle coupe aussi (c) en C.
    Étape 2 : tracer les cercles (c2) et (c3) de centres B et C passant par A. Ces deux derniers cercles se recoupent en D.
    Étape 3 : tracer le cercle (c4) de centre D passant par A.
    Étape 4: le cercle (c4) coupe (c1) en E et F.
    Étape 5: les cercles (c5) et (c6) de centres E et F passant par A se recoupent en O, centre retrouvé du cercle (c).
""",bg='grey100',fg='dark blue',font='Arial 12 bold',justify=LEFT).pack()
    Button(fen1,text='OK',command=fen1.destroy).pack()
    fen1.mainloop()

def hack_sing():
    global fen
    fen=Tk()
    fen.configure (bg='grey0')
    fen.geometry("%sx%s+0+0"%(root.winfo_screenwidth(),root.winfo_screenheight()))
    fen.overrideredirect(TRUE)
    Label(fen,text="""\n\n\n\n
By HCD

autres sources déposées sur le site :

Billard français
Collisions en cascade ... plus d'une centaine de boules s'entrechoquent
Collisions en 3D avec visualpython
Un serpent PYTHON ... pas comme les autres 
Cercle et droite d'Euler animés dans un triangle
""",bg='grey0',fg='grey100',font='Arial 30 bold',justify=LEFT).pack()
    Button(fen,text='OK',font='Arial 10 bold',command=fen.destroy).pack()
    fen.mainloop()

def cercle_c(): 
    "dessin du cercle de départ de centre O et  de rayon RO"
    global R,dR
    ss.configure(state=DISABLED)
    can.delete(ALL)
    if R<RO:
        R=R+dR
        c=can.create_oval(xO-R,yO-R,xO+R,yO+R,outline="red",width=1)
        can.after(1,cercle_c)
    else:
        R=RO
        c=can.create_oval(xO-R,yO-R,xO+R,yO+R,outline="red",width=2)
        B1.configure(state=DISABLED);B2.configure(state=NORMAL)
    texte="Mise en place du cercle C (rouge)\ndont on recherche le centre (O)"
    information.config(text=texte)
    
def points_A_B():
    "mise en place de deux points quelconques A & B sur le cercle de départ"
    global yA,yB
    yA=yO+sqrt(R*R-(xA-xO)*(xA-xO))
    yB=yO-sqrt(R*R-(xB-xO)*(xB-xO))
    cercle_A=can.create_oval(xA-8,yA-8,xA+8,yA+8,fill="red",width=1)
    cercle_B=can.create_oval(xB-8,yB-8,xB+8,yB+8,fill="red",width=1)
    lettre_A=can.create_text(xA,yA,text="A",fill="white",font='Arial 8')
    lettre_B=can.create_text(xB,yB,text="B",fill="white",font='Arial 8')
    B2.configure(state=DISABLED);B3.configure(state=NORMAL)
    texte="A & B sont deux points quelconques\nchoisis sur le cercle rouge"
    information.config(text=texte)
    
def cercle_c1(): 
    "dessin du cercle c1 de centre A et de rayon AB"
    global R1,dR1
    can.delete(ALL)
    a=hypot(xB-xA,yB-yA)
    c=can.create_oval(xO-R,yO-R,xO+R,yO+R,outline="red",width=1)
    points_A_B()
    if R1<a:
        R1=R1+dR1
        c1=can.create_oval(xA-R1,yA-R1,xA+R1,yA+R1,outline="light blue",width=1)
        B3.configure(state=DISABLED)
        can.after(1,cercle_c1)
    else:
        R1=a
        c1=can.create_oval(xA-R1,yA-R1,xA+R1,yA+R1,outline='#007030',width=1)
        points_A_B();point_C()
        B3.configure(state=DISABLED); B4.configure(state=NORMAL)
    texte="Le cercle bleu clair de centre A passant\npar B coupe le cercle rouge en C"
    information.config(text=texte)

def point_C(): 
    "le point C est à l'intersection du cercle rouge et du cercle c1"
    global xC,yC,p
    p=(yA-yO)/(xA-xO)
    x,y=(xB+p*p*xO+p*(yB-yO))/(1+p*p),(p*(xB-xO)+p*p*yB+yO)/(1+p*p)
    xC,yC=2*x-xB,2*y-yB
    cercle_A=can.create_oval(xC-8,yC-8,xC+8,yC+8,fill="light blue",width=1)
    lettre_A=can.create_text(xC,yC,text="C",fill="black",font='Arial 8')
   
def cercles_c2_c3(): 
    "dessin des cercles c2  & c3 de centre B & C et de même rayon égal à AB"
    global R23,dR23,a
    can.delete(ALL)
    a=hypot(xB-xA,yB-yA)
    c=can.create_oval(xO-R,yO-R,xO+R,yO+R,outline="red",width=1)
    c1=can.create_oval(xA-R1,yA-R1,xA+R1,yA+R1,outline='#007030',width=1)
    points_A_B();point_C()
    if R23<a:
        R23=R23+dR23
        c2=can.create_oval(xB-R23,yB-R23,xB+R23,yB+R23,outline="yellow",width=1)
        c3=can.create_oval(xC-R23,yC-R23,xC+R23,yC+R23,outline="yellow",width=1)
        B3.configure(state=DISABLED);B4.configure(state=DISABLED)
        can.after(1,cercles_c2_c3)
    else:
        R23=a
        c2=can.create_oval(xB-R23,yB-R23,xB+R23,yB+R23,outline='#007030',width=1)
        c3=can.create_oval(xC-R23,yC-R23,xC+R23,yC+R23,outline='#007030',width=1)
        points_A_B(); point_C();point_D()
        B3.configure(state=DISABLED);B4.configure(state=DISABLED);B5.configure(state=NORMAL)
    texte="Le point D est à l'intersection des cercles\njaunes de centre B & C passant par A"
    information.config(text=texte)

def point_D(): 
    "le point D est à l'intersection de c2 & c3"
    global xD,yD
    xD,yD=xC+xB-xA,yC+yB-yA
    cercle_D=can.create_oval(xD-8,yD-8,xD+8,yD+8,fill="yellow",width=1)
    lettre_A=can.create_text(xD,yD,text="D",fill="black",font='Arial 8')

def cercle_c4(): 
    "dessin du cercle c4 de centre D et de rayon DA"
    global R4,dR4
    b=hypot(xD-xA,yD-yA)
    can.delete(ALL)
    c=can.create_oval(xO-R,yO-R,xO+R,yO+R,outline="red",width=1)
    c1=can.create_oval(xA-R1,yA-R1,xA+R1,yA+R1,outline="light blue",width=1)
    c2=can.create_oval(xB-R23,yB-R23,xB+R23,yB+R23,outline='#007030',width=1)
    c3=can.create_oval(xC-R23,yC-R23,xC+R23,yC+R23,outline='#007030',width=1)
    points_A_B();point_C();point_D()
    if R4<b:
        R4=R4+dR4
        c4=can.create_oval(xD-R4,yD-R4,xD+R4,yD+R4,outline="pink",width=1)
        B3.configure(state=DISABLED);B5.configure(state=DISABLED)
        can.after(1,cercle_c4)
    else:
        R4=b
        c1=can.create_oval(xA-R1,yA-R1,xA+R1,yA+R1,outline='#007030',width=1)
        c4=can.create_oval(xD-R4,yD-R4,xD+R4,yD+R4,outline='#007030',width=1)
        points_A_B();point_C();point_D();point_E_F()
        B3.configure(state=DISABLED);B5.configure(state=DISABLED);B6.configure(state=NORMAL)
    texte="Les points E & F sont à l'intersection\ndu cercle bleu clair et du cercle rose\nde centre D"
    information.config(text=texte)

def point_E_F(): 
    "les points E & F sont à l'intersection de c5 & c5 et c1"
    global xE,yE,xF,yF
    xM,yM=(xO+xA)/2,(yO+yA)/2
    P=1+1/p/p
    Q=xA+xM/p/p+(yM-yA)/p
    S=xA*xA+(yM-yA)*(yM-yA)+2*(yM-yA)*xM/p+xM*xM/p/p-a*a
    DELTA=Q*Q-P*S
    xE=(Q+sqrt(DELTA))/P
    yE=yM-(xE-xM)/p
    xF=(Q-sqrt(DELTA))/P
    yF=yM-(xF-xM)/p
    cercle_E=can.create_oval(xE-8,yE-8,xE+8,yE+8,fill="pink",width=1)
    lettre_E=can.create_text(xE,yE,text="E",fill="black",font='Arial 8')
    cercle_F=can.create_oval(xF-8,yF-8,xF+8,yF+8,fill="pink",width=1)
    lettre_F=can.create_text(xF,yF,text="F",fill="black",font='Arial 8')

def cercles_c5_c6(): 
    "dessin des cercles c5  & c6 de centre E & F et de même rayon égal à EO"
    global R56,dR56
    b=hypot(xD-xA,yD-yA)
    can.delete(ALL)
    c=can.create_oval(xO-R,yO-R,xO+R,yO+R,outline="red",width=2)
    c1=can.create_oval(xA-R1,yA-R1,xA+R1,yA+R1,outline='#007030',width=1)
    c2=can.create_oval(xB-R23,yB-R23,xB+R23,yB+R23,outline='#007030',width=1)
    c3=can.create_oval(xC-R23,yC-R23,xC+R23,yC+R23,outline='#007030',width=1)
    c4=can.create_oval(xD-R4,yD-R4,xD+R4,yD+R4,outline='#007030',width=1)
    points_A_B();point_C();point_D();point_E_F()
    if R56<a:
        R56=R56+dR56
        c5=can.create_oval(xE-R56,yE-R56,xE+R56,yE+R56,outline="white",width=1)
        c6=can.create_oval(xF-R56,yF-R56,xF+R56,yF+R56,outline="white",width=1)
        B3.configure(state=DISABLED);B6.configure(state=DISABLED)
        can.after(1,cercles_c5_c6)
    else:
        R56=a
        c5=can.create_oval(xE-R56,yE-R56,xE+R56,yE+R56,outline='#007030',width=1)
        c6=can.create_oval(xF-R56,yF-R56,xF+R56,yF+R56,outline='#007030',width=1)
        points_A_B();point_C();point_D();point_E_F()
        cercle_OO=can.create_oval(xO-15,yO-15,xO+15,yO+15,fill="red",width=1)
        cercle_O=can.create_oval(xO-10,yO-10,xO+10,yO+10,fill="white",width=1)
        lettre_O=can.create_text(xO,yO,text="O",fill="black",font='Arial 8')
        B1.configure(state=NORMAL);B3.configure(state=DISABLED);B6.configure(state=DISABLED)
        ss.configure(state=NORMAL)
    texte="Le centre O recherché est à l'intersection\ndes cercles de centres E & F passant par A"
    information.config(text=texte)

def quitter():
    ans=askokcancel('',"Voulez-vous réellement quitter ?")
    if ans:root.quit()

######## Programme principal ############################################ 

root = Tk() 

texto1='|    Le centre du cercle retrouvé par NAPOLEON     |    By HCD '
texto2='  |    Le centre du cercle retrouvé par NAPOLEON     |    By HCD'
texto3='    |    Le centre du cercle retrouvé par NAPOLEON     |    By HCD'
texto4='      |    Le centre du cercle retrouvé par NAPOLEON     |    By HCD'
texto5='        |    Le centre du cercle retrouvé par NAPOLEON     |    By HCD'
texto6='          |    Le centre du cercle retrouvé par NAPOLEON     |    By HCD'
texto7='            |    Le centre du cercle retrouvé par NAPOLEON     |    By HCD'
texto8='              |    Le centre du cercle retrouvé par NAPOLEON     |    By HCD'
texto9='                 |    Le centre du cercle retrouvé par NAPOLEON     |    By HCD'
texto10='                  |    Le centre du cercle retrouvé par NAPOLEON     |    By HCD'
flagi =1
naruto_2()

root.bind('<Button-3>',pop_up)
root.bind('<Alt-F12>',pop_up)# commande au clavier du menu pop-up

# données initiales: 
flag=0
f=1
L,H=900*f,600*f # largeur  et hauteur du plan 
RO=150*f
xO,yO,xA,xB=450*f,300*f,540*f,560*f
R,R1,R23,R4,R56=0,0,0,0,0
dR,dR1,dR23,dR4,dR56=1,0.2,0.2,0.2,0.2

can=Canvas(root,bg='dark green',height=H,width=L) 
can.grid(row=1,column=0,rowspan=2) 
can2=Canvas(root,bg='brown',highlightbackground='brown') 
can2.grid(row=1,column=1,sticky=N) 
#img=PhotoImage(file='transdove.gif')
#can.create_image(400*f,300*f,image=img)
information=Label(can2,text="",height=16*f,width=36,relief=GROOVE,bg="brown",fg="white",justify=LEFT,command=None) 
information.pack(padx=4,pady=4,side=BOTTOM,anchor=SW) 
B7=Button(can2,text='Quitter',height=1,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=quitter)
B7.pack(padx=4,pady=4,side=BOTTOM,anchor=SW) 
B6=Button(can2,text='cercles (E) & (F)',height=1,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=cercles_c5_c6)
B6.pack(padx=4,pady=4,side=BOTTOM,anchor=SW) 
B5=Button(can2,text='cercle (D)',height=1,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=cercle_c4)
B5.pack(padx=4,pady=4,side=BOTTOM,anchor=SW) 
B4=Button(can2,text='cercles (B) & (C)',height=1,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=cercles_c2_c3)
B4.pack(padx=4,pady=4,side=BOTTOM,anchor=SW) 
B3=Button(can2,text='cercle (A)',height=1,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=cercle_c1)
B3.pack(padx=4,pady=4,side=BOTTOM,anchor=SW) 
B2=Button(can2,text='Points A & B',height=1,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=points_A_B)
B2.pack(padx=4,pady=4,side=BOTTOM,anchor=SW) 
B1=Button(can2,text='cercle (O)',height=1,width=35,relief=GROOVE,bg="white",activebackground="dark green",activeforeground="white",command=cercle_c)
B1.pack(padx=4,pady=4,side=BOTTOM,anchor=SW)
B1.configure(state=NORMAL);B2.configure(state=DISABLED);B3.configure(state=DISABLED);B4.configure(state=DISABLED);B5.configure(state=DISABLED);B6.configure(state=DISABLED)
ss=Scale(length=215,orient=HORIZONTAL,sliderlength=11,from_ =4,to=15,showvalue=10,label="Dimensionner la fenêtre    (entre 4 et 15)",command=naruto_1)
ss.grid(row=0,column=0,padx=4,pady=4)
ss.set(8)
root.config(bg="brown") 
root.mainloop() 
root.destroy()

Conclusion :


Si cette source vous parait intéressante, n'hésitez pas à me le dire, car les sujets en math ne manquent pas !

Codes Sources

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.