Catégorie : Art

Art

Un arbre fractale

La fractale est couramment sélectionnée comme thème pour la création d’images en raison de sa capacité à produire des motifs d’une complexité infinie et captivante. Cette fusion entre l’art et les mathématiques permet de représenter de manière créative la beauté des structures complexes, qu’elles soient naturelles ou urbaines.

Projet

Donc pour le projet nous avons décider de faire une fractale (l’arbre de Pythagore) sur un dégradé et faire un petit soleil sur le coté haut droit de l’image. Pour cela nous avons mis les script grâce à la bibliothèque turtle.

Le script

Donc pour faire le script nous nous aidons de la bibliothèque turtel. Mais tous les structure construise sont faite grâce à « def ». Nous avons donc du tous les appels a la fin un part un de manier logique et ordonné.

Le script en detailer

from turtle import *
import turtle
from random import randint
from PIL import Image
try:
    from PIL import Image
    pillow_installed = True
except:
    print("Oops! - ModuleNotFoundError: No module named 'PIL' - RTFM :")
    print("https://nsi.xyz/py2png")
    pillow_installed = False

# Uniquement des lettres, des chiffres, un tiret. Rien d'autre. https://learn.microsoft.com/fr-fr/windows/win32/fileio/naming-a-file
titre = "Fractale - Un arbre fractaleà"

# Définir le titre de la fenêtre de turtle + propagande ^^
title(titre+" | Au lycée, la meilleure spécialité, c'est la spé NSI")

# definir la taille de la fenêtre en 720p (Largeur, Hauteur, abscisse départ, ordonnée du départ)
setup(1280, 720) 
colormode(255) 
speed(0)

Tout d’abord « setup(1280, 720) » aident à configurer la fenêtre graphique Turtle pour votre dessin fractal, en lui donnant une taille spécifique (1280×720 pixels)

Puis colormode(255) serre à modifié le mode de couleur pour le rendre plus lisible (de 0 à 255 pour RGB)

Et enfin speed(0) serre à régler la vitesse de dessin pour qu’elle soit la plus rapide possible (vitesse 0).

Le fond:

def fond():
    penup()
    rciel = 0
    gciel = 0 
    bciel = 0
    hauteur = -360
    goto(-642,-358)
    pendown()
    while hauteur != 360:
        pencolor(round(239 + rciel), round(200 + gciel), round(209 + bciel))
        forward(1280)
        hauteur += 1
        goto(-640, hauteur)
        rciel += (-29/180)
        gciel += (2/45)
        bciel += (7/720)

Cette fonction « fond() » dessine un ciel en dégradé en utilisant une boucle « while » pour créer des bandes horizontales de couleur qui simulent un dégrade sur un ciel . Les composantes de couleur « rciel » « gciel » « bciel » changent progressivement à mesure que la hauteur augmente, créant un effet de transition de couleur réaliste.

La fractale arbre

def arbre(n,longueur):
    down()
    if n==0:
        color('green')
        forward(longueur) # avance
        backward(longueur) # recule
        color('#3f1905')
    else:
        width(n)
        forward(longueur/3) #avance
        left(angle) # tourne vers la gauche de angle degrés
        arbre(n-1,longueur*2/3)
        right(2*angle) # tourne vers la droite de angle degrés
        arbre(n-1,longueur*2/3)
        left(angle) # tourne vers la gauche de angle degrés
        backward(longueur/3) # recule

La fonction arbre à deux paramètres « n" et « longueur » pour contrôler le niveau de récursion et la longueur de la branche.

La condition « if n == 0 » permet de voir le cas de base dais que la profondeur de récursion atteint zéro.

En résumé, ce code utilise la récursion pour faire une fractale d’arbre, créant des branches qui se divise en sous-branches. Le niveau de récursion contrôle le détail de l’arbre, et la longueur de la branche diminue à chaque niveau, formant ainsi une structure d’arbre sur la base d’une fractale.

Le soleil

def soleil():
    speed(0)
    i = 0
    goto(-590, 305)
    while i < 200:
        down()
        color('#FF8C00')
        right(90)
        forward(55)
        right(180)
        forward(55)
        right(90)
        circle(5, 2)
        i = i + 1

Ce processus est répété jusqu’à ce que i atteigne 200 créant une série de formes qui se superposent pour former une figure qui ressemble à un soleil.

fond()

hideturtle() # cache la tortue
up() # lève le stylo
right(90) # tourne de 90 degrés vers la droite 
forward(300) # avance de 300 pixels
left(180) # fait un demi-tour
goto(0,-350)
angle = 50
color('#3f1905')
arbre(11,700) # exécute la macro

hideturtle() # cache la tortue
up() # lève le stylo
soleil()

On appelle tout les fonction maintenant

Vers le PNG

image = getcanvas()
Fractale=titre+"_"+hex(randint(2**30+2**25,2**30+2**25+2**24-1))[2:]

# Génère un fichier .ps
image.postscript(file=Fractale+".ps", colormode='color')

# Ouvre le fichier .ps et génère le fichier .png
psimage = Image.open(Fractale+".ps")
psimage.save(Fractale+".png")

Téléchargement du programme

Art

Astronomie : Voyage dans les étoiles

Observer les étoiles, c’est contempler l’immensité et percer les mystères de l’Univers : « À travers ses télescopes, l’astronomie sonde l’immensité de l’espace, révélant des mondes lointains et des mystères insoupçonnés. Elle nous invite à explorer l’infini, à contempler les astres, les étoiles et à comprendre l’origine de l’univers, suscitant l’émerveillement et la soif de connaissance « (Extrait du livre « Le grand guide de l’astronomie « )

Qu’est ce que l’Astronomie ?

L’astronomie… c’est comme une énorme chasse au trésor dans le ciel, mais avec des étoiles, des planètes et des galaxies ! On apprend à étudier les astres, les étoiles, à comprendre comment elles naissent et évoluent, on étudie aussi leurs propriétés physiques et chimiques.

Pourquoi avons-nous choisi le thème de l’astronomie ?

Tout simplement parce que l’Astronomie est un sujet fascinant, qui captive. Cette science permet d’explorer l’immensité de l’univers, les mystères des étoiles, des planètes et des galaxies. Choisir l’astronomie pour un projet offre une opportunité de découverte, d’apprentissage et d’inspiration.

Les différents problèmes...

Bien évidemment, il y a toujours des problèmes rencontrés lors d’un DM.

Le premier problème a été la communication. En effet, travailler en groupe est toujours compliqué…

Le deuxième problème a été d’assembler les scripts, un message d’erreur apparaissait à chaque fois. La plupart de ces erreurs étaient l’orthographe. En effet, chaque professionnel fait des erreurs…

Ensuite nous avons eu pour les montagnes un bug graphique sur le remplissage qui n’apparaissait que sur le dossier PNG ce qui rendait assez lourd le script sur les montagnes avec « begin_fill() » et « end_fill() »

Analyse du script

Afin d’analyser ce script, nous allons le découper en plusieurs parties, correspondantes aux différentes étapes.

1-Avant de détailler chaque fonction, il faut s’assurer que le script comporte tous les modules nécessaire à la création de l’image.

from turtle import *
from PIL import Image, ImageDraw
from random import randint

titre = "Astronomie - construite avec turtle"


title(titre + " | Au lycée, la meilleure spécialité, c'est la spé NSI")

setup(1280, 720, 0, 0)
speed(0)
goto(0,-200)

On importe les modules PIL (installés auparavant) afin de travailler avec des images, turtle afin de dessiner des formes géométriques sur l’image, et enfin randint afin de générer des nombres aléatoires. Après avoir importé tous ces modules, on définie un titre, ici Astronomie. Ensuite, on définit les titres de la fenêtre graphique. On définit alors la résolution de l’image, ici 1280×720 pixels. On définit aussi la vitesse. Enfin, on place la tortue à la position de départ.

2- Le fond

for i in range(hauteur_degrade):
    bleu_fonce = 0.1 + (i / hauteur_degrade) * 0.8 
    ciel.color(0, 0, bleu_fonce)
    ciel.penup()
    ciel.goto(x, y)
    ciel.pendown()
    ciel.forward(largeur_degrade)
    y -= 1

Afin de réaliser le fond de l’image, nous avons décidé de commencer la réalisation de l’image par une fenêtre noire similaire au lever d’un rideau, nous avons ensuite réalisé un dégradé de bleu similaire à un coucher de soleil à l’aide de chatgpt.

3-Les étoiles

def etoiles():
    for _ in range(42):
        speed(0)
        penup()
        x = randint(-600, 600)
        y = randint(-300, 300)
        penup()
        goto(x, y)
        pendown()
        dot(8, "orange")
        
etoiles()

Ne pas faire d’étoile sur une image qui porte sur l’Astronomie, ce n’est pas de l’Astronomie ! Afin de réaliser des étoiles aléatoirement, nous avons utilisé randint. Nous avons bien évidemment pensé a Halloween et pour cela, nous avons réalisé des étoiles en orange.

