2015-04-16 1 views
5

Je m'intéresse beaucoup aux fractales, mais je n'ai pas eu l'occasion de les appliquer jusqu'à récemment. J'ai d'abord mis en place un jeu de mandelbrot en noir et blanc puis j'ai essayé d'y ajouter des couleurs.Ajouter des couches de couleur à l'ensemble de mandelbrot

Voici la mise en œuvre de mon Mandelbrot (je me sers org.apache.commons.math3.complex.Complex pour les nombres complexes)

public class MyMandelbrot { 

    public static int numberOfIterationsToCheck(Complex z0, int max) { 
     Complex z = z0; 
     for (int t = 0; t < max; t++) { 
      if (z.abs() > 2.0) return t; 
      z =z.multiply(z).add(z0); 
     } 
     return max; 
    } 

    public static void main(String[] args) { 
     double xc = Double.parseDouble(args[0]); 
     double yc = Double.parseDouble(args[1]); 
     double size = Double.parseDouble(args[2]); 

     int N = 512; 
     int max = 255; 

     Viewer viewer = new Viewer(N, N); 
     for (int i = 0; i < N; i++) { 
      for (int j = 0; j < N; j++) { 
       double x0 = xc - size/2 + size*i/N; 
       double y0 = yc - size/2 + size*j/N; 
       Complex z0 = new Complex(x0, y0); 
       int gray = max - numberOfIterationsToCheck(z0, max); 

       Color color = new Color(gray, gray, gray); 
       if (z0.abs() > 2.0) { 

        color = new Color(gray, 128, gray); 
       } else if (z0.abs() > 2.0 && numberOfIterationsToCheck(z0,  max) > max/2) { 
        color = new Color(255, gray, 255); 
       } else if (z0.abs() > 2.0 && numberOfIterationsToCheck(z0,  max) < max/2) { 
        color = new Color(gray, 128,128); 
       } 

       else if (z0.abs() > 1.0 && numberOfIterationsToCheck(z0,  max) < max/2) { 
        color = new Color(128, gray, 128); 
       } else if (z0.abs() > 1.0) { 

        color = new Color(128, gray, 128); 
       } 

       else if (z0.abs() <= 1.0) { 
        color = new Color(gray, gray, 128); 
       } 

       viewer.set(i, N-1-j, color); 
      } 
     } 
     viewer.show(); 
    } 

} 

J'utilise une classe Viewer personnalisée pour afficher l'ensemble après le dessin dans un objet image. Voici la méthode set de la visionneuse

public void set(int col, int row, Color color) { 
    if (col < 0 || col >= width()) throw new IndexOutOfBoundsException("col must be between 0 and " + (width()-1)); 
    if (row < 0 || row >= height()) throw new IndexOutOfBoundsException("row must be between 0 and " + (height()-1)); 
    if (color == null) throw new NullPointerException("can't set Color to null"); 
    if (isOriginUpperLeft) image.setRGB(col, row, color.getRGB()); 
    else     image.setRGB(col, height - row - 1, color.getRGB()); 
} 

Le code rend l'ensemble correctement mais je n'obtiens pas le résultat attendu. Ce que je veux être en mesure de produire une couleur semblable à ces ensemble

beautiful mandelbrot

Ou cette

Beautiful mandelbrot II

Mais je ne pouvais pas obtenir un ensemble plus colorée que cela.

not very beautiful mandelbrot

J'ai lu une explication théorique à ce sujet here et here, mais je fais évidemment quelque chose de mal dans la pratique. Quel est le problème avec mon approche de coloration? Comment puis-je le réparer? Merci

Répondre

3

Dans les exemples que vous montrez, la couleur est simplement basée sur le nombre d'itérations avant que le point n'échappe, et non sur la coordonnée complexe initiale z0. Une approche consiste à utiliser des valeurs de couleur Teinte-Saturation-Luminosité à l'aide getHSBColor() et changer la teinte en fonction du nombre d'itérations avant qu'il échappe, par exemple:

 double x0 = xc - size/2 + size*i/N; 
     double y0 = yc - size/2 + size*j/N; 
     Complex z0 = new Complex(x0, y0); 
     int escapeIterations = numberOfIterationsToCheck(z0, max); 

     // set color varying hue based on escape iterations: 
     Color color = Color.getHSBColor((float)escapeIterations/(float)max, 1.0f, 1.0f); 

     viewer.set(i, N-1-j, color); 

Le code ci-dessus ne change pas la saturation ou la luminosité (les deux sont réglés sur 1.0) mais vous pouvez les modifier aussi en fonction du type d'effet que vous voulez.

Vous pouvez faire le cycle de couleur à travers le cercle de couleur des teintes plus d'une fois en multipliant la valeur de teinte par exemple constante:

(float)escapeIterations * 2.0f/(float)max 

Vous pouvez également ajouter une constante pour le faire démarrer à une couleur particulière .

Parce que escapeIterations est un int, la couleur sautera par étapes pour chaque itération. Vous pouvez rendre les couleurs plus lisse en retournant un flotteur de numberOfIterationsToCheck:

public static float numberOfIterationsToCheckSmooth(Complex z0, int max) { 
    Complex z = z0; 
    for (int t = 0; t < max; t++) { 
     double fAbs = z.abs(); 
     if (fAbs > 2.0) 
     { 
      // based on the final value, add a fractional amount based on 
      // how much it escaped by (fAbs will be in the range of 2 to around 4):     
      return (float)t + (2.0f - (Math.log(fAbs)/Math.log(2.0))); 
     } 
     z =z.multiply(z).add(z0); 
    } 
    return (float)max; 
} 

Enfin, une autre approche qui donnera plus de liberté et de contrôle des couleurs est d'utiliser une table de couleurs, une pour chaque itération jusqu'à maximum , et optionnellement interpoler entre eux.

+0

merci pour la réponse. Je vais appliquer dès que possible – alainlompo

+0

OK, permettez-moi de l'appliquer dans quelques minutes et je serai de retour – alainlompo

+0

merci, c'est excellent! – alainlompo