[Edu-sig] Fractals

Jaime E. Villate villate at gnu.org
Fri Apr 28 12:58:24 CEST 2006


On Thu, 2006-04-27 at 17:59 -0700, kirby urner wrote:
> So then as an example of chaotic, we should import from cmath and
> simply explore the feedback loop z = z**2 + c for convergence or
> divergence.  Actually, we don't really need cmath

For kids who do not know about complex numbers, it might be easier
to introduce fractals in the xy plane. It is also a good idea to
make a graph instead of looking a the numerical sequence; that will
be more exciting. We can use a simple graphic format: PBM.

Here is an example: We first define two functions on the xy plane

>>> def f(x,y):
        return 0.6*x*(1+2*x)+0.8*y*(x-1)-y**2-0.9
>>> def g(x,y):
        return 0.1*x*(1-6*x+4*y)+0.1*y*(1+9*y)-0.4

we also need to define the domain we are going to look at
>>> xmin, ymin, xmax, ymax = -1.1, -0.9, 0.3, 0.2

initial values for x and y and the number of iterations
>>> x, y = -0.5, 0
>>> num = 50000

the resolution of the graph will be 480 by 480 pixels, but since
the pixels are grouped into bytes, we then use:
>>> resx, resy = 60, 480

to transform eight pixel values into a byte, we will use this
>>> mask = [128,64,32,16,8,4,2,1]

the pixel values will be saved into an array of binary numbers,
initialized to zero
>>> from array import array
>>> pixels = array('B')
>>> for i in range(resx*resy):
        pixels.append(0)

Before we start with the iterations we will also need a couple
of functions to transform our (x,y) coordinates into an (i,j)
pixel position on the screen:

>>> def screenx(xmin,xmax,resx,x):
        return int((resx*8-1)*(x-xmin)/(xmax-xmin) + 0.5)
>>> def screeny(ymin,ymax,resy,y):
        return int(resy - 0.5 - (resy-1)*(y-ymin)/(ymax-ymin))

Finally, we are ready to do the iterations. We need a couple
of additional operators (modulus and exclusive or):

>>> from operator import mod, or_
>>> for j in range(num):
        aux = x
        x = f(x,y)
        y = g(aux,y)
        if x>=xmin and x<=xmax and y>=ymin and y<=ymax:
            xi = screenx(xmin,xmax,resx,x)
            yi = screeny(ymin,ymax,resy,y)
            n = resx*yi + xi/8
            pixels[n] = or_(pixels[n], mask[mod(xi,8)])

We now create the PBM file:

>>> pbmfile = open('fractal1.pbm','w') 

The file should start with a "magic number" P4, followed by the x and y
resolutions, in pixels:
>>> pbmfile.write('P4\n%s %s\n' % (8*resx, resy))

we now transfer the array of pixels to the file, and close it
>>> pixels.tofile(pbmfile)
>>> pbmfile.close()

The file fractal1.pbm shows the fractal.

The concept of fractal is explained by zooming into the fractal. We
need a bigger number of iterations to get a sharper image:

>>> xmin, ymin, xmax, ymax = -0.8, -0.4, -0.6, -0.2
>>> x, y = -0.5, 0
>>> num = 500000
>>> pixels = array('B')
>>> for i in range(resx*resy):
            pixels.append(0)

>>> for j in range(num):
            aux = x
            x = f(x,y)
            y = g(aux,y)
            if x>=xmin and x<=xmax and y>=ymin and y<=ymax:
                xi = screenx(xmin,xmax,resx,x)
                yi = screeny(ymin,ymax,resy,y)
                n = resx*yi + xi/8
                pixels[n] = or_(pixels[n], mask[mod(xi,8)])

>>> pbmfile = open('fractal2.pbm','w')
>>> pbmfile.write('P4\n%s %s\n' % (8*resx, resy))
>>> pixels.tofile(pbmfile)
>>> pbmfile.close()

File fractal2.pbm is the enlargement of a small part of the fractal.

Regards,
Jaime

P.S. another fun and easy way to introduce fractals is with the "chaos
game".



More information about the Edu-sig mailing list