4-Les astres

Nous avons réalisé deux astres : le soleil et la lune.

def planète():
    speed(0)
    penup()
    goto(300, 250)  
    pendown()
    color("red")
    begin_fill()
    circle(50)  
    end_fill()
hideturtle()
planète()
penup()
goto(0,-200)
pendown()
fillcolor("white")
begin_fill()
circle(180)
end_fill()

Toujours dans le thème d’Halloween, nous avons décidé de faire le soleil rouge.

5-Le sol

Les montagnes, ça ne volent pas, et pour cela, nous avons mis un sol qui est en fait un rectangle en turtle.

def sol():
         for i in range(2):
             color("black")
             forward(1280) 
             left(90)
             forward(250)
             left(90)
sol()

6- Les montagnes :

Elles sont seulement constituées de triangle les uns à la suite des autres par une boucle. Nous avons mis à certains moments une légère inclinaison du triangle dans la boucle afin de créer un effet de montée

def triangle():
    forward (150) 
    left (120)
    forward (150)
    left (120)
    forward (150)


goto(-640,-200)

def montagne_plane():
         for i in range(50):
             begin_fill()
             triangle()
             left(300)
             backward(1)
             left(180)
             end_fill()
begin_fill()             
montagne_plane()
end_fill()
def montagne_ascendante1():
        for i in range(50):
             begin_fill()
             triangle()
             left(300)
             backward(4)
             left(180)
             left(0.2)
             end_fill()
montagne_ascendante1()

def montagne_ascendante2():
    for i in range(10):
        begin_fill()
        triangle()
        left(300)
        backward(10)
        left(180)
        left(2)
        end_fill()
montagne_ascendante2()

begin_fill() 
#triangle venant juste apres la montée
right(25)
goto(-310,-130)
triangle()
# recalibrage afin de pouvoir continuer l'algorithme
left(300)
backward(10)
left(180)
left(2)
end_fill()
# je fait redescendre legerement la montagne
goto(-290,-200)
for i in range(10):
     begin_fill()
     triangle()
     left(300)
     backward(4)
     left(180)
     end_fill()
for i in range(6):
     begin_fill()
     triangle()
     left(300)
     backward(4)
     right(5)
     end_fill()


left(8)
def montagne_ascendante3():
  for i in range(40):
       begin_fill()
       triangle()
       left(300)
       backward(7)
       left(180)
       left(1)
       end_fill()
montagne_ascendante3()
        
begin_fill()
right(25)
goto(150,-130)
triangle()

goto(150,-220)
left(300)
backward(10)
left(180)
left(1)
end_fill()


for i in range(2):
      montagne_ascendante1()

L’image finale

Le fichier.py

Art

Paysage : un coucher de soleil

Les couchers de soleils vous fascinent ? Vous êtes ici au bon endroit pour apprendre à créer des levers et couchers de soleil de votre choix sans devoir attendre le crépuscule. Je vous explique en détail mon script qui permet de générer une image avec le module turtle en python.

Les prémices du projet

Dans un premier temps, j’ai longtemps réfléchi à ce que je pouvais faire pour le projet libre de cette fin d’année. Je me suis décidée à refaire une image générée par le module turtle en python. Effectivement, notre tout premier projet de l’année était le même, néanmoins j’avais tout de suite commencé très fort en faisant des fractales. Certains vous diront que cela est facile, mais mon niveau de début d’année ne me permettait pas de tout comprendre. Ce qui m’a frustré. Je me suis donc décidée à refaire une image avec mon niveau actuel (qui est encore débutant !) pour pouvoir gérer la conception de A à Z.

Par conséquent, le script et l’image peuvent vous paraître assez simple. Cependant, j’ai souhaité m’inspirer du projet https://nsi.xyz/art/urbanisme-la-skyline-de-new-york/ qui se rapproche du flat design (ils l’expliquent très bien dans leur article). Le rendu final est donc très épuré et très simple.

Le code

Pour concevoir cette image, j’ai procédé par étapes pour créer le code. En découpant mon image, en plusieurs parties.

Le fond

Tout d’abord, j’ai codé le fond c’est-à-dire le coucher de soleil. L’espace utilisé est découpé en morceau rectangulaire. Puis pour chaque rectangle est associé une couleur. Je définis donc en premier mes neuf couleurs. Ensuite, j’utilise une boucle for, qui prend à chaque itération de la boucle la couleur suivante contenu dans la liste couleur.

def coucherdesoleil():
    couleur = ["#FFBA08",
               "#FAA307",
               "#F48C06",
               "#E85D04",
               "#DC2F02",
               "#D00000",
               "#9D0208",
               "#6A040F",
               "#370617"]
    penup()
    goto(640,-300)
    setheading(180)
    pendown()
    
    for fond in couleur: # ChatGPT m'a aidé sur cette ligne et la ligne suivante
        color(fond)
        begin_fill()
        forward(1280)
        right(90)
        forward(74)
        right(90)
        forward(1280)
        end_fill()
        
        left(180)

Le résultat :

Les étoiles

Puis, je crée une fonction qui permet de dessiner des étoiles. Elle prend en paramètre la longueur des branches, et l’emplacement de l’étoile, tout en définissant sa couleur.

def etoile(longueur, x, y):
    goto(x,y)
    pencolor("#DF7B0A")
    pendown()
       
    left(50)
    for i in range(5):
        forward(longueur)
        right(144)
    
    penup()

Je souhaitais que les étoiles se situent seulement en haut du ciel, tout en se positionnant de façon aléatoire, et de taille aléatoire. Ainsi par la boucle for , dix étoiles sont créées avec des paramètres précis (taille et position) mais de façon aléatoires.

for i in range(10):
    etoile(randint(5,15), randint(-630,630), randint(293, 350))

Le résultat :

Le soleil

Ensuite, le script exécute la fonction créant le soleil. Il se positionne à des coordonnées précises, je positionne le curseur en direction du haut de l’image : setheading(90), puis j’utilise la fonction prédéfinie du cercle, en indiquant la taille du rayon et si je souhaite un demi-cercle ou un cercle.

def soleil():
    goto(-115, -285)
    fillcolor("#FFC93E")
    begin_fill()
    setheading(90)
    circle(70, 180)
    end_fill()

Le résultat :

Les montagnes

Pour cette fonction, je me suis inspirée voir même j’ai repris la boucle créant l’ondulation des montagnes de mon ancien projet https://nsi.xyz/art/jardins-foret-enneigee/. Afin de créer une montagne, il faut lui donner comme paramètres d’entrée sa position initiale et finale (pour qu’ensuite elle puisse être remplie), la couleur, la direction, l’angle et la longueur des vagues.

De plus, pour varier la taille des montagnes, j’ai utilisé un test conditionnel afin de modifier l’inclinaison en fonction de sa position initiale.

Enfin, la boucle for permet de créer une vague, qui se répètent trois fois, formant une ondulation.

def rocher(x1, y1, x2, y2, couleur, direction, angle, vague1, vague2):
    fillcolor(couleur)
    pencolor(couleur)
    goto(x1,y1)
    if direction == 0:
        setheading(0)
        right(angle)
    else:
        setheading(direction)
        left(angle)   
    
    begin_fill()

    pendown()
    for i in range (3): # boucle repris de mon ancien projet https://nsi.xyz/art/jardins-foret-enneigee/
        for i in range (5):
            forward(vague1)
            right(2)
        for i in range (5):
            forward(vague2)
            left(2)
    
    goto(x2,y2)
    
    penup()
    end_fill()

Le résultat final

Les problèmes rencontrés et leurs solutions

Le premier problème était que les montagnes ne s’arrêtaient pas toutes à la même ligne, il y avait donc des débordements en dehors du cadre. Ma solution a été de créer une ligne blanche repassant sur ces débordements. Je pense qu’il y avait sûrement une solution ou un bout de code permettant de stopper les boucles quand elles arrivaient à un certain endroit, mais j’ai préféré utiliser cette méthode.

Le deuxième problème a été l’emplacement des étoiles. Effectivement, au début vingt étoiles étaient créées avec des emplacements aléatoires, par conséquent il y avait des superpositions. J’ai donc décidé de réduire le nombre, afin que les étoiles aient moins de chance d’obtenir la même position.

Le troisième problème n’en est pas vraiment un, mais cela était plutôt un souhait que je n’ai pas réussi à effectuer. En effet, je souhaitais faire un beau dégradé pour le coucher de soleil. J’en avais vu un sur cet article https://nsi.xyz/art/perspective-un-paysage-synthwave/ j’ai longtemps essayé de comprendre la fonction et j’ai même demandé à ChatGPT, mais sans succès. J’ai donc décidé de ne pas copier coller un code que je ne comprenais pas et j’ai laissé le coucher de soleil actuel.

Mes sources

