« Fractales » : différence entre les versions

De FrozenWiki
Aller à la navigation Aller à la recherche
 
Ligne 77 : Ligne 77 :
     DO
     DO
       tmp = a
       tmp = a
       a = a * a + b * b + c
       a = a * a - b * b + c
       bi = 2 * tmp * bi + di
       bi = 2 * tmp * bi + di
       zbar = a * a + bi * bi
       zbar = a * a + bi * bi
Ligne 97 : Ligne 97 :
     DO
     DO
       tmp = a
       tmp = a
       a = a * a + b * b + c
       a = a * a - b * b + c
       bi = 2 * tmp * bi + di
       bi = 2 * tmp * bi + di
       zbar = a * a + bi * bi
       zbar = a * a + bi * bi

Dernière version du 21 avril 2012 à 08:04

Mandelbrot et Julia

Comment que l'on les calcule donc ?

Mandelbrot et Julia sont définies par la suite :

<math>Z_{n+1} = Z_n^2 + C</math>

  • Z et C sont deux nombres complexes :
    • <math>Z = a + bi</math>
    • <math>C = c + di</math>
  • Pour Mandelbrot C est le point à calculer :
    • c est l'absisse
    • di est l'ordonnée
    • on part avec Z = 0

  • Pour Julia Z est le point à calculer :
    • a est l'absisse
    • bi est l'ordonnée
    • on prend une constante pour C

On aura donc :

<math>(a + bi)_{n+1} = (a_n + bi_n)^2 + c + di</math>

soit

<math>(a + bi)_{n+1} = a_n^2 +2a_nbi_n + (bi_n)^2 + c + di</math>

avec <math>i^2 = -1</math> ça donne

<math>(a + bi)_{n+1} = a_n^2 + 2a_nbi_n - b_n + c + di</math>

donc pour <math>n+1</math>:

<math>a_{n+1} = a_n^2 -b_n + c</math> et <math>bi_{n+1} = 2a_nbi_n + di</math>

  • le point Z appartient à la fractale si la longueur du vecteur Z (<math>\bar{z}</math> ne tend pas vers l'infini, il est dit un peu partout que si cette longueur dépasse 2, on va tendre vers l'infini...

<math>\bar{z} = \sqrt{a^2 + b^2}</math>

on peut se passer de l'opération avec la racine carrée car <math>\sqrt{4} = 2</math>

donc on peut juste tester <math>\bar{z} < a^2 + b^2 < 4</math>

Et hop, des chtis algorithmes

Pour dessiner la fractale Julia :

c = -0.7
d = -0.1
WHILE x < WIDTH
  WHILE y < HEIGHT
    a = x
    bi = y
    DO
      tmp = a
      a = a * a - b * b + c
      bi = 2 * tmp * bi + di
      zbar = a * a + bi * bi
      i = i + 1
    WHILE i < MAXITER) AND zbar < 4)
    IF zbar < 4:
      PIXEL(x, y)
    y = y + 1
  x = x + 1

Et pour Mandelbrot :

a = 0
bi = 0
WHILE x < WIDTH
  WHILE y < HEIGHT
    c = x
    di = y
    DO
      tmp = a
      a = a * a - b * b + c
      bi = 2 * tmp * bi + di
      zbar = a * a + bi * bi
      i = i + 1
    WHILE i < MAXITER) AND zbar < 4)
    IF zbar < 4:
      PIXEL(x, y)
    y = y + 1
  x = x + 1

Du code, at last !

Voici une version Python de la chose (pygame doit être installé pour faire fonctionner ce petit programme).

Euh... ça se sent dans ce genre de programme que Python est un langage interprété : faut pas s'attendre à une vitesse d'exécution transcendentale !

Outre cette petite lecture, on trouve aussi la version téléchargeable du code ici.

import sys, pygame
from pygame.locals import *

WIDTH = 512
HEIGHT = 512


def show_text(t):
    text = font.render(t, 1, (255, 255, 255))
    textpos = text.get_rect(centerx=screen.get_width()/2,
        centery=screen.get_height()/2)
    screen.blit(text, textpos)
    pygame.display.flip()


def julia(surface): 

    c = -0.78
    di = -0.1
    maxiter = 64

    xmin = -1.5
    ymin = -1.5
    xmax = 1.5
    ymax = 1.5

    # on est obligé de faire une conversion coordonnées des pixels à l'écran <==> coordonnées des points
    # dans le repère (xmin, ymin) / (ymin, ymax)
    dx = (xmax - xmin) / WIDTH
    dy = (ymax - ymin) / HEIGHT

    x = 0
    while x < WIDTH:
        y = 0
        while y < HEIGHT:
            a = xmin + x * dx
            bi = ymin + y * dy
            zbar = a * a + bi * bi

            i = 0
            while i < maxiter and zbar < 4:
                tmp = a
                a = a * a - bi * bi + c
                bi = 2 * tmp * bi + di
                zbar = a * a + bi * bi

                i += 1

            surface.set_at((x, y), (48, 48, 64+i))
 
           y += 1

       x += 1


def mandelbrot(surface):
    maxiter = 64

    xmin = -2.0
    ymin = -1.25
    xmax = 1.25
    ymax = 1.25

    dx = (xmax - xmin) / WIDTH
    dy = (ymax - ymin) / HEIGHT

    x = 0
    while x < WIDTH:
        y = 0
        while y < HEIGHT:
            a = 0
            bi = 0
            c = xmin + x * dx
            di = ymin + y * dy

            zbar = a * a + bi * bi

            i = 0
            while i < maxiter and zbar < 4:
                tmp = a
                a = a * a - bi * bi + c
                bi = 2 * tmp * bi + di
                zbar = a * a + bi * bi

                i += 1

            surface.set_at((x, y), (64+i, 48, 48))

            y += 1

        x += 1


pygame.init()
screen = pygame.display.set_mode( (WIDTH,HEIGHT) )
surface = pygame.Surface( (WIDTH,HEIGHT) )
font = pygame.font.Font(None, 24)

is_julia = False
first = True
while True:
    event = pygame.event.poll()
    if event.type == QUIT:
        break
    if event.type == KEYDOWN and event.key == K_ESCAPE:
        break
    if (event.type == KEYDOWN and event.key == K_SPACE) or first:
        first = False
        if is_julia:
            show_text("Computing Mandelbrot...")
            mandelbrot(screen)
            is_julia = False
        else:
            show_text("Computing Julia...")
            julia(screen)
            is_julia = True

    pygame.display.flip()

Howtos