Astronomie : Le Seigneur des Anneaux … d’Uranus

Art

Dans cet article, nous allons vous présenter notre projet sur Uranus, la septième planète du système solaire, que nous avons réalisée grâce au module turtle de python. Pour rédiger le script, nous avons notamment utilisé des fonctions, boucles et instructions conditionnelles.

Présentation et début du projet

La réalisation de ce projet s’inscrit dans le cadre de la 5ème édition du dispositif « Regard de géomètre ». Nos enseignants nous ont donc demandé de réaliser un script en python sur un thème parmi plusieurs qu’ils avaient sélectionnés. Nous avons choisi de faire notre projet sur le thème « Astronomie » car celui-ci nous a aussitôt inspirés. De plus, nous avons une passion commune pour l’astronomie. L’idée nous est donc venue de dessiner la planète Uranus ainsi que ses anneaux (eh oui Uranus possède des anneaux même si ceux-ci sont beaucoup moins imposants que ceux de Saturne 😁) grâce au module turtle de python.

  • Mais avant de coder Uranus, nous avons voulu rajouter un fond noir (le fond d’écran est blanc par défaut) pour symboliser l’espace. Afin de réaliser le fond noir, nous avons augmenté la taille du stylo grace à la fonction pensize() donc en le mettant à une taille égale à 10000. Ensuite nous avons choisi les coordonnées (x, y) du point vers lequel doit se déplacer la tortue (stylo = tortue) : on utilise donc goto(x, y). De plus, il est inutile de préciser la couleur puisque dans ce cas la couleur par défaut est le noir soit exactement la couleur que nous souhaitons obtenir. Enfin, une fois le fond noir réalisé, on réduit la taille du stylo pour que celui-ci ne soit pas trop grand lors de l’exécutions des fonctions suivantes.
  • Ce qui donne le code suivant :
pensize(10000)
goto(100,1)
pensize(5)
  • Ensuite, une fois que le fond noir est codé, il faut passer à la planète Uranus.
  • Dans un premier temps, nous décidons de la dessiner à l’aide de disques dont on augmentera le rayon successivement avec la boucle for i in range(). Mais, chaque fois qu’un disque apparaîtra, il effacera le précédent. Cela n’aurait guère d’importance si nous n’avions pas eu l’idée de faire des disques de couleurs différentes. Ainsi, la couleur finale d’Uranus est celle du dernier disque formé et la planète n’en est pas vraiment une.
  • Nous nous sommes donc rabattus sur les cercles afin de réaliser Uranus. Puis, à force de réfléchir sur le problème et avec un peu de recul, nous avons décidé de partir d’un cercle de rayon 0 puis d’augmenter ce rayon de la valeur de la variable t. En répétant cette action un grand nombre de fois (ici 220 fois) et en faisant en même temps un dégradé de couleur (en réduisant ou en augmentant les valeurs du Rouge et/ou du Vert et/ou du Bleu du code RVB de la couleur initiale par t) on obtient Uranus !
  • Le code python ci-dessous est l’application de ce que nous venons de dire précédemment. Nous allons cependant préciser quelques éléments :
    • Pour définir la fonction uranus, on doit rentrer la valeur du rayon, des coordonnées x et y du point de départ ainsi que définir la couleur du cercle.
    • Ces éléments sont définis après dans la boucle for t in range(220), ainsi que la valeur de la variable t, avant de les définir. Cela permet à la fonction de tracer des cercles de rayons de plus en plus grands.
    • Les éléments présents en dessous de def uranus permettent de positionner la tortue de façon à tracer un cercle.
    • Si vous souhaitez changer la couleur de la planète, vous avez la possibilité de faire un dégradé bleu en remplaçant les valeurs de color = (254 - t, 12 + t, 1 + t) par : color = (40, 221-t, 255).
def uranus(rayon, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y)
    pendown()
    pencolor(couleur)
    circle(rayon)

t = 1
for t in range(220):
    x, y = 50,-200
    radius = 0 + t
    color = (254 - t, 12 + t, 1 + t)
    uranus(radius, x, y, color)