J’ai principalement codé avec mes connaissances, les cours de NSI et les anciens projets disponibles sur le site https://nsi.xyz/. Toutefois, j’ai eu besoin de faire des recherches et j’ai utilisé ChatGPT à plusieurs reprises pour qu’il me montre mon erreur lorsque je ne comprenais pas le message d’erreur ou quand je ne comprenais pas tout à fait les explications que je trouvais sur internet.

Conclusion

En conclusion, je suis très fière de mon image. Même si son codage est effectué avec les base de la programmation et peut paraître facile. J’ai pris plaisir à programmer, comprendre, corriger toute seule mes erreurs, afin de concevoir une image propre à mes connaissances et à mes envies.

Télécharger le .py

Si vous souhaitez générer l’image et l’utiliser comme fond d’écran n’hésitez pas à télécharger le fichier ci-dessous.

Art

Un rafale en AxiDraw

Il est parfois compliqué de se motiver pour travailler surtout en période de vacance scolaire. C’est pourquoi j’ai choisis lors de ce projet de NSI de mêler travail et passion en vous proposant un projet en lien avec l’aéronautique.

Fait de ta vie un rêve et de ton rêve une réalité.

Antoine de Saint-Exupéry

Naissance du projet :

Lorsque nos professeurs ont présenté les différentes possibilités parmi lesquelles nous pourrions réaliser notre projet, j’ai tout de suite pensé à utiliser l’ Axidraw et ce pour plusieurs raisons.

Tout d’abord, pour découvrir cette machine mais aussi pour les nombreuses possibilités d’utilisation que cette mécanique avait à m’offrir.

Ensuite, j’ai utilisé la maxime  » Il faut joindre l’utile à l’agréable » en choisissant d’utiliser ma passion, qui est celle de l’aéronautique, afin de pouvoir travailler sans regret durant les vacances.

C’ est ainsi que je me suis mis à coder un Rafale ( un célèbre avion de chasse Français ), en python !

Développement du projet

Pour commencer, il me fallait une image sur papier, une sorte de plan, de ce à quoi je voulais que mon Rafale ressemble, et ce tout en traits puisque l’Axidraw ne peut tracer de courbes.

Ma « feuille de route », une véritable œuvre d’art…

Mise en place

Une fois après avoir réalisé mon esquisse, il ne restait plus qu’à mettre à l’échelle mes différentes valeurs que je pouvais dès maintenant mesurer à la règle.

Ainsi, on obtenait :

  • 1cm sur la feuille en longueur -> 30 de longueur pour l’AXIDRAW
  • 1cm sur la feuille en largeur -> 36.5 de largeur pour l’AXIDRAW.

Ensuite, j’ai crée de nombreuses listes que j’ai ensuite appelé en utilisant les fonctions mises à notre disposition par nos professeurs de NSI :

percheravito = [[153,317.55], [141,295.65],[141,295.65], [117,292], [117,288.35], [147,292],[156,313.9]]
haut_aileron = [[759,193,45],[828,193.45],[804,175.2],[784.5,175.2]]
segments(percheravito)
polygone(haut_aileron)

Ainsi, dans l’exemple ci-dessus nous pouvons voir la liste permettant de faire la perche qui sert au ravitaillement en vol du rafale avec son appellation par la fonctions segments qui relie les points aux coordonnées x et y définis dans ma liste. L’appellation de la fonction polygone va elle rajouter un segment qui ira de mon premier point au dernier présent dans la liste haut_aileron afin de former un polygone.

Création des verrières du rafale.

Comme vous avez pu le voir dans mon esquisse de l’œuvre que je voulais produire, les verrières du rafale devaient être constellées de traits afin de donner un esthétique au rendu final mais aussi afin d’introduire quelques fonctions dans ma création.

Mais, je ne pouvais pas créer une seule et même fonction que j’appellerai pour les trois verrières puisque ces mêmes verrières étaient disposées à des endroits différents et séparés par l’armature de l’avion.

image des différentes verrières que je voulais remplir

Ainsi, j’ai du créer trois verrières :

Première verrière :

Pour cette première verrière, vu sa configuration, je n’avais pas besoin de créer un code trop important. En effet, une simple boucle for permettrait de répéter x fois en fonction du nombre de répétitions des segments, grâce à la fonctions segments fournie, en décalant x_depart, y_depart et y_arrivee à chaque répétition. Ainsi, nous obtenons ce code :

def trait(x_depart: float, y_depart: float, x_arrivee: float, y_arrivee: float, repetitions: int):
    for i in range(repetitions):
        segment(x_depart, y_depart, x_arrivee, y_arrivee)
        x_depart += 4.5
        y_depart -= 2.25
        y_arrivee -= 2.25

Seconde verrière :

Pour cette verrière, il n’était cette fois plus question de prendre une boucle for puisque si vous regardez bien elle se compose de deux parties. J’ai donc utilisé une succession de deux boucles while consécutives qui détermineraient les variations des points x et y en fonction des coordonnées d’arrivée des points de mes segments.

def traits(x_depart: float, y_depart: float, x_arrivee: float, y_arrivee: float, ):
    while x_depart >= 209 and y_depart >= 270:
        segment(x_depart, y_depart, x_arrivee, y_arrivee)
        x_depart -= 1
        x_arrivee += 0.75
        y_depart -= 2.25
        y_arrivee -= 2.25

    while x_depart <= 255 and y_depart >= 273.75:
        segment(x_depart, y_depart, x_arrivee, y_arrivee)
        x_depart += 6.5
        x_arrivee += 0.25
        y_depart -= 2.25
        y_arrivee -= 2.25

Troisième verrière :

Pour cette troisième verrière, j’ai réutilisé le code de ma seconde verrière en changeant les points x_depart, x_arrivee, y_depart, y_arrivee ainsi que les variations de ces points en fonction des boucles while ce qui nous donne :

def traittss(x_depart: float, y_depart: float, x_arrivee: float, y_arrivee: float):
    while x_arrivee <= 360 and y_arrivee >= 290.75:
        segment(x_depart, y_depart, x_arrivee, y_arrivee)
        x_depart += 0.8
        x_arrivee += 1.2
        y_depart -= 2.25
        y_arrivee -= 2.25

    while y_depart >= 278:
        segment(x_depart, y_depart, x_arrivee, y_arrivee)
        x_depart += 0.3
        x_arrivee -= 8
        y_depart -= 2.25
        y_arrivee -= 2.25

Compte rendu final des verrières :

Ainsi, après avoir appelé ces fonctions j’obtenais les verrières en image ci-dessous :

Néanmoins, comme vous vous en doutez surement, cette réalisation n’a pas été aussi facile que ce qu’il vous a été présenté puisque il a fallu calculer les variations des points x et tester différentes variations des points y afin d’obtenir le meilleur rendu visuel.

Création du réacteur :

Pour le réacteur, j’ai souhaité ajouter des segments de la même manière que pour mes verrières. J’ai donc repris le code utilisant les boucles while que j’ai développé puisqu’il ma fallu créer une troisième boucle while pour obtenir le rendu souhaité.

def react(x_depart: float, y_depart: float, x_arrivee: float, y_arrivee: float):
    while  y_arrivee >= 405.15:
        segment(x_depart, y_depart, x_arrivee, y_arrivee)
        x_depart += 0
        x_arrivee += 10
        y_depart -= 5
        y_arrivee -= 5

    while y_arrivee >= 372:
        segment(x_depart, y_depart, x_arrivee, y_arrivee)
        x_depart += 0
        x_arrivee += 0
        y_depart -= 5
        y_arrivee -= 5
        
    while y_arrivee >= 355.875:
        segment(x_depart, y_depart, x_arrivee, y_arrivee)
        x_depart -= 0
        x_arrivee -= 10
        y_depart -= 5
        y_arrivee -= 5

L’exécution de ce code ma ensuite donné ce rendu :

Dernières finitions :

Maintenant que les parties complexes de mon code ont été réalisées, il ne me restait plus que deux choses à faire :

  • Positionner la fameuse cocarde tricolore ( qui sera unicolore sur mon rendu graphique car l’Axidraw ne prend pas en charge les couleurs ) sur mon rafale.
  • « Légender » mon œuvre en écrivant le nom de l’avion représenté en dessous.

Pour la cocarde, je n’eu qu’à utiliser la fonction cercle déjà donnée et en tracer deux consécutivement, avec le même centre mais avec le rayon du second cercle moitié moins grand que le rayon du premier cercle.

Pour légender le dessin obtenu, il ne me restait seulement qu’ à exécuter une succession de segments formant le mot RAFALE.

Conclusion :

Ainsi, ce projet m’a permis de normaliser mon utilisation des fonctions et des listes. Néanmoins, je pense que de nombreuses améliorations auraient pu être possible avec un peu plus de temps notamment en ajoutant des segments pour rendre mon image plus précise mais aussi en modifiant la bordure dessinée par l’Axidraw afin qu’elle mette plus en valeur le rafale représenté.

