Advertisement
here2share

# Tk_Wraps_Mandelbrot.py

Nov 10th, 2023
827
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.42 KB | None | 0 0
  1. # Tk_Wraps_Mandelbrot.py
  2.  
  3. from tkinter import *
  4. from functools import wraps
  5. from PIL import Image, ImageTk
  6. import sys
  7.  
  8. ww = 200
  9. hh = 200
  10.  
  11. root = Tk()
  12. root.title("Tk_Wraps_Mandelbrot")
  13. root.geometry('{}x{}'.format(ww * 2, hh))
  14.  
  15. canvas_main = Canvas(root, width=ww, height=hh)
  16. canvas_main.pack(side=LEFT, fill="both", expand=True)
  17.  
  18. canvas_debug = Canvas(root, width=ww, height=hh, bg='white')
  19. canvas_debug.pack(side=LEFT, fill="both", expand=True)
  20.  
  21. zoom_factor = 1.5
  22.  
  23. xRange = 1.0
  24. yRange = 1.0
  25. xOffset = 0
  26. yOffset = 0
  27. cx = ww // 2
  28. cy = hh // 2
  29. dx = dy = 0
  30.  
  31. precision = 400
  32.  
  33. def rgb2hex(rgb):
  34.     r, g, b = rgb
  35.     return "#{:02x}{:02x}{:02x}".format(r, g, b)
  36.  
  37. rainbow = []
  38. def z(r, g, b):
  39.     rainbow.append((r, g, b))
  40.  
  41. r, g, b = 255, 0, 0
  42. for g in range(256):
  43.     z(r, g, b)
  44. for r in range(254, -1, -1):
  45.     z(r, g, b)
  46. for b in range(256):
  47.     z(r, g, b)
  48. for g in range(254, -1, -1):
  49.     z(r, g, b)
  50. for r in range(256):
  51.     z(r, g, b)
  52. for b in range(254, -1, -1):
  53.     z(r, g, b)
  54. Lr = len(rainbow) - 1
  55.  
  56. img = Image.new('RGB', (ww, hh))
  57. pixels = img.load()
  58.  
  59. def memoize(func):
  60.     cache = {}
  61.     @wraps(func)
  62.     def wrapper(*args, **kwargs):
  63.         key = str(args) + str(kwargs)
  64.         if key not in cache:
  65.             cache[key] = func(*args, **kwargs)
  66.         return cache[key]
  67.     return wrapper
  68. sys.setrecursionlimit(10_000)
  69.  
  70. @wraps('cache_mandelbrot')
  71. def cache_mandelbrot(x0, y0):
  72.     x = 0.0
  73.     y = 0.0
  74.     k = 4000
  75.     for i in range(precision + 1):
  76.         x_new = x * x - y * y + x0
  77.         y = 2 * x * y + y0
  78.         x = x_new
  79.         if x * x + y * y > 10:
  80.             k = 12
  81.             break
  82.     j = (x * x + y * y) ** 0.5
  83.     j = int(i * (i * 10) + j * k) % Lr
  84.     return rainbow[j]
  85.  
  86. def calculate_mandelbrot(xRange, yRange):
  87.     canvas_debug.create_text(10, 20, anchor=NW, text="Processing, Please Wait...")
  88.     canvas_debug.update()
  89.     canvas_main.delete("all")
  90.     for row in range(hh):
  91.         for col in range(ww):
  92.             x0 = ((row - 50 - cx + dx + xOffset * xRange) * 3 / ww) / xRange
  93.             y0 = ((col - cy + dy + yOffset * yRange) * 2.5 / hh) / yRange
  94.             pixels[col, row] = cache_mandelbrot(x0, y0)
  95.     canvas_main.image = ImageTk.PhotoImage(img)
  96.     canvas_main.create_image(0, 0, anchor=NW, image=canvas_main.image)
  97.     update_debug_canvas()
  98.  
  99. def update_debug_canvas():
  100.     canvas_debug.delete("all")
  101.     canvas_debug.create_text(10, 50, anchor=NW, text=f"x offset: {xOffset*-1}")
  102.     canvas_debug.create_text(10, 70, anchor=NW, text=f"y offset: {yOffset*-1}")
  103.     canvas_debug.create_text(10, 90, anchor=NW, text=f"zoom_factor: {xRange}")
  104.  
  105. def on_mouse_down(event):
  106.     global drag_data
  107.     drag_data = {'x': event.x, 'y': event.y}
  108. def on_mouse_move(event):
  109.     global dx, dy
  110.     dx = (event.x - drag_data['x'])
  111.     dy = (event.y - drag_data['y'])
  112.     canvas_main.coords("all", dx, dy)
  113.     update_debug_canvas()
  114. def on_mouse_up(event):
  115.     global xOffset, yOffset, dx, dy
  116.     dx /= yRange
  117.     dy /= xRange
  118.     xOffset -= dy
  119.     yOffset -= dx
  120.     dx = dy = 0
  121.     calculate_mandelbrot(xRange, yRange)
  122.  
  123. def on_key_up(event):
  124.     global xRange, yRange
  125.     xRange, yRange = (xRange * zoom_factor, yRange * zoom_factor)
  126.     calculate_mandelbrot(xRange, yRange)
  127. def on_key_down(event):
  128.     global xRange, yRange
  129.     xRange, yRange = (xRange / zoom_factor, yRange / zoom_factor)
  130.     calculate_mandelbrot(xRange, yRange)
  131.  
  132. canvas_main.bind('<Button-1>', on_mouse_down)
  133. canvas_main.bind('<B1-Motion>', on_mouse_move)
  134. canvas_main.bind('<ButtonRelease-1>', on_mouse_up)
  135. root.bind('<Down>', on_key_down)
  136. root.bind('<Up>', on_key_up)
  137.  
  138. calculate_mandelbrot(xRange, yRange)
  139.  
  140. root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement