Search code examples
pythonnumpymathpython-imaging-librarymandelbrot

I'm trying to create a GIF of zooming into the Mandelbrot set in Python but having some trouble with floats


from PIL import Image
import numpy as np
import math

class Fractal(object):

    def __init__(self, resolution=(720,720), x_range=(-2.0,2.0), y_range=(-2.0,2.0), maxIterations=255, zoom=0, zoomRate=0):
        self.resolution = resolution
        self.x_range = x_range
        self.y_range = y_range
        self.maxIterations = maxIterations
        self.zoom = zoom
        self.zoomRate = zoomRate

    def computePixel(self, x, y):
        z = complex(0.0,0.0)
        c = complex(x,y)
        iterations = 0
        while iterations < self.maxIterations or abs(z)<2:
            z = z*z + c
            iterations += 1
        # pixelHue = (360/self.maxIterations)*iterations
        # RGB = hsv_to_rgb(pixelHue, 0.0, 0.0)
        # return RGB
        return iterations

    def generateFrame(self):
        #x_max, x_min, y_max, y_min = self.zoom()
        x_max, x_min, y_max, y_min = (self.x_range[1],self.x_range[0],self.y_range[1],self.y_range[0])
        x_increment = (x_max - x_min)/self.resolution[0]
        print(x_increment)
        y_increment = (y_max - y_min)/self.resolution[1]
        print(y_increment)
        frame = []
        yPixels = []
        for x in np.arange(x_min, x_max, x_increment):
            for y in np.arange(y_min, y_max, y_increment):
                x,y = float(x), float(y)
                iterations = self.computePixel(x,y)
                print(x,y,iterations)
        #         pixel_RGB= self.computePixel(x,y)
        #         yPixels.append(pixel_RGB)
        #     frame.append(yPixels)
        # return frame


    def zoom(self):
        '''this is the change that will happen in one second'''
        x_max = self.x_range[1]-(self.zoomRate/2)
        x_min = self.x_range[0]+(self.zoomRate/2)
        y_max = self.y_range[1]-(self.zoomRate/2)
        y_min = self.y_range[0]+(self.zoomRate/2)
        return (x_max, x_min, y_max, y_min)

    def sweep(self):
        for x in np.arange(self.size[0]):
            for y in np.arange(self.size[1]):
                pass



def hsv_to_rgb(h, s, v):
    if s == 0.0: return (v, v, v)
    i = int(h*6.) # XXX assume int() truncates!
    f = (h*6.)-i; p,q,t = v*(1.-s), v*(1.-s*f), v*(1.-s*(1.-f)); i%=6
    if i == 0: return (v, t, p)
    if i == 1: return (q, v, p)
    if i == 2: return (p, v, t)
    if i == 3: return (p, q, v)
    if i == 4: return (t, p, v)
    if i == 5: return (v, p, q)

f = Fractal()
f.generateFrame()     

Currently, I'm only trying to display the first frame of the GIF, i.e. the non-zoomed-into Mandelbrot set. However, when I try to iterate through all the pixel values the iteration stops at x=-1.8611111111111116 and y=-0.005555555555562641

I'm guessing this is because of some overflow error occurring when y is supposed to be zero, but I don't know how to solve this.

Here's a final screenshot of the command line where I'm printing the real and imaginary parts of all complex numbers with the number of iterations it took for that number to converge (or not if the output is 255).

enter image description here


Solution

  • You need to change your while loop condition to:

    while iterations < self.maxIterations and abs(z)<2:
    

    Otherwise, the loop is running for a long time since abs(z) is less than 2.