In [214]:
import math
import numpy as np
from enum import Enum
In [215]:
# set start values
zstart = np.complex(-2.5,-1.5)
zend = np.complex(1.0, 1.5)
bailout = np.int(100)
image_width = np.int(50)
image_height = np.int(50)
# enum of fractals that are supported
class FractalType(Enum):
mandelbrot = 1
julia = 2
tricorn = 3
burning_ship = 4
In [216]:
def calc_complex_pos(xpos, ypos):
print (zstart + np.complex(xpos * ((zend.real - zstart.real) / image_width), ypos * ((zend.imag - zstart.imag) / image_height)))
In [217]:
# basic fractal escape time algorithm. i am using a similar approach like in the c++ code
# so this is not very pythonic
def fractal_calc (xpos, ypos, frac_type=FractalType.mandelbrot, julia_c=np.complex(0.285, 0.01), print_fractal=False):
"""
Method to calculate escape time for different fractals
Args:
x (int): Real part as image coordinate
y (int): Imaginary part as image coordinate
frac_type (FractalType): The fractal that should be calculated
julia_c (numpy.Complex): Complex number representing the julia set constant
print_fractal (bool): Print an ascii art fractal
"""
#z = np.complex(0.0, 0.0)
c = zstart + np.complex(xpos * ((zend.real - zstart.real) / image_width),
ypos * ((zend.imag - zstart.imag) / image_height))
z = c
if (frac_type == FractalType.julia):
c = julia_c
print("zO " + str(z))
# using an extra iterations variable here because this is essentially what we are doing in c++ as well.
iterations = 0
for i in range(bailout):
if (abs(z) >= 2.0): # check the radius
break
if (frac_type == FractalType.tricorn):
z = np.power(z, -2) + c # this doesn't work, but why?
elif (frac_type == FractalType.burning_ship):
z = np.power(np.complex(abs(z.real), abs(z.imag)), 2) + c
else:
z = z*z + c
iterations += 1
#print(str(iterations) + ", ", end="",flush=True) # this generates a nice list that we can use with c++
print(str(xpos) + "/" + str(ypos) + " Escape time: " + str(iterations) + " - Z " + str(z))
# print("Z: " + str(z))
if (print_fractal):
# print ascii fractal
if (iterations == bailout):
print("*", end="", flush=True)
else:
print(".", end="", flush=True)
In [218]:
def continuous_index (its, z):
print ("Continuous index " + str(its + 1 - (math.log(2) / abs(z)) / math.log(2.0)))
In [219]:
# calculate all complex numbers for the whole range
for y in range(image_height):
for x in range(image_width):
#fractal_calc(x, y, FractalType.burning_ship, np.complex(-0.8, 0.156), False)
pass
#print("")
# calculate single points
fractal_calc(10, 15, FractalType.burning_ship, np.complex(-0.8, 0.156), False)
# continuous_index(55, np.complex(2.3637850846657784, -2.264372597523388))