2015-04-16 21 views
5

Ho un grande interesse per i frattali ma non ho avuto l'opportunità di implementarli fino a poco tempo fa. In primo luogo ho implementato un set di mandelbrot in bianco e nero, quindi ho provato ad aggiungere colori ad esso.Aggiunta di livelli di colore al set mandelbrot

Qui è la realizzazione del mio Mandelbrot (sto usando org.apache.commons.math3.complex.Complex per i numeri complessi)

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(); 
    } 

} 

Sto usando una classe visualizzatore personalizzato per visualizzare il set dopo aver disegnato in un oggetto immagine. Ecco il metodo impostato del Viewer

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()); 
} 

Il codice sta visualizzando correttamente il set ma non sto ottenendo il risultato previsto. Quello che voglio è essere in grado di produrre un colore simile insieme a questi

beautiful mandelbrot

O questo

Beautiful mandelbrot II

ma non ho potuto ottenere un insieme più colorata di questo.

not very beautiful mandelbrot

Ho letto qualche spiegazione teorica su di esso here e here, ma sono ovviamente facendo qualcosa di sbagliato nella pratica. Cosa c'è di sbagliato nel mio approccio alla colorazione? Come posso ripararlo? Grazie

risposta

3

Negli esempi mostrati, il colore si basa solo sul numero di iterazioni prima del punto di escape e non sulla coordinata complessa iniziale z0. Un approccio è quello di utilizzare valori di colore tonalità-saturazione-luminosità utilizzando getHSBColor(), e cambiare la tonalità in base al numero di iterazioni prima che sfugge, ad esempio:

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

Il codice di cui sopra non cambia la saturazione o la luminosità (entrambi sono impostati su 1.0) ma puoi anche modificarli a seconda del tipo di effetto desiderato.

Si potrebbe fare il ciclo di colore attraverso il cerchio di colore di tonalità più di una volta moltiplicando il valore di tonalità da un esempio costante:

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

È inoltre possibile aggiungere una costante per renderlo partono da un colore particolare .

Poiché escapeIterations è un valore int, il colore salterà a passi per ogni iterazione. È possibile rendere i colori più liscia restituendo un galleggiante da 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; 
} 

Infine, un altro approccio che darà la massima libertà e controllo sui colori è quello di utilizzare una tabella di colori, uno per ogni iterazione fino al massimo e facoltativamente interpolare tra di loro.

+0

grazie per la risposta. Applicherò appena possibile – alainlompo

+0

OK, lasciatemi applicare questo in un minuto e torno – alainlompo

+0

grazie, è eccellente! – alainlompo