Mais je dois quand même ajouter que je suis fier de ce que j’ai déjà réalisé car jamais je ne me serais attendu à un rendu comme celui là en n’ utilisant que des segments !

Télécharger le .py :

L’image finale :

Art

Les différentes étapes pour coder un dessin avec AxiDraw

Vous souhaitez dessiner avec précision mais vous n’avez pas le coup de main ? Vous désirez représenter plusieurs fois des images ou textes à l’identique ? L’AxiDraw est fait pour vous !

Qu’est ce que l’AxiDraw ?

Dans le cadre de notre projet libre de fin d’année en NSI, nos professeurs, Monsieur Robert et Monsieur Clemente, nous ont présenté l’AxiDraw qui permet de dessiner un projet que l’on a imaginé.

L’AxiDraw est une machine composée de deux moteurs et d’un bras automatisé au bout duquel il est possible d’ajouter différents types d’outils de graphisme.

Son fonctionnement est assez simple : il suffit de programmer les traits que l’on souhaite tracer, à l’aide du logiciel « Inskape » ou avec du langage python, et l’AxiDraw réalise alors notre modèle au format SVG (Scalable Vector Graphics).

Par où commencer ?

Au préalable, il est primordial de définir parfaitement le rendu final désiré.

Il existe différentes façons de le faire. Pour ma part, j’ai choisi de dessiner mon modèle à la main mais on peut aussi préparer son projet à l’aide de logiciels comme Paint.

J’ai donc dessiné une maison sur une feuille à petits carreaux afin de respecter plus facilement une échelle donnée. En effet, notre réalisation ne devait pas être supérieure à un cadre défini par une abscisse comprise entre 20 et 1040 pixels et une ordonnée comprise entre 20 et 730 pixels.

Programme et fonctions de codage

Une fois mon modèle prêt, il ne restait plus qu’à passer au codage !

Nos professeurs nous ont fourni un programme où de nombreux paramètres étaient déjà prédéfinis, comme la bordure de la feuille, la vitesse de l’AxiDraw ou encore différentes fonctions (pouvant tracer une succession de segments par exemple). J’ai donc utilisé ce programme et je l’ai inséré dans l’IDE Thonny. J’ai ensuite installé la bibliothèque Pyaxidraw et Pillow afin que ce dernier puisse fonctionner.

J’ai alors pu commencer réellement la programmation de mon dessin.

Tout d’abord, il était nécessaire de convertir toutes les longueurs, sur ma feuille en centimètres, en pixels. A partir des valeurs obtenues, j’ai alors défini les points délimitant les segments que je souhaitais tracer.

J’ai notamment utilisé la fonction « segments », qui permet de tracer une succession de segments en fonction d’une liste d’abscisses et d’ordonnées de points successifs, comme présentée ci dessous:

def segments(points:list):
    for i in range(len(points) - 1):
        if not coord_in_cadre(points[i][0],points[i][1]) or not coord_in_cadre(points[i+1][0],points[i+1][1]):
            global dessin_valide
            dessin_valide = False
            print("Segments ne pouvant être tracés")
            return        
    if axi_connect and dessin_valide:
        for i in range(len(points)):
            points[i][0], points[i][1] = points[i][0] * 8.267 / 793.7, points[i][1] * 8.267 / 793.7
        ad.goto(points[0][0], points[0][1])
        ad.draw_path(points) 
        ad.penup() 
    else:
        for i in range(len(points)-1): 
            draw.line((points[i][0], points[i][1], points[i+1][0], points[i+1][1]), fill = black)

ma_liste = [(926.25,661.5625),(958.75,661.5625),(975,593.125),(910,593.125),(926.25,661.5625)]
segments(ma_liste)

Cet extrait de code permet, une fois la fonction « segments » définie, de produire très simplement et d’un seul trait l’image suivante:

D’autres fonctions comme celles traçant des cercles, des rectangles ou des paraboles m’ont aussi été très utiles.

Utilisation de boucles for

Lors de la réalisation de mon dessin, j’ai veillé à utiliser des motifs qui se répétaient afin de réduire le nombre de lignes de code et ainsi, me faciliter le travail.

J’ai donc par exemple utilisé la boucle for i in range() afin de créer un panneau de bois sur la façade de la maison en soustrayant une même longueur à la hauteur du rectangle à chaque incrémentation :

def rectangle(x_depart,y_depart,delta_x,delta_y):
    polygone([[x_depart,y_depart],[x_depart + delta_x,y_depart],[x_depart + delta_x,y_depart + delta_y],[x_depart,y_depart + delta_y]])

for i in range(9):
    rectangle(568.75,319.375,113.75, 91.25 - 11.40625*i)

Image associée :

J’ai aussi voulu dessiner des platebandes d’herbe avec des boucles for i in range() mais ne sachant pas comment coder un demi-cercle, j’ai utilisé la fonction parabole, ce qui a d’ailleurs donné un rendu plus réaliste. Afin de donner un effet de profondeur à la succession de paraboles, l’ordonnée du point initiant la parabole devait être différente de l’ordonnée du point terminant la parabole. Pour cela, il fallait veiller à ajouter la bonne valeur à chaque incrémentation. En effet, il ne fallait donc plus ajouter l’écart exact entre les deux abscisses (ici 6) mais cette valeur moins 1 (ce qui revenait à ajouter 5).

def parabole1(x_depart, y_depart):
    return[(a+x_depart,a**2+y_depart) for a in range(-3,3)]

for i in range(37):
    segments(parabole1(341.25+5*i,638.75))
    
for i in range(26):
    segments(parabole1(480+5*i,604))

Image associée :

Rendu final :

Après ces petites explications, je vous partage le rendu final de mon travail qui peut être réalisé par l’AxiDraw que nous avons la chance d’avoir au Lycée Louis Pasteur d’Avignon !

Merci pour votre lecture.

Télécharger le .py :

Et pour finir, vous pouvez télécharger mon projet afin que vous puissiez le découvrir plus en détail !

Art

Perspective : un paysage Synthwave

Dans le cadre de la 5ème édition du dispositif “Regards de Géomètre”, nous avons décidé dans le thème « Perspective » de produire un paysage synthwave.

Origines de la Synthwave

Avant tout la synthwave est un genre musical électronique ayant émergé dans les années 2000/2010 qui s’inspire d’éléments des années 80. Et c’est justement dans les clips de ces musiques que l’on va retrouver ce type d’image.

Pour en savoir plus nous vous conseillons cette vidéo qui explique brièvement les origines.

Le Projet

Revenons donc au projet. Pour ce projet nous avons donc décidé de produire une image d’un paysage synthwave. Pour cela nous utilisons le module turtle ainsi que le module random, le module turtle est utilisé pour produire l’image est le module random est utilisé pour les étoiles de l’image où la taille et leur position est générée aléatoirement nous avons également utilisé le script permettant d’exporter une image générée par turtle en .png que vous pouvez retrouver ici.

Structure du script

Pour la structure du script nous avons décidé de découper chaque partie de l’image (pavage, fond, étoiles, soleil, ville et montagnes) afin de créer des fonctions et à la fin nous les avons toutes appelées dans un ordre précis pour que les différentes parties de l’image soit dans leur plan respectif.

Analyse du script

Nous allons donc analyser le script.

Commençons par l’appel des modules et la mise en place de turtle.

from turtle import *
from random import randint
# vérification des modules importés
try:
    from PIL import Image
    pillow_installed = True
except:
    print("Oops! - ModuleNotFoundError: No module named 'PIL' - RTFM :")
    print("https://nsi.xyz/py2png")
    pillow_installed = False
titre = "Perspective - Un paysage Synthwave"
title(titre+" | Au lycée, la meilleure spécialité, c'est la spé NSI")
setup(1280, 720) # définit la taille de la fenêtre
colormode(255) # permet l'utilisation de couleurs rgb
speed(0) #Remplaçable par tracer(2) (10x plus rapide) mais si il est utilisé des lignes du pavage peuvent manquer
hideturtle() #dissimule la tortue

On appelle les fonctions turtle, random avec pour random uniquement randint et on utilise une partie du script « exporter une image générée par turtle » pour vérifier que l’utilisateur a bien installé le module PIL et dans le cas contraire un message d’erreur s’affichera et lui donnera un lien pour installer le module et tout ça sans que le script ne s’arrête. Après la vérification on met en place le titre de la fenêtre qui va affiché le rendu ainsi que sa taille. Enfin on définit le type de couleurs utilisées (R,G,B), la vitesse de la tortue, et on dissimule la tortue (c’est plus joli).

Commençons par la première fonction : le fond

def fond():
    penup()
    rciel = 0
    gciel = 0 
    bciel = 0
    hauteur = -360
    goto(-642,-358)
    pendown()
    while hauteur != 360:
        pencolor(round(239 + rciel), round(41 + gciel), round(209 + bciel))
        forward(1280)
        hauteur += 1
        goto(-640, hauteur)
        rciel += (-29/180)
        gciel += (2/45)
        bciel += (7/720)

