Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- from tkinter import messagebox
- from tkinter import ttk
- import os, sys, math, time
- from PIL import Image, ImageTk
- PATH = os.getcwd() + "\\"
- WIDTH = 400
- HEIGHT = 400
- DEPTH = 5000
- ZOOM_FACTOR = 5
- MAX_COLOR = 255
- RECURS_LIMIT = 999999
- sys.setrecursionlimit(RECURS_LIMIT)
- MINUTE = 60
- RGB_PALETTE = [(128,0,0), (139,0,0), (165,42,42), (178,34,34), (220,20,60),
- (255,0,0), (255,99,71), (255,127,80), (205,92,92),
- (240,128,128), (233,150,122), (250,128,114), (255,160,122),
- (255,69,0), (255,140,0), (255,165,0), (255,215,0),
- (184,134,11), (218,165,32), (238,232,170), (189,183,107),
- (240,230,140), (128,128,0), (255,255,0), (154,205,50),
- (85,107,47), (107,142,35), (124,252,0), (127,255,0),
- (173,255,47), (0,100,0), (0,128,0), (34,139,34), (0,255,0),
- (50,205,50), (144,238,144), (152,251,152), (143,188,143),
- (0,250,154), (0,255,127), (46,139,87), (102,205,170),
- (60,179,113), (32,178,170), (47,79,79), (0,128,128),
- (0,139,139), (0,255,255), (224,255,255), (0,206,209),
- (64,224,208), (72,209,204), (175,238,238), (127,255,212),
- (176,224,230), (95,158,160), (70,130,180), (100,149,237),
- (0,191,255), (30,144,255), (173,216,230), (135,206,235),
- (135,206,250), (25,25,112), (0,0,128), (0,0,139), (0,0,205),
- (65,105,225), (138,43,226), (75,0,130), (72,61,139),
- (106,90,205), (123,104,238), (147,112,219), (139,0,139),
- (148,0,211), (153,50,204), (186,85,211), (128,0,128),
- (216,191,216), (221,160,221), (238,130,238), (255,0,255),
- (218,112,214), (199,21,133), (219,112,147), (255,20,147),
- (255,105,180), (255,182,193), (255,192,203), (250,235,215),
- (245,245,220), (255,228,196), (255,235,205), (245,222,179),
- (255,248,220), (255,250,205), (250,250,210), (255,255,224),
- (139,69,19), (160,82,45), (210,105,30), (205,133,63),
- (244,164,96), (222,184,135), (210,180,140), (188,143,143),
- (255,228,181), (255,222,173), (255,218,185), (255,228,225),
- (255,240,245), (250,240,230), (253,245,230), (255,239,213),
- (255,245,238), (245,255,250), (112,128,144), (119,136,153),
- (176,196,222), (230,230,250), (255,250,240), (240,248,255),
- (248,248,255), (240,255,240), (255,255,240), (240,255,255),
- (255,250,250), (0,0,0), (105,105,105), (128,128,128),
- (169,169,169), (192,192,192), (211,211,211), (220,220,220),
- (245,245,245), (255,255,255)]
- #Class representing complex numbers
- class Complex:
- def __init__(self, real, imag=0.0):
- self.real = real
- self.imag = imag
- def __add__(self, other):
- return Complex(self.real + other.real,
- self.imag + other.imag)
- def __sub__(self, other):
- return Complex(self.real - other.real,
- self.imag - other.imag)
- def __mul__(self, other):
- return Complex(self.real*other.real - self.imag*other.imag,
- self.imag*other.real + self.real*other.imag)
- def __abs__(self):
- return math.sqrt((self.real * self.real) + (self.imag * self.imag))
- def __str__(self):
- return '(%g, %g)' % (self.real, self.imag)
- def __repr__(self):
- return 'Complex' + str(self)
- #Class to represent the mandelbrot fractal
- class Fractal:
- #Pre: None Post: Initialization of the class attributes
- def __init__(self):
- self.palette()
- self.range = None
- self.image = None
- self.c = None
- self.min_a = None
- self.max_a = None
- self.min_b = None
- self.max_b = None
- self.canvas = None
- self.iterations = 0
- self.center_x, self.center_y = None, None
- self.progress_bar = None
- self.save = True
- #This was a quick fix to get the number of colors to be ~255
- def palette(self):
- for i in range(len(RGB_PALETTE) - 1):
- RGB_PALETTE.insert(i + 1, self.linear_interp(RGB_PALETTE[i], RGB_PALETTE[i + 1], i))
- def read_start(self, a_file):
- a_list = []
- a_file = open(a_file, 'r')
- a_list = a_file.readlines()
- a_list = a_list[0][:-1]
- a_list = a_list.split(' ')
- self.range = float(a_list[2])
- self.center_x, self.center_y = float(a_list[0]), float(a_list[1])
- self.min_a = float(a_list[0]) - (float(a_list[2]) / 2)
- self.max_a = float(a_list[0]) + (float(a_list[2]) / 2)
- self.min_b = float(a_list[1]) - (float(a_list[2]) / 2)
- self.max_b = float(a_list[1]) + (float(a_list[2]) / 2)
- a_file.close()
- def linear_interp(self, color_1, color_2, i):
- r = (color_1[0] * (1 - i)) + (color_2[0] * i)
- g = (color_1[1] * (1 - i)) + (color_2[1] * i)
- b = (color_1[2] * (1 - i)) + (color_2[2] * i)
- rgb_list = [r, g, b]
- for value in rgb_list:
- if value > MAX_COLOR:
- rgb_list[rgb_list.index(value)] = MAX_COLOR
- if value < 0:
- rgb_list[rgb_list.index(value)] = abs(value)
- return (rgb_list[0], rgb_list[1], rgb_list[2])
- def rgb_to_hex(self, color):
- return "#%02x%02x%02x" % color
- def mandel(self, x, y, z, iteration):
- mod_z = math.sqrt((z.real * z.real) + (z.imag * z.imag))
- #If its not in the set or we have reached the maximum depth
- if mod_z >= 100.0 or iteration == DEPTH:
- if iteration < DEPTH:
- if iteration > MAX_COLOR:
- iteration = iteration % MAX_COLOR
- nu = math.log2(math.log2(abs(mod_z)) / math.log2(2)) / math.log2(2)
- value = iteration + 5 - nu
- print(iteration)
- color_1 = RGB_PALETTE[math.floor(value)]
- color_2 = RGB_PALETTE[math.floor(value) + 1]
- fractional_iteration = value % 1
- color = self.linear_interp(color_1, color_2, fractional_iteration)
- self.canvas.create_line(x, y, x + 1, y + 1,
- fill = self.rgb_to_hex(color))
- else:
- z = (z * z) + self.c
- self.mandel(x, y, z, iteration + 1)
- return z
- def create_image(self):
- begin = time.time() #For computing how long it took (start time)
- diam_a = self.max_a - self.min_a
- diam_b = self.max_b - self.min_b
- for y in range(HEIGHT):
- for x in range(WIDTH):
- self.c = complex(x * (diam_a / WIDTH) + self.min_a,
- y * (diam_b / HEIGHT) + self.min_b)
- constant = 1.0
- z = self.c
- bound = 1 / 4
- q = (self.c.real - bound)**2 + (self.c.imag * self.c.imag)
- x1 = self.c.real
- y2 = self.c.imag * self.c.imag
- sixteenth = 1 / 16
- if not (q*(q + (x1 - bound)) < y2 / (constant * 4) or
- (x1 + constant)**2 + y2 < sixteenth):
- #value of the recursive call while it is not in the set
- z = self.mandel(x, y, z, iteration = 0)
- if self.progress_bar != None:
- self.progress_bar["value"] = y
- self.canvas.update()#Update the progress bar
- print("Took %s Minutes to Render" % ((time.time() - begin) / MINUTE))
- def create_canvas(self):
- self.canvas = tk.Canvas(root, width = WIDTH, height = HEIGHT)
- self.make_menu()
- self.progress_bar = ttk.Progressbar(orient = "horizontal",
- length = WIDTH,
- mode = "determinate",
- maximum = HEIGHT,
- value = 0)
- self.progress_bar.pack(side = "bottom")
- self.canvas.pack()
- def zoom_in(self, event):
- self.canvas.delete(tk.ALL)
- messagebox.showinfo("Zooming in the Mandelbrot",
- "Please wait until the next image loads")
- self.range = float(self.range / ZOOM_FACTOR)
- self.center_x = float((self.canvas.canvasx(event.x) /
- float(WIDTH)) *
- (self.max_a - self.min_a) + self.min_a)
- self.center_y = float((self.canvas.canvasy(event.y) /
- float(HEIGHT)) *
- (self.max_b - self.min_b) + self.min_b)
- #Compute new boundaries
- self.min_a = self.center_x - (self.range)
- self.max_a = self.center_x + (self.range)
- self.min_b = self.center_y - (self.range)
- self.max_b = self.center_y + (self.range)
- self.create_image() #Redraw the image
- def zoom_out(self, event):
- self.canvas.delete(tk.ALL)
- messagebox.showinfo("Zooming in the Mandelbrot",
- "Please wait until the next image loads")
- self.range = float(self.range * ZOOM_FACTOR)
- self.center_x = float((self.canvas.canvasx(event.x) /
- float(WIDTH)) *
- (self.max_a - self.min_a) + self.min_a)
- self.center_y = float((self.canvas.canvasy(event.y) /
- float(HEIGHT)) *
- (self.max_b - self.min_b) + self.min_b)
- #Compute new boundaries
- self.min_a = self.center_x - (self.range)
- self.max_a = self.center_x + (self.range)
- self.min_b = self.center_y - (self.range)
- self.max_b = self.center_y + (self.range)
- self.create_image() #Redraw the image
- root = tk.Tk()
- root.title("Mandelbrot Viewer")
- if __name__ == '__main__':
- fractal = Fractal()
- if fractal.range == None:
- fractal.read_start("zoom_location.txt")
- fractal.create_canvas()
- fractal.create_image()
- root.bind("<Double-Button-1>", fractal.zoom_in)
- root.bind("<Double-Button-3>", fractal.zoom_out)
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement