Bibm@th

Forum de mathématiques - Bibm@th.net

Bienvenue dans les forums du site BibM@th, des forums où on dit Bonjour (Bonsoir), Merci, S'il vous plaît...

Vous n'êtes pas identifié(e).

#1 06-03-2018 13:09:45

gbrinon
Membre
Inscription : 06-03-2018
Messages : 2

Inscrire N cercles égaux dans un cercle

Bonjour,

Je suis sur le développement d'un jeu de type civilization et je bute sur un problème au niveau de l'affichage d'unités de combat. En effet, si on considère qu'une armée occupe une case (hexagonale mais assimilable à un cercle dans notre problème) et que cette "armée" est constituée de 8 personnages, il faut, pour que ce soit un minimum joli, répartir les personnages de manière régulière dans le carcle qui constitue la case où ils sont. Là où ça se corse un peu, c'est que j'ai pris 8 comme exemple mais durant le durée de vie de l'unité, on peut imaginer voir le nombre de personnages qui la constitue varier et les positionnements s'adapter.

En y réfléchissant un peu, j'ai l'impression que mon problème se présente de la manière suivante en fait :
Si je souhaite inscrire N cercles de taille égales dans un cercle, comment définir la taille de ces cercles et surtout ce qui m'intéresse, où seront les centres par rapport au centre du "grand cercle ?

Je ne suis pas une super flèche en mathématiques, je ne sais même pas si c'est un problème compliqué ou pas.

Merci d'avance pour vos réponses :)

Bonne journée

Hors ligne

#2 07-03-2018 07:47:03

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 946

Re : Inscrire N cercles égaux dans un cercle

Bonjour,

Bienvenue chez nous...
Non, ton problème n'est pas si simple.
J'y ai réfléchi hier soir.
Ton problème se ramène donc à cette problématique :
étant donné un cercle dont on connaît centre et rayon, tu veux pouvoir inscrire dans ce cercle n petits cercles dont les cercles seront équidistants.
D'accord ?
* Veux-tu que ces cercles soient tangents deux par deux, et que chacun soit tangent intérieurement au grand cercle ?
  (Je vais essayer de construire un dessin)
* Veux-tu que ces cercles soient tangents entre eux mais répartis au mieux dans la surface du disque ?

De toutes façons, tu dois bien être conscient que plus n est grand, plus le rayon des petits cercles va être petit et que ça risque de ne pas être très beau... D'où ma deuxième question ci-dessus.
Peut-être même faut-il envisager un mix des deux et à partir d'un certain n, ajouter des cercles plus près vers le centre ?
Sinon qu'entends-tu par
on peut imaginer voir le nombre de personnages qui la constitue varier et les positionnements s'adapter. ?

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#3 08-03-2018 22:27:53

tibo
Membre expert
Inscription : 23-01-2008
Messages : 1 097

Re : Inscrire N cercles égaux dans un cercle

Salut,

J'ai réfléchi à ton problème et j'ai trouvé une solution générale pour placer $n$ petits cercles tangents entre eux et au grand cercle.

Soit un (grand) cercle de centre $O$ et de rayon $R$.
Soit $n$ le nombre de petits cercles à inscrire dedans de rayon $x$.
Tous les centres de ces petits cercles sont sur un cercle de centre $O$ et de rayon $y$.
On cherche à exprimer $x$ et $y$ en fonction de $R$ et $n$.

shéma

h0xb.png

On a immédiatement $x+y\ =\ R$.
Et la formule des sinus nous donne $\dfrac{2x}{\sin\left(\frac{2\pi}{n}\right)}\ =\ \dfrac{y}{\sin\left(\frac{(n-2)\pi}{2n}\right)}$

Ce qui nous donne $\left\{\begin{array}{lll}
x & = & R\dfrac{\sin\left(\frac{2\pi}{n}\right)}{2\sin\left(\frac{(n-2)\pi}{2n}\right)+\sin\left(\frac{2\pi}{n}\right)} \\
y & = & R-x \\
& = & R\dfrac{\sin\left(\frac{(n-2)\pi}{2n}\right)}{2\sin\left(\frac{(n-2)\pi}{2n}\right)+\sin\left(\frac{2\pi}{n}\right)} \\
\end{array}\right.$

Ceci nous donne directement les coordonnées polaires des centres de chaque petit cercle.
Il suffit de repasser en coordonnées cartésiennes pour les placer facilement.

Je code de ce pas un petit script Python pour visualiser ça un peu mieux.



Il reste cependant un problème de taille : Ma solution n'est pas optimale du tout !
En effet, caser tous les petits cercles autour laisse beaucoup de place au centre.
Notamment, à partir de $n=6$, on a la place de mettre un 7ième centre.
Je réfléchie encore comment calculer le nombre de cercle que l'on peut mettre au centre en fonction de $n$...

[edit2] Pour résoudre ce problème, il est possible de récupérer le rayon du disque vide central et de calculer le nombre de petits cercles que l'on peut mettre dedans.
À la main ça me semble fastidieux, mais Python devrait pouvoir faire ça...
Enfin ça complique pas mal le code...



[edit]

Python


##### Import #####

#from Tkinter import *   # Python 2.x
from tkinter import *  # Python 3.x
from math import *


##### Fonctions #####

def coordPolaireToCarte(theta, r):
    """Convertie des coordonnées polaires en coordonnées cartésiennes."""
    x = r*cos(theta)
    y = r*sin(theta)
    return [x,y]

def cercle(can, x, y, r, col="white"):
    """Trace dans le Canvas can un cercle de centre (x,y), de rayon r et de couleur col."""
    return can.create_oval(x-r, y-r, x+r, y+r, fill=col)

def nUp():
    cer.nUp()
    nbText.config(text="Nombre de petits cercles : %s"%(cer.n))

def nDown():
    cer.nDown()
    nbText.config(text="Nombre de petits cercles : %s"%(cer.n))


##### Classes #####

class CerclesTangents():
    """Des cercles !"""
    def __init__(self, boss):
        """Constructeur de la classe CerclesTangent."""
        # général
        self.boss = boss                # Canvas dans lequel on va dessiner

        # grand cercle
        self.r = 400
        self.xO = 450
        self.yO = 450
        self.gdCercle = cercle(self.boss, self.xO, self.yO, self.r)

        # petits cercles
        self.nMax = 20
        self.n = 1
        self.ptCercle = [cercle(self.boss, self.xO, self.yO, self.r, col="cyan")]

        #self.tracer()


    def nUp(self):
        """Augmente le nombre de petits cercles de 1."""
        if self.n < self.nMax:
            self.n = self.n+1

    def nDown(self):
        """Diminue le nombre de petits cercles de 1."""
        if self.n > 1:
            self.n = self.n-1

    def tracer(self):
        # Suppression de tous les petits cerlces précédents
        for c in self.ptCercle:
            self.boss.delete(c)
        self.ptCercle = []

        # Cas particulier pour n=1 et n=2
        if self.n==1:
            self.ptCercle = [cercle(self.boss, self.xO, self.yO, self.r, col="cyan")]
        elif self.n==2:
            self.ptCercle = [cercle(self.boss, self.xO+self.r/2, self.yO, self.r/2, col="cyan"),
                             cercle(self.boss, self.xO-self.r/2, self.yO, self.r/2, col="cyan")]

        # Cas général
        else:
            # Calcul des rayons
            n = self.n
            r = self.r
            x = r * sin(2*pi/n) / (2*sin((n-2)*pi/(2*n)) + sin(2*pi/n))
            y = r-x

            # Ajout des nouveaux petits cercles
            for k in range(n):
                theta = k*2*pi/n
                centre = coordPolaireToCarte(theta ,y)
                self.ptCercle.append(cercle(self.boss, centre[0]+self.xO, centre[1]+self.yO, x, "cyan"))


##### Main #####

if __name__=="__main__":
    # fenetre
    root = Tk()
    root.title("Des cercles")
    # Canvas
    can = Canvas(root, width=900, height=900, bg="white")
    can.grid(row=0,column=0, rowspan=100)
    # Cercle
    cer = CerclesTangents(can)

    # Paramètres
    nbText = Label(root, text="Nombre de petits cercles : %s"%(cer.n))
    nbText.grid(row=0, column=1)
    Button(root, text="+", comman=nUp).grid(row=1, column=1)
    Button(root, text="-", comman=nDown).grid(row=2, column=1)
    Button(root, text="Afficher", command=cer.tracer).grid(row=3, column=1)

    # C'est parti !
    root.mainloop()
 

Dernière modification par tibo (09-03-2018 11:00:29)


A quoi sert une hyperbole?
----- A boire de l'hypersoupe pardi !

Hors ligne

#4 09-03-2018 07:55:01

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 946

Re : Inscrire N cercles égaux dans un cercle

Salut,

Bravo.
Un détail dans ton code...
Si pour Python 3.x tu écris : from Tkinter import *
tu recevras le message d'erreur suivant :
    from Tkinter import *   # Python 3.x
ImportError: No module named 'Tkinter'

C'est tkinter avec minuscule... là, ça marche et c'est chouette !
Effectivement  pour la place au centre, j'ai vu ça hier avec mes dessins.

J'y ai réfléchi un peu, je vais pouvoir m'y remettre : je boucle ma revue trimestrielle aujourd'hui...
J'avais déjà traité une problématique voisine avec dessins et calculs sur le forum : j'ai été incapable de la retrouver !

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#5 09-03-2018 11:00:02

tibo
Membre expert
Inscription : 23-01-2008
Messages : 1 097

Re : Inscrire N cercles égaux dans un cercle

Salut,

Ha oui c'est l'inverse. C'est sur la version 2.x qu'il faut mettre une majuscule.
Je corrige ça.


[edit] Petite amélioration du script avec la possibilité de faire une deuxième couronne.
Mais il reste encore de la place au milieu !
Je teste des trucs pour faire plus de couronnes automatiquement mais pour l'instant c'est vraiment trop bourrin et j'aime pas ça.

Texte caché


##### Import #####

#from Tkinter import *   # Python 2.x
from tkinter import *  # Python 3.x
from math import *


##### Fonctions #####

def coordPolaireToCarte(theta, r):
    """Convertie des coordonnées polaires en coordonnées cartésiennes."""
    x = r*cos(theta)
    y = r*sin(theta)
    return [x,y]

def cercle(can, x, y, r, col="white"):
    """Trace dans le Canvas can un cercle de centre (x,y), de rayon r et de couleur col."""
    return can.create_oval(x-r, y-r, x+r, y+r, fill=col)

def nUp():
    cer.nUp()
    nbText.config(text="Nombre de petits cercles : %s"%(cer.n))

def nDown():
    cer.nDown()
    nbText.config(text="Nombre de petits cercles : %s"%(cer.n))


##### Classes #####

class CerclesTangents():
    """Un canvas pour tracer des cercles."""
    def __init__(self, boss):
        """Constructeur de la classe CanvasCerclesTangent."""
        ## général
        self.boss = boss                ## Canvas dans lequel on va dessiner

        ## grand cercle
        self.r = 400
        self.xO = 450
        self.yO = 450
        self.gdCercle = cercle(self.boss, self.xO, self.yO, self.r)

        ## petits cercles
        self.nMax = 50
        self.n = 1
        self.x = self.r             ## rayon des petits cercles
        self.y = self.r-self.x      ## rayon du cercle des centres des petits cercles exterieurs
        self.ptCercle = []

        ## cercles intérieurs
        self.cerclePalier = [0, 6, 8, 10, 14, 22, 38, 100]       ## paliers pour lesquels le nombre de cercles interieurs change
        self.cercleExter = 1
        self.cercleInter = self.n-self.cercleExter

    def nUp(self):
        """Augmente le nombre de petits cercles de 1."""
        if self.n < self.nMax:
            self.n = self.n+1

    def nDown(self):
        """Diminue le nombre de petits cercles de 1."""
        if self.n > 1:
            self.n = self.n-1

    def supprimer(self):
        """Supprime tous les petits cercles."""
        for c in self.ptCercle:
            self.boss.delete(c)
        self.ptCercle = []

    def calculs(self):
        """Effectue tous les calculs necessaires au tracer."""
        ## Calcul du nombre de cercles interieurs et exterieurs
        i=0
        while self.n>=self.cerclePalier[i+1]:
            i = i+1
        if i==0:
            self.cercleExter = self.n
            self.cercleInter = 0
        else:
            self.cercleExter = self.cerclePalier[i]
            self.cercleInter = self.n-self.cercleExter

        ## Calcul des rayons
        if self.cercleExter==1:
            self.x = self.r
            self.y = 0
        elif self.cercleExter==2:
            self.x = self.r/2
            self.y = self.r/2
        else:
            n = self.cercleExter        ## Simplification des notations
            r = self.r
            self.x = r * sin(2*pi/n) / (2*sin((n-2)*pi/(2*n)) + sin(2*pi/n))
            self.y = r-self.x

    def dessinerCercle(self, n, x, y):
        """Dessine n cercles de rayon x dont les centres sont sur un cercle de rayon y."""
        ## Cas particulier pour n=1 et n=2
        if n==1:
            self.ptCercle.append(cercle(self.boss, self.xO, self.yO, x, col="cyan"))
        elif self.n==2:
            self.ptCercle.append(cercle(self.boss, self.xO+y, self.yO, x, col="cyan"))
            self.ptCercle.append(cercle(self.boss, self.xO-y, self.yO, x, col="cyan"))
        ## Cas général
        else:
            for k in range(n):
                theta = k*2*pi/n
                centre = coordPolaireToCarte(theta ,y)
                self.ptCercle.append(cercle(self.boss, centre[0]+self.xO, centre[1]+self.yO, x, "cyan"))

    def dessinerTout(self):
        """Dessine la figure."""
        ## Suppression de tous les petits cerlces précédents
        self.supprimer()

        ## Calculs
        self.calculs()
        #print(self.n, self.cercleExter, self.cercleInter, "/", self.x, self.y)

        ## Dessin
        self.dessinerCercle(self.cercleExter, self.x, self.y)
        if self.cercleInter>0:
            self.dessinerCercle(self.cercleInter, self.x, self.y-2*self.x)

##### Main #####

if __name__=="__main__":
    ## fenetre
    root = Tk()
    root.title("Des cercles")
    ## Canvas
    can = Canvas(root, width=900, height=900, bg="white")
    can.grid(row=0,column=0, rowspan=100)
    ## Cercle
    cer = CerclesTangents(can)

    ## Paramètres
    nbText = Label(root, text="Nombre de petits cercles : %s"%(cer.n))
    nbText.grid(row=0, column=1)
    Button(root, text="+", comman=nUp).grid(row=1, column=1)
    Button(root, text="-", comman=nDown).grid(row=2, column=1)
    Button(root, text="Afficher", command=cer.dessinerTout).grid(row=3, column=1)

    # C'est parti !
    root.mainloop()
 

Dernière modification par tibo (09-03-2018 12:14:16)


A quoi sert une hyperbole?
----- A boire de l'hypersoupe pardi !

Hors ligne

#6 09-03-2018 20:12:57

tibo
Membre expert
Inscription : 23-01-2008
Messages : 1 097

Re : Inscrire N cercles égaux dans un cercle

Re,

Toujours pas optimal, mais il y a plusieurs couronnes...

Python


##### Import #####

#from Tkinter import *   # Python 2.x
from tkinter import *  # Python 3.x
from math import *
import time


##### Fonctions #####

def coordPolaireToCarte(theta, r):
    """Convertie des coordonnées polaires en coordonnées cartésiennes."""
    x = r*cos(theta)
    y = r*sin(theta)
    return [x,y]

def cercle(can, x, y, r, col="white"):
    """Trace dans le Canvas can un cercle de centre (x,y), de rayon r et de couleur col."""
    return can.create_oval(x-r, y-r, x+r, y+r, fill=col)

def nUp():
    cer.nUp()
    nbText.config(text="Nombre de petits cercles : %s"%(cer.n))

def nDown():
    cer.nDown()
    nbText.config(text="Nombre de petits cercles : %s"%(cer.n))

def nUp10():
    for i in range(10):
        nUp()

def nDown10():
    for i in range(10):
        nDown()

def nUp100():
    for i in range(100):
        nUp()

def nDown100():
    for i in range(100):
        nDown()

def go():
    global okGo
    okGo = 1
    while okGo==1 and cer.n<10000:
        cer.dessinerTout()
        root.update()
        nUp()
        time.sleep(5/cer.n)
    ekGo=0

def stop():
    global okGo
    okGo = 0

##### Classes #####

class CerclesTangents():
    """Un canvas pour tracer des cercles."""
    def __init__(self, boss):
        """Constructeur de la classe CanvasCerclesTangent."""
        ## général
        self.boss = boss                ## Canvas dans lequel on va dessiner

        ## grand cercle
        self.r = 400
        self.xO = 450
        self.yO = 450
        self.gdCercle = cercle(self.boss, self.xO, self.yO, self.r)

        ## petits cercles
        self.nMax = 1000000
        self.n = 1
        self.x = self.r             ## rayon des petits cercles
        self.y = self.r-self.x      ## rayon du cercle des centres des petits cercles exterieurs
        self.ptCercle = []

        ## cercles intérieurs
        self.cerclePalier = [0, 6, 8, 10, 14, 23, 53, 247, 4961, 10000000]       ## paliers pour lesquels le nombre de cercles interieurs change
        self.cercleExter = 1
        self.cercleInter = self.n-self.cercleExter

    def nUp(self):
        """Augmente le nombre de petits cercles de 1."""
        if self.n < self.nMax:
            self.n = self.n+1

    def nDown(self):
        """Diminue le nombre de petits cercles de 1."""
        if self.n > 1:
            self.n = self.n-1

    def supprimer(self):
        """Supprime tous les petits cercles."""
        for c in self.ptCercle:
            self.boss.delete(c)
        self.ptCercle = []

    def calculs(self):
        """Effectue tous les calculs necessaires au tracer."""
        ## Calcul du nombre de cercles interieurs et exterieurs
        i=0
        while self.n>=self.cerclePalier[i+1]:
            i = i+1
        if i==0:
            self.cercleExter = self.n
            self.cercleInter = 0
        else:
            self.cercleExter = self.cerclePalier[i]
            self.cercleInter = self.n-self.cercleExter

        ## Calcul des rayons
        if self.cercleExter==1:
            self.x = self.r
            self.y = 0
        elif self.cercleExter==2:
            self.x = self.r/2
            self.y = self.r/2
        else:
            n = self.cercleExter        ## Simplification des notations
            r = self.r
            self.x = r * sin(2*pi/n) / (2*sin((n-2)*pi/(2*n)) + sin(2*pi/n))
            self.y = r-self.x

    def dessinerCercle(self, n, x, y):
        """Dessine n cercles de rayon x dont les centres sont sur un cercle de rayon y."""
        ## Cas particulier pour n=1 et n=2
        if n==1:
            self.ptCercle.append(cercle(self.boss, self.xO, self.yO, x, col="cyan"))
        elif self.n==2:
            self.ptCercle.append(cercle(self.boss, self.xO+y, self.yO, x, col="cyan"))
            self.ptCercle.append(cercle(self.boss, self.xO-y, self.yO, x, col="cyan"))
        ## Cas général
        else:
            for k in range(n):
                theta = k*2*pi/n
                centre = coordPolaireToCarte(theta ,y)
                self.ptCercle.append(cercle(self.boss, centre[0]+self.xO, centre[1]+self.yO, x, "cyan"))

    def dessinerTout(self):
        """Dessine la figure."""
        ## Suppression de tous les petits cerlces précédents
        self.supprimer()

        ## Calculs
        self.calculs()
        #print(self.n, self.cercleExter, self.cercleInter, "/", self.x, self.y)

        ## Dessin
        self.dessinerCercle(self.cercleExter, self.x, self.y)
        while self.cercleInter>0:
            self.y = self.y-2*self.x
            n = int(min(self.cercleInter, max(1,(self.y*2*pi)/(2*self.x))))
            self.dessinerCercle(n, self.x, self.y)
            self.cercleInter = self.cercleInter-n

##### Main #####

if __name__=="__main__":
    ## fenetre
    root = Tk()
    root.title("Des cercles")
    ## Canvas
    can = Canvas(root, width=900, height=900, bg="white")
    can.grid(row=0,column=0, rowspan=100)
    ## Cercle
    cer = CerclesTangents(can)

    ## Paramètres
    nbText = Label(root, text="Nombre de petits cercles : %s"%(cer.n))
    nbText.grid(row=0, column=1, columnspan=6)
    Button(root, text="-100", comman=nDown100).grid(row=1, column=1)
    Button(root, text="-10", comman=nDown10).grid(row=1, column=2)
    Button(root, text="-", comman=nDown).grid(row=1, column=3)
    Button(root, text="+", comman=nUp).grid(row=1, column=4)
    Button(root, text="+10", comman=nUp10).grid(row=1, column=5)
    Button(root, text="+100", comman=nUp100).grid(row=1, column=6)

    Button(root, text="Afficher", command=cer.dessinerTout).grid(row=2, column=1, columnspan=2)

    okGo = 0
    Button(root, text="GO !", command=go).grid(row=2, column=3, columnspan=2)
    Button(root, text="Stop", command=stop).grid(row=2, column=5, columnspan=2)


    # C'est parti !
    root.mainloop()
 




[edit] Je continue à m'amuser tout seul.
Cette fois, pour un nombre de cercles $n$ fixé, le rayon est maximal.
Enfin plus exactement, avec la méthode que j'utilise pour placer les cercles, les rayons ne peuvent pas être plus grand.

Python


##### Import #####

#from Tkinter import *   # Python 2.x
from tkinter import *  # Python 3.x
from math import *
import time


##### Fonctions #####

def coordPolaireToCarte(theta, r):
    """Convertie des coordonnées polaires en coordonnées cartésiennes."""
    x = r*cos(theta)
    y = r*sin(theta)
    return [x,y]

def cercle(can, x, y, r, col="white"):
    """Trace dans le Canvas can un cercle de centre (x,y), de rayon r et de couleur col."""
    return can.create_oval(x-r, y-r, x+r, y+r, fill=col)

def nUp():
    """Commande de bouton : augmente le nombre de cercles de 1."""
    cer.nUp()
    nbText.config(text="Nombre de petits cercles : %s"%(cer.n))

def nDown():
    """Commande de bouton : diminue le nombre de cercles de 1."""
    cer.nDown()
    nbText.config(text="Nombre de petits cercles : %s"%(cer.n))

def nUp10():
    """Commande de bouton : augmente le nombre de cercles de 10."""
    for i in range(10):
        nUp()

def nDown10():
    """Commande de bouton : diminue le nombre de cercles de 10."""
    for i in range(10):
        nDown()

def nUp100():
    """Commande de bouton : augmente le nombre de cercles de 100."""
    for i in range(100):
        nUp()

def nDown100():
    """Commande de bouton : diminue le nombre de cercles de 100."""
    for i in range(100):
        nDown()

def go():
    """Fonction permettant de visualiser toutes les configurations de 1 cercle au maximum de cercles."""
    global okGo
    okGo = 1
    while okGo==1 and cer.n<10000:
        cer.dessinerTout()
        root.update()
        nUp()
        time.sleep(5/cer.n)
    ekGo=0

def stop():
    """Arrete la fonction go."""
    global okGo
    okGo = 0

##### Classes #####

class CerclesTangents():
    """Des cercles !"""
    def __init__(self, boss):
        """Constructeur de la classe CerclesTangents."""
        ## général
        self.boss = boss            ## Canvas dans lequel on va dessiner

        ## grand cercle
        self.r = 400                ## rayon du grand cercle
        self.xO = 450               ## coordonnées du centre
        self.yO = 450               ##      du grand cercle
        self.gdCercle = cercle(self.boss, self.xO, self.yO, self.r)

        ## petits cercles
        self.nMax = 100             ## nombre max de cercles que l'on peut afficher
        self.n = 1                  ## nombre de cercles à placer
        self.x = self.r             ## rayon des petits cercles
        self.y = self.r-self.x      ## rayon du cercle des centres des petits cercles exterieurs
        self.ptCercle = []          ## liste des petits cercles

        ## cercles intérieurs
        self.cerclePalier = [       ## Nombre de cercles de la couronne exterieure pour chaque valeur de n
                             0,1,2,3 ,4 ,5 ,6 ,6 ,7 ,8 ,9 ,
                             10,10,10,11,11,12,12,13,13,13,
                             14,14,15,15,16,16,16,17,17,17,
                             17,18,18,18,19,19,19,19,20,20,
                             20,21,21,21,22,22,22,22,23,23,
                             23,23,24,24,24,24,25,25,25,25,
                             26,26,26,26,26,26,27,27,27,27,
                             28,28,28,28,29,29,29,29,29,29,
                             30,30,30,30,30,31,31,31,31,31,
                             32,32,32,32,32,32,33,33,33,33]
        self.cercleExter = 1        ## Nombre de cercles de la couronne exterieure
        self.cercleInter = self.n-self.cercleExter ## Nombre de cercles intèrieurs restant à placer

    def nUp(self):
        """Augmente le nombre de petits cercles de 1."""
        if self.n < self.nMax:
            self.n = self.n+1

    def nDown(self):
        """Diminue le nombre de petits cercles de 1."""
        if self.n > 1:
            self.n = self.n-1

    def supprimer(self):
        """Supprime tous les petits cercles."""
        for c in self.ptCercle:
            self.boss.delete(c)
        self.ptCercle = []

    def calculs(self):
        """Effectue tous les calculs necessaires au tracer."""
        ## Calcul du nombre de cercles interieurs et exterieurs
        self.cercleExter = self.cerclePalier[self.n]
        self.cercleInter = self.n-self.cercleExter

        ## Calcul des rayons
        if self.cercleExter==1:
            self.x = self.r
            self.y = 0
        elif self.cercleExter==2:
            self.x = self.r/2
            self.y = self.r/2
        else:
            n = self.cercleExter        ## Simplification
            r = self.r                  ##      des notations
            self.x = r * sin(2*pi/n) / (2*sin((n-2)*pi/(2*n)) + sin(2*pi/n))
            self.y = r-self.x

    def dessinerCercle(self, n, x, y):
        """Dessine n cercles de rayon x dont les centres sont sur un cercle de rayon y."""
        ## Cas particulier pour n=1 et n=2
        if n==1:
            self.ptCercle.append(cercle(self.boss, self.xO, self.yO, x, col="cyan"))
        elif self.n==2:
            self.ptCercle.append(cercle(self.boss, self.xO+y, self.yO, x, col="cyan"))
            self.ptCercle.append(cercle(self.boss, self.xO-y, self.yO, x, col="cyan"))
        ## Cas général
        else:
            for k in range(n):
                theta = k*2*pi/n
                centre = coordPolaireToCarte(theta ,y)
                self.ptCercle.append(cercle(self.boss, centre[0]+self.xO, centre[1]+self.yO, x, "cyan"))

    def dessinerTout(self):
        """Dessine la figure."""
        ## Suppression de tous les petits cerlces précédents
        self.supprimer()

        ## Calculs
        self.calculs()
        #print(self.n, self.cercleExter, self.cercleInter, "/", self.x, self.y)

        ## Dessin
            ## Cercles de la couronne extérieure
        self.dessinerCercle(self.cercleExter, self.x, self.y)
        while self.cercleInter>0:           ## Tant qu'il y a des cercles à placer
            self.y = self.y-2*self.x        ## Calcul du rayon de la couronne
                ## Calcul du nombre de cercles que l'on peut placer sur cette couronne
            n = int(min(self.cercleInter, max(1,(self.y*2*pi)/(2*self.x))))
            self.dessinerCercle(n, self.x, self.y)
            self.cercleInter = self.cercleInter-n

##### Main #####

if __name__=="__main__":
    ## fenetre
    root = Tk()
    root.title("Des cercles")
    ## Canvas
    can = Canvas(root, width=900, height=900, bg="white")
    can.grid(row=0,column=0, rowspan=100)
    ## Cercle
    cer = CerclesTangents(can)

    ## Paramètres
    nbText = Label(root, text="Nombre de petits cercles : %s"%(cer.n))
    nbText.grid(row=0, column=1, columnspan=6)
    Button(root, text="-100", comman=nDown100).grid(row=1, column=1)
    Button(root, text="-10", comman=nDown10).grid(row=1, column=2)
    Button(root, text="-", comman=nDown).grid(row=1, column=3)
    Button(root, text="+", comman=nUp).grid(row=1, column=4)
    Button(root, text="+10", comman=nUp10).grid(row=1, column=5)
    Button(root, text="+100", comman=nUp100).grid(row=1, column=6)

    ## Affichage
    Button(root, text="Afficher", command=cer.dessinerTout).grid(row=2, column=1, columnspan=2)

    okGo = 0
    Button(root, text="GO !", command=go).grid(row=2, column=3, columnspan=2)
    Button(root, text="Stop", command=stop).grid(row=2, column=5, columnspan=2)


    # C'est parti !
    root.mainloop()
 

La grosse liste au milieu, c'est le nombre de cercles de la couronne extérieure pour chaque valeur de $n$.
Faite à la main en mode bourrin, en testant combien je pouvais en mettre...
C'est moche et fastidieux, mais les calculs l'étaient encore plus. Et je n'ai pas trouvé de formule générale...

Dernière modification par tibo (10-03-2018 12:06:48)


A quoi sert une hyperbole?
----- A boire de l'hypersoupe pardi !

Hors ligne

#7 11-03-2018 00:37:02

gbrinon
Membre
Inscription : 06-03-2018
Messages : 2

Re : Inscrire N cercles égaux dans un cercle

Bonjour,

Merci pour toutes vos réponses, quelque part ça me rassure un peu que ça n'était pas simple parce que je séchait totalement. En attendant de voir ce que vous alliez trouver, j'étais même parti a coder en dur les positions en fonction du nombre de petits cercles (de toute façon au delà de 10 - 12 ça devient trop brouillon a regarder).

Je vais me pencher sur vos implémentations. Merci encore :)