Pour le fond on aurait pu utiliser une fonction qui crée un rectangle et qui le remplit avec fill_rect, cependant la couleur dans ce cas est uni ce qui ne nous intéresse pas. Nous avons donc produit un script qui fait un fond dégradé qui fait avancer la tortue sur une ligne d’un pixel de large et à la fin de cette ligne la tortue est envoyé grâce à un goto à la ligne d’après et qui ajoute la différence de chaque couleur (rouge,vert et bleu) entre la couleur de début du dégradé et la couleur de fin. Tout ceci est arrondi car turtle n’est pas compatible avec des arguments à virgule (pour la fonction pencolor en tout cas).

Par la suite la fonction qui produit les étoiles a été codée :

def etoile():
    for i in range(90):
        penup()
        goto(randint(-720,720), randint(0,360))
        pendown()
        pencolor(255, 255, 255)
        lcercle = randint(1,3)
        fillcolor('white')
        begin_fill()
        circle(lcercle)
        end_fill()

Pour les étoiles on définit aléatoirement leur position sur la moitié haute de l’image, on les met en blanc, on définit aussi aléatoirement la taille de l’étoile et on créer l’étoile avec sa position, et sa taille en aléatoire puis on refait ce processus 90 fois pour avoir 90 étoiles.

Ensuite nous avons le soleil (Le script affiché n’est qu’une petite partie du script total du soleil car il est très long et qu’il se répète, il est donc inutile de commenter la suite) :

def soleil():
    penup()
    liste1 = [10,7,5,4,3,3,3,3,2,2,2,2,2,2,2,1,2,1,2,1,1,2,1,1,1,1,2,1,1,1]
    liste2 = [1,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0]
    pliste1 = 0
    pliste2 = 0
    rsoleil = 0
    gsoleil = 0
    bsoleil = 0
    lsoleil = 8
    hauteur = 30
    goto(0,30)
    pendown()
    for i in range(15):
        pencolor(round(255 + rsoleil), round(23 + gsoleil), round(226 + bsoleil))
        forward(lsoleil)
        backward(2*lsoleil)
        hauteur += 1
        lsoleil += liste1[pliste1]
        pliste1 += 1
        goto(0, hauteur)
        rsoleil += (0)
        gsoleil += (114/101)
        bsoleil += (-203/202)
    forward(lsoleil)
    backward(2*lsoleil)
    penup()

Pour le soleil nous réutilisons le script du dégradé, cependant nous l’avons modifier pour que le point d’origine de la tortue soit au centre du rectangle et que la longueur de chaque ligne soit défini par une liste (ce qui permet de faire un cercle en prenant les longueur d’un cercle utilisable en pixel art). Pour ce qui est des endroits ou le soleil est coupé la tortue fait le tracé mais on a utilisé la fonction penup() qui fait que la tortue ne dessine plus.

Après nous avons la fonctions des montagnes (Encore une fois le script n’est pas complet car il se répète encore 3 fois après.) :

def montagne():
    #montagne derrière la première
    penup()
    goto(-480,0)
    fillcolor(110, 27, 188)
    begin_fill()
    for i in range(3):
        forward(250)
        left(120)
    end_fill()
    
    goto(-480,0)
    pencolor(51, 210, 246)
    ymontagne = 10
    for i in range(11):
        pendown()
        goto(-355,ymontagne)
        goto(-230,0)
        penup()
        goto(-480,0)
        ymontagne += 20

Pour le script des montagnes nous avons utilisé le script pour faire des triangles équilatéraux retrouvable ici. Et ensuite nous avons utilisé un ‘for i in range’ pour faire des goto enchaîné pour faire les lignes des montagnes.

Ensuite nous avons les fonctions de la ville. Pourquoi les fonctions car il y a une fonction pour chaque bâtiment différent ainsi qu’une fonction finale qui définit l’ordre des bâtiments.

def bat1():
    penup()
    rbat = 0
    gbat = 0 
    bbat = 0
    hauteur = 0
    pendown()
    xturtle, yturtle = pos()
    while hauteur != 72:
        pencolor(round(125 + rbat), round(35 + gbat), round(216 + bbat))
        forward(42)
        hauteur += 1
        goto(xturtle, hauteur)
        rbat += (-5/3)
        gbat += (-7/15)
        bbat += (-72/25)
    forward(42)
    penup()
    right(90)
    forward(72)
    left(90)

Pour le bâtiment 1 il y a un dégradé (toujours le même script) puis on fait que la tortue finisse le bâtiment en bas à droite de ce dernier pour pouvoir enchainer les bâtiments.

fun fact : Au début nous n’avions pas prévu les quelques lignes à la fin pour que la tortue puisse enchaîner les bâtiments sans que les fonctions des bâtiments aient besoin d’être modifiés ce qui nous a amené à avoir tous les bâtiments qui se chevauchaient.

def ville():
    penup()
    goto(-320,0)
    bat3(), bat2(), bat1(), bat4() ,bat3(), bat4(), bat3(), bat2(), bat1(), bat2(), bat1(), bat3(), bat1(), bat4(), bat2(), bat1(), bat3(), bat1(), bat4(), bat3()

Et à la fin on a fait la fonction ville qui appelle dans l’ordre choisi les bâtiments. Le goto permet de définir où commence le premier bâtiment, les autres se mettent juste après le premier sans se chevaucher ni laisser un espace.

Par la suite nous avons le pavage (très long aussi, il sera donc coupé) :

def pavage():
    colormode(255)
    pensize(5)
    speed(0)
    rciel = 0
    gciel = 0 
    bciel = 0
    hauteur = -360
    penup()
    goto(-640,-360)
    pendown()
    while hauteur != 0:
        pencolor(round(15 + rciel), round(4 + gciel), round(76 + bciel))
        forward(1280)
        hauteur += 1
        goto(-640, hauteur)
        rciel += (91/180)
        gciel += (1/36)
        bciel += (7/18)

Pour le début du pavage on retrouve encore le script du dégradé mais avec les couleurs modifiées.

pencolor(229, 123, 240)
    #Lignes au dessus du pavage
    pensize(4),penup(),goto(-640,0),pendown(),goto(640,0),pensize(2),penup(),goto(-640, 0),pendown()
    #lignes gauche
    penup(),goto(-20.00,0),pendown(),goto(-60.00,-360.00),penup(),goto(-60.00,0),pendown(),goto(-180.00,-360.00),penup(),goto(-100.00,0),pendown(),goto(-300.00,-360.00),penup(),goto(-140.00,0),pendown(),goto(-420.00,-360.00),penup(),goto(-180.00,0),pendown(),goto(-540.00,-360.00),penup(),goto(-220.00,0),pendown(),goto(-660.00,-360.00),penup(),goto(-260.00,0),pendown(),goto(-780.00,-360.00),penup(),goto(-300.00,0),pendown(),goto(-900.00,-360.00),penup(),goto(-340.00,0),pendown(),goto(-1020.00,-360.00),penup(),goto(-380.00,0),pendown(),goto(-1140.00,-360.00),penup(),goto(-420.00,0),pendown(),goto(-1260.00,-360.00),penup(),goto(-460.00,0),pendown(),goto(-1380.00,-360.00),penup(),goto(-500.00,0),pendown(),goto(-1500.00,-360.00),penup(),goto(-540.00,0),pendown(),goto(-1620.00,-360.00),penup(),goto(-580.00,0),pendown(),goto(-1740.00,-360.00),penup(),goto(-620.00,0),pendown(),goto(-1760.00,-360.00)
    #lignes droites
    penup(),goto(20,0),pendown(),goto(60.00,-360.00),penup(),goto(60.00,0),pendown(),goto(180.00,-360.00),penup(),goto(100.00,0),pendown(),goto(300.00,-360.00),penup(),goto(140.00,0),pendown(),goto(420.00,-360.00),penup(),goto(180.00,0),pendown(),goto(540.00,-360.00),penup(),goto(220.00,0),pendown(),goto(660.00,-360.00),penup(),goto(260.00,0),pendown(),goto(780.00,-360.00),penup(),goto(300.00,0),pendown(),goto(900.00,-360.00),penup(),goto(340.00,0),pendown(),goto(1020.00,-360.00),penup(),goto(380.00,0),pendown(),goto(1140.00,-360.00),penup(),goto(420.00,0),pendown(),goto(1260.00,-360.00),penup(),goto(460.00,0),pendown(),goto(1380.00,-360.00),penup(),goto(500.00,0),pendown(),goto(1500.00,-360.00),penup(),goto(540.00,0),pendown(),goto(1620.00,-360.00),penup(),goto(580.00,0),pendown(),goto(1740.00,-360.00),penup(),goto(620.00,0),pendown(),goto(1760.00,-360.00)
    #Lignes horizontales
    penup(),goto(-640, -300),pendown(),goto(640, -300),penup(),goto(-640, -240),pendown(),goto(640, -240),penup(),goto(-640, -190),pendown(),goto(640, -190),penup(),goto(-640, -140),pendown(),goto(640, -140),penup(),goto(-640, -100),pendown(),goto(640, -100),penup(),goto(-640, -70),pendown(),goto(640, -70),penup(),goto(-640, -40),pendown(),goto(640, -40),penup(),goto(-640, -15),pendown(),goto(640, -15),

