test_fractale_3.py

Created by dan-tabet

Created on September 30, 2025

3.66 KB


# Folded Spiral Julia - fractale inventée pour NumWorks
# Version pixel-par-pixel (fiable). Utilise kandinsky.
# Modifie C, ZOOM, angle_scale pour obtenir d'autres formes.

import kandinsky
import math

# -- Configuration écran NumWorks (ajuste si nécessaire) --
WIDTH, HEIGHT = 320, 222

# -- Paramètres de la fractale --
C = complex(-0.7, 0.27015)   # paramètre de Julia (change beaucoup la forme)
MAX_ITER = 60                # itérations max (augmenter rend plus de détails)
ESCAPE_RADIUS = 4.0
ZOOM = 1.6                   # <1 = zoom out, >1 = zoom in
CENTER = complex(0.0, 0.0)   # recentrage dans le plan complexe

# contrôle la force de la rotation dépendante de l'itération
angle_scale = 0.35

# vitesse/qualité : si trop lent, réduire WIDTH/HEIGHT ou MAX_ITER
# -----------------------------------------------------------------

def pixel_to_complex(px, py):
    """Convertit coord. pixel -> complexe en tenant compte du ratio écran."""
    # on veut que la largeur couvre environ [-scale, +scale]
    aspect = WIDTH / HEIGHT
    scale_x = ZOOM * 1.5
    scale_y = scale_x / aspect
    x = (px / (WIDTH - 1)) * (2 * scale_x) - scale_x
    y = (py / (HEIGHT - 1)) * (2 * scale_y) - scale_y
    # on inverse y pour que l'origine graphique corresponde au plan usuel
    return complex(x, -y) + CENTER

def hsv_to_rgb(h, s, v):
    """Convertit HSV (h en 0..1) -> RGB tuple 0..255 (simple impl)."""
    if s == 0.0:
        r = g = b = int(v * 255)
        return (r, g, b)
    i = int(h * 6.0)  # secteur 0..5
    f = (h * 6.0) - i
    p = v * (1.0 - s)
    q = v * (1.0 - s * f)
    t = v * (1.0 - s * (1.0 - f))
    i = i % 6
    if i == 0:
        r, g, b = v, t, p
    elif i == 1:
        r, g, b = q, v, p
    elif i == 2:
        r, g, b = p, v, t
    elif i == 3:
        r, g, b = p, q, v
    elif i == 4:
        r, g, b = t, p, v
    else:
        r, g, b = v, p, q
    return (int(r * 255), int(g * 255), int(b * 255))

def iter_to_color(i, z):
    """Mapping couleur : on utilise une teinte dépendante de i + lissage."""
    if i >= MAX_ITER:
        return (0, 0, 0)  # noir si dans l'ensemble (non divergé)
    # lissage (smooth coloring)
    zn = abs(z)
    if zn == 0:
        frac = 0.0
    else:
        # valeur lissée approximative
        frac = math.log(math.log(zn + 1.0) + 1.0 + 1e-9)  # sécurité denom
    # compose une teinte en mélangeant i et frac
    h = (i / MAX_ITER + 0.5 * frac) % 1.0
    s = 0.8
    v = 0.9 if i < MAX_ITER else 0.0
    return hsv_to_rgb(h, s, v)

def folded_spiral_iter(z0):
    """Itération personnalisée : pliage + rotation dépendante de l'itération + z^2 + C."""
    z = z0
    for i in range(MAX_ITER):
        # 1) pliage : valeurs absolues -> symétrie
        z = complex(abs(z.real), abs(z.imag))
        # 2) rotation variante selon l'itération
        theta = math.sin(i * angle_scale) * (0.6 + 0.4 * math.cos(i * 0.13))
        r_cos = math.cos(theta)
        r_sin = math.sin(theta)
        # multiplication complexe par rotation r = cos + i sin
        z = complex(z.real * r_cos - z.imag * r_sin,
                    z.real * r_sin + z.imag * r_cos)
        # 3) la classique z^2 + C
        z = z * z + C
        # test d'échappement (module carré pour perf)
        if (z.real * z.real + z.imag * z.imag) > (ESCAPE_RADIUS * ESCAPE_RADIUS):
            return i, z
    return MAX_ITER, z

def draw():
    """Trace la fractale sur l'écran (pixel par pixel)."""
    for py in range(HEIGHT):
        for px in range(WIDTH):
            z0 = pixel_to_complex(px, py)
            i, z = folded_spiral_iter(z0)
            color = iter_to_color(i, z)
            kandinsky.set_pixel(px, py, color)

# Lancer le dessin
draw()

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.