@Yoshi, tu avais bien saisi ma question, il fallait bien des cercles tangents entre eux, pas forcement au grand cercle dans le cas ou on est au delà de 4 ou 5, il y a un cercle au milieu, comme vous l'aviez vu. Comme tu le dis au dela de 10, ça devient un peu n'importe quoi en termes d'affichage de toute façon.

Une fois encore merci pour vos réponses

Hors ligne

#8 16-03-2018 11:55:59

Wiwaxia
Membre
Lieu : Paris 75013
Inscription : 21-12-2017
Messages : 409

Re : Inscrire N cercles égaux dans un cercle

Bonjour,

Je reviens sur ce sujet après suppression d'un premier commentaire, faute d'avoir bien saisi la méthode à prendre.

Soit 1°) un grand cercle de rayon (R), centré en (O) et contenant (N) autres cercles qui lui sont concentriques, et dont les rayons successifs sont en progression arithmétique: Rk =  2ka , avec a = R/(2N + 1) .
2°) un ensemble de (N') petits cercles de rayon (a), dont les centres sont régulièrement disposés sur les cercles intérieurs précédents, à égale distance de leurs plus proches voisins, et en nombre proportionnel au rayon (N'k = 6k)
a) à l'exception cependant de l'un d'entre eux , positionné en (O);
b) et de telle sorte qu'il y ait alignement de (2N + 1) centres selon trois directions mutuellement orientées à 60°, et concourant au centre (O).