On a par la suite énormément de goto afin de faire le quadrillage du pavage.

Pour produire l’image finale nous avons les appels des différents fonctions à la fin :

#appel de toutes les fonctions
fond(), etoile(), soleil(), montagne(), ville(), pavage()

Et pour exporter l’image finale en .png il y a la suite du script pour exporter une image générée par turtle en .png utilisé au début du script.

#enregistrement de l'image finale avec vérification des modules importés
image = getcanvas()
nom_du_fichier_sans_extension=titre+"_"+hex(randint(2**30+2**25,2**30+2**25+2**24-1))[2:]
image.postscript(file=nom_du_fichier_sans_extension+".ps", colormode='color')
try:
    psimage = Image.open(nom_du_fichier_sans_extension+".ps")
    psimage.load(scale=2)
    psimage_resized = psimage.resize((1280, 720))
    psimage.save(nom_du_fichier_sans_extension+".png")
    print(nom_du_fichier_sans_extension+".png", psimage.size, "sauvegardé dans le dossier")    
except:
    if not pillow_installed:
        print("Oops! - ModuleNotFoundError: No module named 'PIL' - RTFM :")
        print("https://nsi.xyz/py2png")
    else:
        print("Oops! - 'ghostscript' not installed- RTFM :")
        print("https://nsi.xyz/py2png")
exitonclick()

Le script va donc générer une image en .ps et la convertir en .png avec un nom généré aléatoirement pour éviter que à chaque fois que vous générez une image l’image soit écrasée

Télécharger le .py

L’image finale

Art

Astronomie : Un semblant de liberté

« C’est dur, oui, il a tant cherché sa place dans l’univers : société, nature sauvage, vie luxueuse,… mais rien de tout ça ne lui convenait. Se tournant vers le ciel, c’était peut-être parmi les étoiles que se trouvait sa place… »


Introduction

À l’aide du module Turtle, on va pouvoir créer une image en python, animée ou non.
Aujourd’hui, ce sera alors plutôt un dessin que nous générerons par notre code, de plus, celle-ci sera différente à chaque exécution !
Nous allons alors décortiquer des parties de celui-ci afin de le comprendre, si ce n’est pas déjà le cas ! 😉


Une mise en bouche qui nous prépare

colormode(255)
color(5,9,44)
goto(-640,0)
pensize(1000)
forward(1000)

Ce bloc de code permet de préparer le dessin en y installant un fond bleu nuit rappelant l’espace.
La couleur est définie dans les 2 premières lignes, ensuite on se rend à des coordonnées hors du champ de vision puis on trace un trait très épais.


Des fonctions par-ci, des fonctions par-là

def etoile():
    pensize(2)
    couleur = randint(0,3)
    if couleur == 0:
        color(250, 137, 25)
    else:
        color(247,247,36)
    for _ in range(5):
        forward(10)
        right(144)

Le bloc de code suivant est une fonction, elle nous permet de définir une suite d’instructions qu’on peut utiliser par la suite.
Elle dessine une étoile tout en utilisant un autre module permettant d’utiliser l’aléatoire, à l’aide de celui-ci et de structure conditionnelles, on choisit aléatoirement entre 2 couleurs pour l’étoile.
Puis, on la trace à l’aide d’une boucle bornée. 😵

def position_aleatoire():
    penup()
    x = randint(-640,640)
    y = randint(-320,320)
    goto(x,y)
    pendown()

Cette seconde fonction diffère de la 1ère par son utilité-même : elle permet de choisir une position aléatoire.
La fonction génère aléatoirement des coordonnées dans un intervalle défini, ici, celle de la fenêtre puis elle s’y rend.

for _ in range(42):
    position_aleatoire()
    type_etoile = randint(0,2)
    if type_etoile == 0:
        etoile_2()
    else:
        etoile()

C’est alors que la magie entre en scène, on manipule les fonctions précédemment créées afin de produire un splendide ciel étoilé !
On se rend à un endroit aléatoire grâce à la 2ème fonction puis on dessine une étoile grâce à la 1ère fonction (et une autre produisant un autre type d’étoile), et ceci 42 fois !! 😱


Des éléments de décoration


D’autres éléments constituant l’image proviennent de fonctions, prenons ici l’exemple de la fusée :

def fusee():
    left(55)
    penup()
    goto(-100,-40)
    pendown()
    corps_fusee()
    for i in range(2):
        penup()
        goto(-125+i*275/100*25,-50-i*5/2*20)
        pendown()
        moteur()
    for i in range(2):
        penup()
        goto(-15+i*35*135/100,-65/2+i*50*135/100)
        pendown()
        hublot()
    right(30)
    penup()
    goto(15,125)
    pendown()
    toit()


On peut voir une différence notable avec les fonctions précédentes, cette fonction est elle-même constituée de fonctions : « corps_fusee » ; « moteur » ; « hublot » et « toit ».
Et comme dit plus tôt, on utilise et manipule ces fonctions, par exemple en les utilisant plusieurs fois dans une boucle, en définissant un angle au préalable,… et ça ne s’arrête pas là ! on pourrait très bien utiliser la fonction définissant la fusée afin de lui donner une autre utilité !

C’est alors en usant de fonctions, de boucles et de structures conditionnelles qu’on peut facilement produire une œuvre avec le module Turtle, mais tout cela ne peut se réaliser qu’avec de la pratique, car comme j’ai dit : « C’est en programmant que l’on devient programmeur ».

L’image finale

Télécharger le .py

Art

Urbanisme : La skyline de New York

Pour ce premier projet en classe de première NSI nous avons choisi comme thème l’urbanisme. Nous avons souhaiter créer un projet original. Ce programme a pour but de réaliser un rendu graphique qui se rapproche au maximum du flat design. 

C’est quoi le flat design ?

Petit point de culture générale : Très brièvement le flat design est un style graphique caractérisé par le minimalisme et la simplicité des éléments présents sur le rendu. On ne cherche pas à faire à être dans le détail avec des ombres, des effets 3d… mais à être dans la simplicité avec une recherche en amont. Le flat design est aujourd’hui utilisé dans différentes catégories telle que l’illustration ou encore dans l’UI design où il consistera à obtenir un rendu fluide et ergonomique pour l’utilisateur. Un très grand artiste français qui utilise le flat design est Malika Favre voilà quelques exemples de créations qu’il a pu réaliser :

Les Recherches

Dans un premier temps pour réaliser ce projet nous avons dû faire différentes recherches sur internet. Les recherches finies, nous avons créer un moodboard pour mettre nos idées au claire et pour avoir de l’inspiration.

Nous avons sélectionné une image de la Skyline sur internet et nous l’avons directement modifiée sur Photoshop pour ne pas avoir de soucis avec les droits d’auteur.

Skyline/ Photoshop

Dans un second temps, nous nous sommes mis d’accord pour ne pas créer une simple Skyline mais bien plus. Notre point de départ est un couché de soleil avec des couleurs pastelles pour obtenir un rendu idéal qui se rapproche du flat design.

Une fois que nous étions d’accord sur les détails de notre projet, nous avons commencé le script phyton. Nous nous sommes divisés le travail en deux groupes :

  • Skyline : Noah / Henry
  • Ciel : Constance

Le code en entier

from turtle import *
from random import randint

#Lever de soleil

colormode(255)
bgcolor("#ffb399")

def disque(rayon, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y-rayon)
    pendown()
    pencolor(couleur)
    fillcolor(couleur)
    begin_fill()
    circle(rayon)
    end_fill()
    
x, y = (0,-120)
radius = (500)
color = ("#ffc6b3")
disque(radius, x, y, color) 

x, y = (0,-120)
radius = (400)
color = ("#ffd9cc")
disque(radius, x, y, color) 
    
x, y = (0,-120)
radius = (300)
color = ("#ffece6")
disque(radius, x, y, color)     

x, y = (0,-120)
radius = (200)
color = ('white')
disque(radius, x, y, color)   


def arrondi_gauche():
    for i in range(180):
        left(1)
        forward(7/45)
        
def arrondi_droit():
    for i in range(180):
        right(1)
        forward(7/100)


