16.3 Julia Sets and the Complex Function f(z)z2 c

   

 
Java Number Cruncher: The Java Programmer's Guide to Numerical Computing
By Ronald  Mak

Table of Contents
Chapter  16.   Fractals

16.3 Julia Sets and the Complex Function f ( z ) = z 2 + c

Let's now move to the complex plane and iterate the function f ( z ) = z 2 + c, where z and c are complex numbers. If we let the horizontal axis represent the real parts of the complex numbers and the vertical axis represent their imaginary parts, then we can generate two-dimensional graphs.

We'll need to be able to do some basic complex arithmetic:

graphics/16equ02.gif


Also,

graphics/16equ03.gif


Listing 16-2a shows class Complex in package numbercruncher.mathutils.

Listing 16-2a Class Complex.
 package numbercruncher.mathutils; /**  * Perform basic complex arithmetic.  The complex objects are  * immutable, and complex operations create new complex objects.  */ public class Complex {     /** the real part */        private float real;     /** the imaginary part */   private float imaginary;     /**      * Constructor.      * @param real the real part      * @param imaginary the imaginary part      */     public Complex(float real, float imaginary)     {         this.real      = real;         this.imaginary = imaginary;     }     /**      * Return this complex number's real part.      * @return the real part      */     public float real() { return real; }     /**      * Return this complex number's imaginary part.      * @return the imaginary part      */     public float imaginary() { return imaginary; }     /**      * Compute this complex number's modulus      */     public float modulus()     {         return (float) Math.sqrt(real*real + imaginary*imaginary);     }     /**      * Return whether or not this complex number      * is equal to another one.      * @param z the other complex number      * @return true if equal, false if not      */     public boolean equal(Complex z)     {         return (real == z.real()) && (imaginary == z.imaginary());     }     /**      * Add another complex number to this one.      * @param a the other complex number      * @return a new complex number that is the sum      */     public Complex add(Complex z)     {         return new Complex(real + z.real(),                            imaginary + z.imaginary());     }     /**      * Subtract another complex number from this one.      * @param a the other complex number      * @return a new complex number that is the difference      */     public Complex subtract(Complex z)     {         return new Complex(real - z.real(),                            imaginary - z.imaginary());     }     /**      * Multiply this complex number by another one.      * @param a the other complex number      * @return a new complex number that is the product      */     public Complex multiply(Complex z)     {         return new Complex(real*z.real() - imaginary*z.imaginary(),                            real*z.imaginary() + imaginary*z.real());     }     /**      * Divide this complex number by another one.      * @param a the other complex number      * @return a new complex number that is the quotient      */     public Complex divide(Complex z)     {         float denom = z.real()*z.real() + z.imaginary()*z.imaginary();         float qr    = (real*z.real() + imaginary*z.imaginary())/denom;         float qi    = (imaginary*z.real() - real*z.imaginary())/denom;         return new Complex(qr, qi);     }     /**      * Return the string representation of this complex number.      * @return the string representation      */     public String toString()     {         String operator = (imaginary >= 0) ? "+" : "-";         return real + operator + Math.abs(imaginary) + "i";     } } 

Note that class Complex follows the design pattern of classes java.math.BigDecimal and java.math.BigInteger. Each Complex object is immutable, and a Complex operation generates a new Complex object.

Program 16 C2 iterates complex functions of the form f ( z ) = z 2 + c for various values of c to plot the set of points whose orbits are bounded they do not escape. This set of points whose orbits either converge or cycle is called the Julia set, and the plot is a fractal image. [2] The program forms a complex value z = x + yi for each point in the xy plane. It can accept a manually entered value for the complex number c, or the program can randomly generate a value. Listing 16-2b shows class PlotThread of the program, which performs the iterations and plots the resulting Julia set.

[2] French mathematician Gaston Julia (1893 C1978) was 25 when he first developed his theories on complex functions whose values stay bounded as the functions are iterated. Unfortunately, his work was mostly forgotten until the 1970s.

Listing 16-2b Class PlotThread of Program 16 C2, which plots the Julia set of the complex function f(z) = z 2 + c .
 private static final int MAX_ITERS      = 32; private static final int ESCAPE_MODULUS =  2; /**  * Graph thread class that iterates z^2 + c as z varies over  * each point in the complex plane bounded by the rectangle  * xMin, xMax, yMin, yMax.  */ private class PlotThread extends Thread {     public void run()     {         // Loop over each graph panel pixel.         for (int row = 0; row < h; ++row) {             float y0 = yMax - row*delta;           // row => y0             for (int col = 0; col < w; ++col) {                 float   x0 = xMin + col*delta;     // col => x0                 Complex z  = new Complex(x0, y0);  // z = x0 + y0i                 if (stopFlag) return;                 boolean escaped = false;                 int     iters   = 0;                 float   x       = x0;                 float   y       = y0;                 float   modulus;                 // Iterate z^2 + c, keeping track of the                 // iteration count.                 do {                     z = z.multiply(z).add(c);                     modulus = z.modulus();                     escaped = modulus > ESCAPE_MODULUS;                 } while ((++iters < MAX_ITERS) && (!escaped));                 // Escaped: Set the shade of gray based on the                 // number of iterations needed to escape.  The                 // more iterations, the darker the shade.                 if (escaped) {                     int k = 255 - (255*iters)/MAX_ITERS;                     k = Math.min(k, 240);                     plotPoint(col, row, new Color(k, k, k));                 }                 // No escape: Set the colors based on the                 // last computed modulus.                 else {                     int m = ((int) (100*modulus))                                         /ESCAPE_MODULUS + 1;                     int r = (307*m)&255;                     int g = (353*m)&255;                     int b = (401*m)&255;                     plotPoint(col, row, new Color(r, g, b));                 }             }             // Draw a row of the graph.             drawPlot();             yield();         }     } } 

The values of the orbit of each value of z are complex. To determine whether the orbit escapes or stays bounded, PlotThread tests the moduli of the orbit values. If the modulus of any orbit value is greater than ESCAPE_MODULUS , then the orbit has escaped. If there is no escape after MAX_ITERS number of iterations, then the orbit is bounded.

For each value of z whose orbit escapes, PlotThread plots a point in a shade of gray to represent the point's "escape velocity" the more iterations it took to escape, the darker the shade. If the orbit did not escape, then PlotThread plots a point using a color based on the modulus of the last computed orbit value.

As we can see from Listing 16-2b, the programming is very straightforward, yet it produces beautifully intricate images. Screen 16-2a shows screen shots of two examples of the images this program can generate.

Screen 16-2a. Screen shots of two fractal images of Julia sets produced by Program 16 C2.

graphics/16scr02a1.jpg

graphics/16scr02a2.jpg

Like the bifurcation diagram, the fractal image of a Julia set is recursive. Screen 16-2b shows using the mouse to select a rectangular region to zoom into. Each region resembles the whole image. At "higher magnifications," we can also see more clearly the different escape velocities. The gray shading is darkest at the border of the fractal image, since that is the boundary between points on one side whose orbits are bounded and points on the other side whose orbits barely escaped at the maximum number of iterations.

Screen 16-2b. Zooming into a region of a Julia set.

graphics/16scr02b1.jpg

graphics/16scr02b2.jpg

graphics/16scr02b3.jpg


   
Top
 


Java Number Cruncher. The Java Programmer's Guide to Numerical Computing
Java Number Cruncher: The Java Programmers Guide to Numerical Computing
ISBN: 0130460419
EAN: 2147483647
Year: 2001
Pages: 141
Authors: Ronald Mak

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net