# Sur ces trois droites, les petits cercles sont en contact avec leurs voisins, les centres correspondants étant séparés par la distance
l = Rk+1 - Rk = 2a(k + 1) - 2ak = 2a ;
les petits cercles extrêmes sont de même tangents au grand cercle délimitant le domaine, puisque leur centre est distant de la grande circonférence d'une longueur égale à : l' = R - 2Na = a(2N + 1) - 2Na = a .

# Les centres de deux petits cercles consécutifs situés sur la circonférence intérieure de rayon (Rk) (et qui en contient N'k = 6k) délimitent par ailleurs un segment de longueur:
dk = 2Rk.Sin(2$\pi$/(2N'k)) = 2.2ka.Sin(2$\pi$/(2.6k)) = 4ka.Sin($\pi$/6k)

   k   =  1        2        3        4        5        6        7  
d[k]/a = 2.0000   2.0706   2.0838   2.0884   2.0906   2.0917   2.0924  

fonction croissante de (k), supérieure à (2a) et admettant pour limite: d ~ 4ka.($\pi$/6k) = 2($\pi$a/3 = 2.0944a .

Le nombre de petits cercles ainsi disposés dans le grand  est:
N' = 1 + N'1 + N'2 + ... + N'N = 1 + 6(1 + 2 + ... + N) = 1 + 3N(N + 1) ;
on observe donc une distribution très proche de la distribution optimale (correspondant à la plus grande valeur possible de (a)) pour les nombres de petits cercles suivants:

N  = 1      2      3      4      5      6      7
N' = 7     19     37     61     91    127    169

Pour des nombres différents des valeurs remarquables précédentes, on peut envisager une disposition analogue, mais lacunaire; la plus désavantageuse du point de vue du taux d'occupation correspondrait aux valeurs: 8, 20, 38 ... etc .

D'autres approches, relevant d'un calcul programmé, sont possibles, par exemple:
a) placer un nombre donné de petits cercles de diamètre maximal sur le plus grand cercle intérieur, puis voir de proche en proche combien d'autres peuvent être ajoutés, d'une façon analogue, plus près de centre;
b) envisager l'évolution d'un nuage de (N) points confiné à l'intérieur du cercle de rayon (R) sous l'effet de forces répulsives; le système atteint un état d'équilibre pour lequel les distances sont maximales - mais l'algorithme est assez lourd à écrire.

Hors ligne

#9 14-04-2018 15:29:13

Wiwaxia
Membre
Lieu : Paris 75013
Inscription : 21-12-2017
Messages : 409

Re : Inscrire N cercles égaux dans un cercle

J'ai regardé quels arrangements pouvaient apparaître spontanément dans un nuage de (N) points en répulsion mutuelle, chacun d'eux subissant de la part de ses voisins une force en (1/rij3):
Fji = (1/MjMi)4.MjMi     (1 <= j <= N , j<>i)
et par ailleurs une force centrale de rappel proportionnelle à (ri5):
Fi = (-k*OMi4).OMi
qui maintient le système dans un domaine circulaire centré sur l'origine.

Une fois atteintes les positions d'équilibre, on a défini le rayon limite Rlim = (1/2)*Min(MjMi) et la distance maximale des points au centre: Dmax = Max(OMi); toutes les coordonnées ont ensuite été multipliées par le rapport r = 1/(Dmax + Rlim), de sorte qu'on observe sur l'image (N) cercles identiques de même rayon (R = r*Rlim), tangents à leurs plus proches voisins, et dont les plus éloignés sont eux-même tangents au grand cercle de rayon (1).

Bien qu'il n'intervienne aucune distance prédéfinie dans l'algorithme, celui-ci permet de connaître (à défaut du rayon maximal des petits cercles) la disposition mutuelle de leurs centres; les figures présentent au moins un ou deux axes de symétrie, quand ce n'est pas un axe de révolution dont l'ordre peut atteindre (8):

# Arrangements de 5 à 12 cercles
Arrangements de 5 à 12 cercles

# Arrangements de 13 à 20 cercles
Arrangements de 13 à 20 cercles

Dernière modification par Wiwaxia (22-05-2018 11:55:54)

Hors ligne

Pied de page des forums