def nuage():
    speed(10)
    pendown()
    width(2)
    pencolor("#ffffb3")
    fillcolor("#ffffb3")
    begin_fill()
    forward(210)
    arrondi_gauche()
    forward (21)
    arrondi_droit()
    forward(14)
    arrondi_gauche()
    forward(70)
    arrondi_droit()
    forward(56)
    arrondi_gauche()
    forward(28)
    arrondi_droit()
    forward(14)
    arrondi_gauche()
    forward(20)
    for i in range(90):
        right(1)
        forward(7/50)
    for i in range(90):
        left(1)
        forward(7/45)
    forward(35)
    for i in range(90):
        left(1)
        forward(7/45)
    for i in range(90):
        right(1)
        forward(7/50)
    forward(21)
    arrondi_gauche()
    forward(14)
    arrondi_droit()
    forward(49)
    arrondi_gauche()
    forward(42)
    arrondi_droit()
    forward(56)
    arrondi_gauche()
    forward(7)
    arrondi_droit()
    forward(42)
    arrondi_gauche()
    forward(10)
    end_fill()

penup()
goto(-450,-40)
nuage()

penup()
goto(300,55)
nuage()

penup()
goto(-50,200)
nuage()

#Skyline

pensize(3)
def building1(longueur,largeur, couleur=(1,1,1)):
    pendown()
    pencolor(couleur)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    right(90)
    forward(longueur/1.5)
    left(90)
    forward(longueur/2)
 
def building2(longueur, largeur, couleur=(1,1,1)):
    etage(longueur, largeur/5)
    etage(longueur/2 , largeur/5)
    etage(longueur/3 , largeur/5)
    left(80)
    forward(longueur/2)

def etage(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)

def etage_inverse(longueur, largeur, couleur=(1,1,1)):
    forward(largeur)
    left(270)
    forward(longueur)
    left(90)
def building2_inverse(longueur, largeur, couleur=(1,1,1)):
    right(160)
    forward(longueur/2)
    left(80)
    etage_inverse(longueur/3, largeur/5)
    etage_inverse(longueur/2 , largeur/5)
    etage_inverse(longueur, largeur/5)

def building3(longueur, largeur, couleur=(1,1,1)):
   forward(longueur/3)
   left(90)
   forward(longueur)
   right(90)
   forward(largeur)
   right(90)
   forward(longueur/4)
   left(90)
   forward(largeur)
   left(90)
   forward(longueur/5)
   right(90)
   forward(largeur)
   right(90)
   forward(longueur/2)
   
def building4(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur/3)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    left(90)
    forward(longueur-30)
    right(90)
    forward(largeur+25)
    right(90)
    forward(longueur+20)
    
