Une pensée pour Benoît Mandelbrot

Benoît Mandelbrot, l'inventeur des objets fractals, est décédé le 14 octobre 2010.

Quelques lignes de JavaScript en son honneur:

(function(canevas) {
    if (canevas.getContext) {

        var largeur = parseInt(canevas.width, 10);  // px
        var hauteur = parseInt(canevas.height, 10); // px
        var definition = largeur > hauteur ?
                         0.4*hauteur: 0.4*largeur;  // px/unité

        var origine_x = largeur / 1.3;
        var origine_y = hauteur / 2;

        var contexte = canevas.getContext("2d");
        var image_data = contexte.getImageData(0, 0, largeur, hauteur);
        var pixels = image_data.data;

        var pixel = 0;  // Le numéro du pixel courant.
        var index = 0;  // L'index courant dans le tableau «pixels».
                        // Incrémenté de 4 à chaque itération.

        // Pour éviter de bloquer l'interface, le
        // calcul est découpé en tranches de 50 ms.
        setTimeout(function() {
            var start_time = +new Date();
            do {
                var max_iter = 100;
                do {
                    // Déterminer la position du pixel dans le plan
                    // des complexes à partir de son index.
                    var x = (pixel % largeur - origine_x) / definition;
                    var y = (pixel / largeur - origine_y) / definition;

                    // Évaluer la convergence pour ce point.
                    var mu = mandelbrot(x, y, 40, 3);

                    // Coloration volontairement simpliste. À ajuster
                    // selon les besoins.
                    var red = mu * 12;
                    var green = mu * 12;
                    var blue = mu * 55;

                    if (red > 255) red = 255;
                    if (green > 255) green = 255;
                    if (blue > 255) blue = 255;

                    pixels[index  ] = red;
                    pixels[index+1] = green;
                    pixels[index+2] = blue;
                    pixels[index+3] = 255;

                    index += 4;
                    pixel++;
                    max_iter--;
                } while (index < pixels.length &&
                            max_iter != 0)

            } while (index < pixels.length &&
                        (+new Date() - start_time < 50));

            if (index < pixels.length) {
                setTimeout(arguments.callee, 25);
            } else {
                contexte.putImageData(image_data, 0, 0);
            }
        }, 25);
    }

    // Les composantes d'un nombre complexe, a et b.
    // Retourne le niveau de convergence normalisé.
    function mandelbrot(a, b, max_iter, escape_radius) {

        var x = y = 0;
        var x_n1 = y_n1 = 0;

        var iter_count = 0;
        var max_iter = max_iter || 18;
        var escape_radius = escape_radius || 3;

        while (Math.sqrt(x*x+y*y) < escape_radius &&
                    iter_count < max_iter) {

            x_n1 = x*x - y*y + a;
            y_n1 = 2*x*y + b;
            x = x_n1;
            y = y_n1;
            iter_count++;
        }

        // Normaliser avant de retourner le niveau de convergence.
        return iter_count - (Math.log(Math.log(Math.sqrt(x*x+y*y)))) / Math.log(2.0);
    }

})(document.getElementById("surface"));

Ce qui donne l'ensemble de Mandelbrot[1]:

L'ensemble de Mandelbrot.

Pour un tour d'horizon complet sur la coloration des fractales, voir la thèse de Jussi Härkönen: On Smooth Fractal Coloring Techniques.

  1. Le navigateur doit évidemment supporter les canevas, sans quoi une simple image du résultat sera affichée.