Et voici le résultat (fond noir + fonction uranus) :

Améliorations du projet

Une fois la planète obtenue sur fond noir nous contemplons de manière enthousiaste notre travail. Mais il nous reste toujours les anneaux à faire ! Et c’est là que ça se complique.

  • Pour les anneaux, nous pensions tout d’abord à les faire avec des cercles. Après plusieurs tentatives, il faut se rendre à l’évidence : les anneaux avec les cercles ça ne marche pas ! C’est à ce moment-là que l’un d’entre nous se souvient de la présence, sur la calculatrice NumWorks, dans la rubrique « Fonction », d’une fonction appelée « conique » qui trace des ellipses. La forme de l’ellipse nous semblant similaire à celle des anneaux, nous décidons donc de tracer des ellipses pour les anneaux. Comme nous ne savons pas comment coder une ellipse avec le module turtle de python, nous faisons une recherche sur Internet. Nous tombons alors sur une fonction très simple permettant de tracer une ellipse. Nous l’ajoutons alors au script.
  • Puis, nous remanions le script trouvé sur Internet en reprenant les mêmes principes utilisés précédemment dans la fonction uranus c’est-à-dire en augmentant progressivement la taille du rayon et en faisant un dégradé de couleurs. Pour définir la couleur, nous avons utilisé pencolor() afin que la couleur des anneaux soit autre que noir. Puis nous avons aussi rajouté pensize(5) avant for j in range(30) pour augmenter la taille du tracé. Enfin nous avons changé la valeur de seth() afin que les anneaux soient inclinés vers le bas droit de l’image, ainsi que la valeur de la fonction anneaux() dans le but que ceux-ci soient assez grands pour que la planète se situe bien au milieu.
  • Et comme d’habitude ne pas oublier de définir la variable avant son utilisation (sinon ça ne marche pas😉). Ci-dessous le code python des anneaux ainsi qu’Uranus + ses anneaux.