def building5(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    right(90)
    forward(longueur/2)
    left(45)
    forward(longueur/2)
    right(225)
    forward(longueur/3)
    right(90)
    forward(largeur+5)
    right(90)
    forward(longueur+30)
    
def building6(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur)
    left(90)
    forward(longueur)
    right(30)
    forward(longueur/8)
    left(30)
    forward(30)
    right(30)
    forward(longueur/8)
    left(30)
    forward(60)

def building6_reverse(longueur, largeur, couleur=(1,1,1)):
    left(180)
    forward(60)
    left(30)
    forward(longueur/8)
    right(30)
    forward(30)
    left(30)
    forward(longueur/8)
    right(30)
    forward(longueur)
    left(90)
    forward(largeur)
    
def building7(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    left(90)
    forward(longueur/3)
    right(90)
    forward(largeur)
    right(90)
    forward(longueur-130)
    left(90)
    forward(largeur)
    right(90)
    forward(longueur-50)
    left(35)
    forward(largeur*2)
    right(35)
    forward(longueur-75)


def building8(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    right(90)
    forward(longueur/2)
    left(35)
    forward (largeur)
    right(35)
    forward(longueur-20)
       
    
    
penup()
fillcolor("#80586D")
begin_fill()
goto(-630,-350)
goto(-630,-300)
building1(60,30, couleur=("#80586D"))
building2(150,80 , couleur=("#80586D"))
building2_inverse(150,80 , couleur=("#80586D"))
building3(120,30, couleur=("#80586D"))
building4(100,40, couleur=("#80586D"))
building5(80,25, couleur=("#80586D"))
building6(275,50, couleur=("#80586D"))
building6_reverse(275,50, couleur=("#80586D"))
right(90)
building4(90,30, couleur=("#80586D"))
building7(165,35, couleur=("#80586D"))
left(90)
building3(170,35, couleur=("#80586D"))
building8(150,45, couleur=("#80586D"))
pendown()
goto(630,-350)
goto(-630,-350)
end_fill()



penup()
fillcolor("#01343D")
begin_fill()
left(90)
goto(-620,-350)
building1(60,30, couleur=("#01343D"))
building2(150,80 , couleur=("#01343D"))
building2_inverse(150,80 , couleur=("#01343D"))
building3(120,30, couleur=("#01343D"))
building4(100,40, couleur=("#01343D"))
building5(80,25, couleur=("#01343D"))
building6(275,50, couleur=("#01343D"))
building6_reverse(275,50, couleur=("#01343D"))
right(90)
building4(90,30, couleur=("#01343D"))
building7(165,35, couleur=("#01343D"))
left(90)
building3(170,35, couleur=("#01343D"))
building8(150,45, couleur=("#01343D"))
pendown()
goto(-630,-350)
end_fill()

Le Fond

def disque(rayon, x, y, couleur=(1, 1, 1)):
    penup()
    goto(x, y-rayon)
    pendown()
    pencolor(couleur)
    fillcolor(couleur)
    begin_fill()
    circle(rayon)
    end_fill()
    
x, y = (0,-120)
radius = (500)
color = ("#ffc6b3")
disque(radius, x, y, color) 

x, y = (0,-120)
radius = (400)
color = ("#ffd9cc")
disque(radius, x, y, color) 
    
x, y = (0,-120)
radius = (300)
color = ("#ffece6")
disque(radius, x, y, color)     

x, y = (0,-120)
radius = (200)
color = ('white')
disque(radius, x, y, color)   


def arrondi_gauche():
    for i in range(180):
        left(1)
        forward(7/45)
        
def arrondi_droit():
    for i in range(180):
        right(1)
        forward(7/100)
Fond

Pour réaliser le fond, j’ai adapté la fonction disque des exemples donnés afin de faire un dégradé de disques partant d’un peu plus bas que le centre et du plus clair au plus foncé. De cette manière, le disque au centre est blanc et représente donc le Soleil. De plus, les disques autour forment un dégradé de couleurs modélisant le levé du Soleil dans le ciel.

Les nuages

def nuage():
    speed(10)
    pendown()
    width(2)
    pencolor("#ffffb3")
    fillcolor("#ffffb3")
    begin_fill()
    forward(210)
    arrondi_gauche()
    forward (21)
    arrondi_droit()
    forward(14)
    arrondi_gauche()
    forward(70)
    arrondi_droit()
    forward(56)
    arrondi_gauche()
    forward(28)
    arrondi_droit()
    forward(14)
    arrondi_gauche()
    forward(20)
    for i in range(90):
        right(1)
        forward(7/50)
    for i in range(90):
        left(1)
        forward(7/45)
    forward(35)
    for i in range(90):
        left(1)
        forward(7/45)
    for i in range(90):
        right(1)
        forward(7/50)
    forward(21)
    arrondi_gauche()
    forward(14)
    arrondi_droit()
    forward(49)
    arrondi_gauche()
    forward(42)
    arrondi_droit()
    forward(56)
    arrondi_gauche()
    forward(7)
    arrondi_droit()
    forward(42)
    arrondi_gauche()
    forward(10)
    end_fill()

penup()
goto(-450,-40)
nuage()

penup()
goto(300,55)
nuage()

penup()
goto(-50,200)
nuage()

Pour rajouter un effet naturel au ciel, on a décidé d’ajouter des nuages avec une couleur et une forme adaptée au moment de la journée du levé de Soleil. J’ai donc crée une fonction nuage qui comprend également deux autres fonctions pour arrondir chaque bosse des nuages. De cette façon, le script est bien plus court. Pour faire les arrondis, j’ai d’abord fait le script d’un cercle, puis je l’ai adapté dans chacune des fonctions afin que sa largeur puisse varier.

La Skyline

def building1(longueur,largeur, couleur=(1,1,1)):
    pendown()
    pencolor(couleur)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    right(90)
    forward(longueur/1.5)
    left(90)
    forward(longueur/2)
 
def building2(longueur, largeur, couleur=(1,1,1)):
    etage(longueur, largeur/5)
    etage(longueur/2 , largeur/5)
    etage(longueur/3 , largeur/5)
    left(80)
    forward(longueur/2)

def etage(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)

def etage_inverse(longueur, largeur, couleur=(1,1,1)):
    forward(largeur)
    left(270)
    forward(longueur)
    left(90)
def building2_inverse(longueur, largeur, couleur=(1,1,1)):
    right(160)
    forward(longueur/2)
    left(80)
    etage_inverse(longueur/3, largeur/5)
    etage_inverse(longueur/2 , largeur/5)
    etage_inverse(longueur, largeur/5)

def building3(longueur, largeur, couleur=(1,1,1)):
   forward(longueur/3)
   left(90)
   forward(longueur)
   right(90)
   forward(largeur)
   right(90)
   forward(longueur/4)
   left(90)
   forward(largeur)
   left(90)
   forward(longueur/5)
   right(90)
   forward(largeur)
   right(90)
   forward(longueur/2)
   
def building4(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur/3)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    left(90)
    forward(longueur-30)
    right(90)
    forward(largeur+25)
    right(90)
    forward(longueur+20)
    
def building5(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    right(90)
    forward(longueur/2)
    left(45)
    forward(longueur/2)
    right(225)
    forward(longueur/3)
    right(90)
    forward(largeur+5)
    right(90)
    forward(longueur+30)
    
def building6(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur)
    left(90)
    forward(longueur)
    right(30)
    forward(longueur/8)
    left(30)
    forward(30)
    right(30)
    forward(longueur/8)
    left(30)
    forward(60)

def building6_reverse(longueur, largeur, couleur=(1,1,1)):
    left(180)
    forward(60)
    left(30)
    forward(longueur/8)
    right(30)
    forward(30)
    left(30)
    forward(longueur/8)
    right(30)
    forward(longueur)
    left(90)
    forward(largeur)
    
def building7(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    left(90)
    forward(longueur/3)
    right(90)
    forward(largeur)
    right(90)
    forward(longueur-130)
    left(90)
    forward(largeur)
    right(90)
    forward(longueur-50)
    left(35)
    forward(largeur*2)
    right(35)
    forward(longueur-75)


def building8(longueur, largeur, couleur=(1,1,1)):
    left(90)
    forward(largeur)
    left(90)
    forward(longueur)
    right(90)
    forward(largeur)
    right(90)
    forward(longueur/2)
    left(35)
    forward (largeur)
    right(35)
    forward(longueur-20)
       
    
    
penup()
fillcolor("#80586D")
begin_fill()
goto(-630,-350)
goto(-630,-300)
building1(60,30, couleur=("#80586D"))
building2(150,80 , couleur=("#80586D"))
building2_inverse(150,80 , couleur=("#80586D"))
building3(120,30, couleur=("#80586D"))
building4(100,40, couleur=("#80586D"))
building5(80,25, couleur=("#80586D"))
building6(275,50, couleur=("#80586D"))
building6_reverse(275,50, couleur=("#80586D"))
right(90)
building4(90,30, couleur=("#80586D"))
building7(165,35, couleur=("#80586D"))
left(90)
building3(170,35, couleur=("#80586D"))
building8(150,45, couleur=("#80586D"))
pendown()
goto(630,-350)
goto(-630,-350)
end_fill()



penup()
fillcolor("#01343D")
begin_fill()
left(90)
goto(-620,-350)
building1(60,30, couleur=("#01343D"))
building2(150,80 , couleur=("#01343D"))
building2_inverse(150,80 , couleur=("#01343D"))
building3(120,30, couleur=("#01343D"))
building4(100,40, couleur=("#01343D"))
building5(80,25, couleur=("#01343D"))
building6(275,50, couleur=("#01343D"))
building6_reverse(275,50, couleur=("#01343D"))
right(90)
building4(90,30, couleur=("#01343D"))
building7(165,35, couleur=("#01343D"))
left(90)
building3(170,35, couleur=("#01343D"))
building8(150,45, couleur=("#01343D"))
pendown()
goto(-630,-350)
end_fill()
New York Skyline

Dans le cas de la Skyline, le principal défi a été d’éviter de reproduire la même chose. Donc pour remédier au problème, nous avons coder de nombreuses fonctions « def » pour initialiser les buildings. Ensuite, il s’agissait surtout de calculer les bâtiments et les étages car ils étaient tous hétérogènes. Enfin, il nous suffisait d’utiliser les fonctions en rentrant les mesures et définir les couleurs puis la Skyline de New York prend vie.

Conclusion

En réalisant ce projet, nous avons étudié l’architecture de New York en analysant les suites logiques de buildings en fonction de leurs tailles par exemple. Nous avons aussi travaillé sur la meilleure façon de représenter un lever de Soleil de manière simple et évidente en regardant des exemples sur des dessins et des photos. En python, on a appris à manipuler les fonctions pour exécuter des scripts sans les réécrire plusieurs fois (avec les arrondis des nuages par exemple). Nous avons aussi du travailler beaucoup avec les couleurs avec les plusieurs plans des buildings qui ont permis de donner du relief à l’image grâce aux couleurs mais aussi avec le dégradé du ciel pour qu’il paraisse naturel. Nous avons aussi du visualiser l’image finale en gardant le meilleur de différentes inspirations et tout calculer pour que l’image ne soit ni trop vide ni trop surchargée d’éléments. Cette réalisation avait pour but d’être esthétique, moderne et simple.4

Télécharger le .py

Si vous voulez l’essayer, vous trouverez le script ci-dessous, mais attention, les nuages prennent énormément de temp à s’exécuter !

Art

Musique : Pink Floyd et son album lumineux

Le choix de la pochette d’album « The Dark Side of the Moon » n’a, d’après les membres du groupe, pas de signification précise. Lassés des photographies chargées ou des collages compliqués, ceux-ci cherchaient un visuel simple et facile à retenir. C’est bien le cas puisque 50 ans après, l’image du spectre lumineux se dispersant à travers un prisme est presque toujours associée au groupe Pink Floyd.

Vidéo de présentation du projet

De la physique à la musique

Lors du feuilletage d’un manuel de physique, l’attention du graphiste des Pink Floyd a été retenue par une photographie en noir et blanc d’un prisme à travers lequel se dispersait la lumière. L’idée lui est alors venue de choisir cette image en guise de pochette d’album.

En physique, un spectre lumineux est le résultat de la décomposition de la lumière par un spectroscope. Il permet d’analyser celle ci grâce aux radiations qui la composent.

Cette image n’est pas sans rappeler les éclairages des concerts où des faisceaux lumineux traversent la scène en se modifiant au contact des musiciens, tel le spectre traversant le prisme.

De la musique à la NSI

Nous avons donc décidé de récréer numériquement cette pochette d’album. Pour ce faire, nous avons utilisé le langage python et l’émulateur Thonny.

Tout d’abord, nous avons instauré le fond de couleur noir en utilisant la fonction bgcolor().

Nous avons ensuite tracé le triangle principal en veillant à le placer au centre. Pour cela, nous avons mis pour point d’abscisse de départ la valeur « -100 » afin que la longueur du triangle soit de « 200 ».

Puis, nous nous sommes penchés sur la partie gauche de notre image en commençant par tirer un trait défini par ses points de coordonnées de départ et d’arrivée.

Effet dégradé à l’intérieur du triangle :

Vient ensuite une partie plus complexe : l’élargissement du trait en dégradé, partant de la couleur initiale du trait pour aller vers le noir de l’arrière plan.

Pour cela, le script effectue des traits en allers-retours (grâce à une boucle for), d’un point défini sur le triangle jusqu’au milieu du triangle. Pour chaque trait, l’opacité (a) diminue au fur et à mesure que le trait se rapproche du milieu du triangle. L’opacité est remise à sa valeur initiale (a=255) avant chaque traçage de trait.

turtle.colormode(255)
for i in range(20):
    penup()
    a = 255
    go to(-40, 100)
    for i in range(41):
        turtle.color(a,a,a)
        pendown()
        turtle.forward(1)
        a += -6
    turtle.right(1)

Et voici le résultat:

Réalisation du triangle et du faisceaux lumineux entrant

Création de l’arc en ciel :

Ensuite, en partant d’un point situé sur la bordure droite du triangle, nous avons créé une boucle for permettant de réaliser les traits de couleur à droite, définis par une liste. Pour que les couleurs attendus soient identiques à celle de la pochette d’album originale, nous avons trouvé leur équivalent en hexadécimal grâce au site « Image Color Picker ».

liste = ["#6f597a","#3476b2","#78ab23", "#f9fc49","#e8b30d","#de2b05",]
goto(63 - 10/6, 81)
turtle.right(12)
turtle.pensize(10)
s=5
for i in range(6):
    turtle.color(liste[i%6])
    pendown()
    turtle.forward(355 + 0.1*i)
    penup()
    goto(58 - 10/6*i, 80 + s + 4*i)
    turtle.left(1)
    s+=-1
Script initial avec ajout de l’arc en ciel

Enfin, nous avons reproduit les commandes de lecture, situées dans la partie inferieure de notre rendu visuel, en utilisant encore une fois des boucles for pour créer des formes géométriques telles que des rectangles ou des triangles.

Afin de créer un effet visuel plus esthétique nous avons aussi intégré les fonctions begin_fill() et end_fill() qui permettent de colorer l’intérieur de formes géométriques telles que le « bouton pause » par exemple.

Nous vous proposons la découverte de notre rendu final ci-dessous, j’espère qu’il vous plaira!

Rendu final du script après exécution

Télécharger le .py :

Pour finir, nous vous partageons l’intégralité de notre projet afin que vous puissiez le découvrir plus en détail !

Art

Astronomie : Le Seigneur des Anneaux … d’Uranus

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) :