# Source: https://stacklima.com/dessiner-une-ellipse-a-laide-de-turtle-en-python/
j = 1
def anneaux(rad):
  pensize(5)
  for j in range(30):
    pencolor(255- 5*j, 255- 5*j, 255- 5*j)
    circle(rad + j,90)
    circle(rad//2 + j,90)

seth(-80) 
anneaux(290)

Arrivés à ce stade-là, on aurait pu arrêter. On avait la planète Uranus, ses anneaux et le fond noir. Mais l’image semblait un peu vide, on a donc eu l’idée de rajouter quelque chose en fond d’écran : des étoiles.

  • Pour dessiner les étoiles, c’est assez facile. Si on veut dessiner une étoile à 5 branches on peut dessiner une partie de l’étoile et répéter cette action cinq fois. Tout ceci en utilisant (encore) une fonction, dans laquelle on doit définir la longueur d’un trait, les coordonnées (x, y) du point de départ ainsi que la couleur de l’étoile. Avant de coder la fonction on met la taille du stylo à 5 avec pensize(5) pour remplir l’interieur de l’étoile (il est inutile de le préciser avant puisqu’on l’a déjà mis dans le code du fond noir qui est situé avant la fonction etoiles). On choisit aussi de préférence une longueur assez basse (mais pas trop quand même). 4 est un bon chiffre par exemple.
  • La boucle for i in range(5) permet de dessiner 5 fois deux demi-branches d’étoiles pour obtenir une étoile (il faut faire attention aux mesures d’angles et si l’on tourne à droite ou à gauche). La boucle for i range(210) permet de dessiner 210 étoiles. Dans cette boucle, on définit les coordonnées (x, y) ainsi que la couleur de l’étoile grâce au module randint. Celui-ci permet, pour chaque étoile, de définir des coordonnées aléatoires comprises entre -800 et 800 pour x et -400 et 400 pour y. C’est le même principe pour les couleurs à part que l’on a réduit l’écart entre les nombres pour obtenir comme couleur (toujours de manière aléatoire) du jaune, de l’orange ou des couleurs s’en rapprochant de très près.

Le code python des étoiles :

def etoiles(longueur, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y)
    pendown()
    pencolor(couleur)
    for i in range(5):
        forward(longueur)
        left(74.2)
        forward(longueur)
        right(146)

for i in range(210):
    x, y = randint(-800, 800), randint(-400, 400)
    longueur = 4
    color = (randint(247, 255), randint(127, 255), randint(0, 12)) 
    etoiles(longueur, x, y, color)

Et le résultat :

Finalisation du projet

Enfin, nous avons pensé à rajouter le plus grand satellite naturel d’Uranus, Titania (à ne pas confondre avec Titan qui lui est le plus grand satellite naturel de Saturne).

  • On s’est dit que rajouter un petit détail supplémentaire pourrait être intéressant. On a tout de suite pensé à rajouter son plus grand satellite naturel. Pour le faire, on a utilisé le même procédé que pour Uranus, à savoir des cercles qui augmentent progressivement de rayon et un dégradé de couleurs. Mais cette fois-ci, pour plus d’originalité, nous avons utilisé des instructions conditionnelles pour faire le dégradé de couleur en fonction de la taille des cercles.
  • On utilise une boucle while cette fois-ci (on aurait pu aussi utiliser une boucle for comme dans les autres fonctions et vice versa). Ici on prend radius (le rayon du cercle) comme variable puis on l’augmente de 1 (avec +=) jusqu’à ce que radius soit égal à 30 : le principe reste donc le même qu’avec une boucle for.
  • Puis, dans la boucle while, on utilise des instructions conditionnelles afin que les cercles soit d’une certaine couleur en fonction de leur taille. Ainsi, la première condition (if) s’applique aux cercles dont le rayon est inférieur ou égal à 28 et dont la couleur sera du marron très clair. La deuxième condition (elif) concerne les cercles ayant un rayon compris entre 28 (non inclus) et 29 (inclus) : la couleur du cercle sera marron clair. A noter que l’on aurait pu remplacer elif radius > 28 and radius <= 29: par elif radius == 29: . Enfin, la troisième et dernière condition (else) concerne tous les cercles dont le rayon va jusqu’à 30 (mais ne concerne pas ceux des précédentes conditions), qui auront donc un couleur marron.
  • Le code et l’image obtenus :
def titania(rayon, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y)
    pendown()
    pencolor(couleur)
    circle(rayon)
    
x, y = -200, 100
radius = 0
while radius <= 30:
    radius += 1
    if radius <= 28:
        color = (167-2, 103-2, 38-1)
    elif radius > 28 and radius <= 29:
        color = (136-2, 66-2, 29)   
    else :
        color = (91-2, 60-2, 17)
    titania(radius, x, y, color)

Au cours de la rédaction de notre script python, nous avons rencontré différents problèmes que nous avons essayé de résoudre.

  • Le problème majeur que nous avons rencontré est le décalage des anneaux et de la planète sur l’image quand d’autres fonctions étaient exécutées avant. De plus, comme la même variable i était utilisée pour chaque fonction cela créait des confusions de même que le positionnement des objets sur l’image. Nous avons donc changé le nom des variables afin que chacune est un nom différent (i, j, t et radius) ce qui explique le nom des variables précédentes. Nous avons aussi ajouté les lignes suivantes entre chaque fonction afin d’éviter toutes confusions et pour remettre les fonctions à jour :
penup()
goto(0,0)
pendown()
  • Nous avons aussi eu des problèmes avec la fonction titania, notamment avec le cercle marron qui se décalait trop vers le haut. Nous avons donc réduit l’intervalle dans lequel il était appliqué pour supprimer ce décalage. Nous avons rencontré d’autres problèmes minimes et sans importance notamment sur les valeurs et la précision de celles-ci, qui peuvent faire varier le rendu.

L’image finale

Voici donc le résultat final ci-dessous une fois que tous les éléments ont été assemblés et les problèmes réglés :

Télécharger le .py

Si vous désirez le télécharger (il en format compressé il faudra donc le décompresser😉). Le script contient un code python permettant de générer une image ainsi que les fonctions permettant de dessiner le fond noir, les étoiles, les anneaux, Uranus et Titania (dans l’ordre) :