Zooming 10^13 Times into Julia Set Animation

Write a Python program to generate hundreds of images of Julia Set with ever zooming ranges. Please note that Turtle is not used in this project for speed consideration. Then use an external software to combine the images into a video:

Zooming 10^13 Times into Julia Set

The video above zooms into the center at 0.0958598997051 + 1.1501990019993i with c = 0.355 + 0.355i. In each iteration the range shrinks by 5% until the range becomes 1/10^13 the size of the original range. You can modify the code to try different centers and c. The following is the source code:

from PIL import Image
import colorsys

cx = -0.7269
cy = 0.1889
R = (1+(1+4*(cx**2+cy**2)**0.5)**0.5)/2+0.001
max_iteration = 512
print(R)

w, h, zoom = 1500,1500,1

def julia(cx,cy,RZ,px,py,R,max_iteration,x,y,minx,maxx,miny,maxy):
    zx = (x-minx)/(maxx-minx)*2*RZ-RZ+px
    zy = (y-miny)/(maxy-miny)*2*RZ-RZ+py
    i=0
    while zx**2 + zy**2 < R**2 and i < max_iteration:
        temp = zx**2 - zy**2
        zy = 2*zx*zy + cy
        zx = temp + cx
        i += 1
    return i

def gen_julia_image(sequence,cx,cy,RZ):
  bitmap = Image.new("RGB", (w, h), "white")
  pix = bitmap.load()
  for x in range(w):
    for y in range(h):
        # smllaer: right,down
      c=julia(cx,cy,RZ,0.0958598997051,1.1501990019993,R,max_iteration,x,y,0,w-1,0,h-1)
      v = c/max_iteration
      hv = 0.67-v*0.67
      r,g,b = colorsys.hsv_to_rgb(hv,1,v/2+0.45)
      r = min(255,round(r*255))
      g = min(255,round(g*255))
      b = min(255,round(b*255))
      pix[x,y] = int(r) + (int(g) << 8) + (int(b) << 16)
  bitmap.save("julia_"+str(sequence)+".jpg")
#  bitmap.show()

f = 0.95
RZF = 1/1000000000000
RZ = 1
k=1
while RZ>RZF:
  print(k,RZ)
  gen_julia_image(k,0.355,0.355,RZ)
  RZ *= f
  k+=1

Related Projects:

Julia Set Fractal Animation

Julia Set with Different Parameters

N Overlapping Circle with Python and Turtle (Source Code)

Generalize the three overlapping circles project by letting it draw any number of overlapping circles. The following is the overlapping circles from size 2 to size 7.

Solution

import turtle
import math

screen = turtle.Screen()
screen.title('N Overlapping Circles - PythonTurtle.Academy')
screen.setup(1000,1000)
turtle.hideturtle()
turtle.speed(0)
turtle.pensize(2)

def draw_circle(x,y,radius):
  turtle.up()
  turtle.goto(x,y-radius)
  turtle.seth(0)
  turtle.down()
  turtle.circle(radius,steps=360)

r = 150
n = 3
r2 = r/2/math.sin(math.radians(180/n))
angle = 90
for _ in range(n):
  draw_circle(r2*math.cos(math.radians(angle)),
              r2*math.sin(math.radians(angle)),
              r)
  angle += 360/n

Three Overlapping Circles with Python and Turtle (Tutorial)

Draw the following overlapping circles. Please note that each circle passes through the center of the other two circles.

Three Overlapping Circles

Solution

We observe that the centers of the three circles form an equilateral triangle and the length of the equilateral triangle is the radius of the circle. So, the first step is to figure out the coordinates of the vertices of the equilateral triangle (with some math), and then draw three circles given the these three coordinates as the centers. So, it will be helpful to create a function that draws circle based on the center and radius. The following is the source code:

import turtle

screen = turtle.Screen()
screen.title('Three Circles - PythonTurtle.Academy')
screen.setup(1000,1000)
turtle.hideturtle()
turtle.speed(0)

def draw_circle(x,y,radius):
  turtle.up()
  turtle.goto(x,y-radius)
  turtle.seth(0)
  turtle.down()
  turtle.circle(radius,steps=360)

r = 150
draw_circle(0,r,r*3**0.5)
draw_circle(-r/2*3**0.5,-r/2,r*3**0.5)
draw_circle(r/2*3**0.5,-r/2,r*3**0.5)

What’s next?

Draw any number of overlapping circles.

Julia Set with Different Parameters

In this project, we are generate several Julia Sets by varying the constant c in the normal Julia Set function. Turtle will be too slow to do this work. Instead we are going to use the PIL library. Please check out Julia Set Animation project for source code.

c = -0.618 (Max Iteration=38)
c = 0.355534-0.337292i (Max Iteration=4064)
c = 0.355+0.355i (Max Iteration=512)
c = 0.285+0.01i (Max Iteration=204)
c = -0.8+0.156i (Max Iteration=924)
c = -0.835+0.2321i (Max Iteration=104)
c = 0.7269+0.1889i (Max Iteration=1024)

Related Projects:

Zooming 10^13 Times into Julia Set Animation

Julia Set Fractal Animation

Julia Set Fractal Animation

Julia Set Animation

In this project, we are going to animate the Julia Set by varying the constant c in the normal Julia Set function. Turtle will be too slow to do this work. Instead we are going to use the PIL library to generate 360 images. Then, a video editing software can be used to combine 360 images into a video file. The following is the source code:

from PIL import Image
import colorsys
import math

cx = 0.7885
cy = 0
R = (1+(1+4*(cx**2+cy**2)**0.5)**0.5)/2+0.001
max_iteration = 200

w, h, zoom = 1000,1000,1

def julia(cx,cy,R,max_iteration,x,y,minx,maxx,miny,maxy):
    zx = (x-minx)/(maxx-minx)*2*R-R
    zy = (y-miny)/(maxy-miny)*2*R-R
    i=0
    while zx**2 + zy**2 < R**2 and i < max_iteration:
        temp = zx**2 - zy**2
        zy = 2*zx*zy + cy
        zx = temp + cx
        i += 1
    return i

def gen_julia_image(sequence,cx,cy):
  bitmap = Image.new("RGB", (w, h), "white")
  pix = bitmap.load()
  for x in range(w):
    for y in range(h):
      c=julia(cx,cy,R,max_iteration,x,y,0,w-1,0,h-1)
      r,g,b = colorsys.hsv_to_rgb(c/max_iteration,1,0.9)
      r = min(255,round(r*255))
      g = min(255,round(g*255))
      b = min(255,round(b*255))
      pix[x,y] = int(b) + (int(g) << 8) + (int(r) << 16)
  bitmap.save("julia_"+str(sequence)+".jpg")


for i in range(360):
  cx = 0.7885*math.cos(i*math.pi/180)
  cy = 0.7885*math.sin(i*math.pi/180)
  gen_julia_image(i,cx,cy)

Related Projects:

Julia Set with Different Parameters

Zooming 10^13 Times into Julia Set Animation

6-Line Snowflake Fractal with Python and Turtle (Tutorial and Source Code)

Use recursion to draw the following snowflake shape generated from 6 sub-fractals of splitting lines.

Recursion Depth 5

The following figures show recursion depths ranging from 0 to 4.

Solution:

To solve this problem, you want to start from a function that draws a line given starting point (x,y), length, direction, and pensize. The following is the code for this function:

def line(x,y,length,direction,pensize):
  turtle.up()
  turtle.pensize(pensize)
  turtle.goto(x,y)
  turtle.down()
  turtle.seth(direction)
  turtle.fd(length)

Now you can define the recursive function that keeps branching out the shorter pair of lines. The starting point of the branch is about 2/5 of way from the original starting point. One branch is turning right about 25 degrees and the other branch is turning left about 25 degrees. Pen size should decrease proportionally too. The following is the code for this function:

def line_fractal(x,y,length,direction,pensize,n):
  if n==0: return
  line(x,y,length,direction,pensize)
  line_fractal(x+math.cos(direction*math.pi/180)*length*2/5,
               y+math.sin(direction*math.pi/180)*length*2/5,
               length*3/5,
               direction-25,
               pensize*3/5,
               n-1)
  line_fractal(x+math.cos(direction*math.pi/180)*length*2/5,
               y+math.sin(direction*math.pi/180)*length*2/5,
               length*3/5,
               direction+25,
               pensize*3/5,
               n-1)

The last function is the easiest. Just call the function above 6 times with 6 evenly spaced lines across 360 degrees. The following is the complete code for this project:

import turtle
import math

screen = turtle.Screen()
screen.title('6 Line Snowflake Fractal - PythonTurtle.Academy')
screen.setup(1000,1000)
screen.tracer(0,0)
turtle.hideturtle()
turtle.speed(0)

def line(x,y,length,direction,pensize):
  turtle.up()
  turtle.pensize(pensize)
  turtle.goto(x,y)
  turtle.down()
  turtle.seth(direction)
  turtle.fd(length)

def line_fractal(x,y,length,direction,pensize,n):
  if n==0: return
  line(x,y,length,direction,pensize)
  line_fractal(x+math.cos(direction*math.pi/180)*length*2/5,
               y+math.sin(direction*math.pi/180)*length*2/5,
               length*3/5,
               direction-25,
               pensize*3/5,
               n-1)
  line_fractal(x+math.cos(direction*math.pi/180)*length*2/5,
               y+math.sin(direction*math.pi/180)*length*2/5,
               length*3/5,
               direction+25,
               pensize*3/5,
               n-1)

def snowflake():
  for i in range(6):
    line_fractal(0,0,400,i*60,5,5)

snowflake()
screen.update()

Gardi Fractal with Python and Turtle (Source Code)

Lori Gardi created this nested overlapping circle fractal in the paper ‘The Universe is a Fractal’. The fractal according to the paper looks similar to a supernova. A simple version to draw is to let the overlapping circles to pass through the centers of the other circle.

Gardi Fractal

To draw this, it will be helpful to create a basic function that draw a circle given the center and radius. Then, create a function that draws the overlapping circles in horizontal and vertical orientations. With these two functions, the recursive function just need to flip the orientation and reduce the radius size in each recursive call. You need do a little geometry to figure out the radius of the smaller circles. The following is the source code that draw this fractal:

import turtle

screen = turtle.Screen()
screen.title('Gardi Fractal - PythonTurtle.Academy')
screen.setup(1000,1000)
screen.tracer(0,0)
turtle.hideturtle()
turtle.speed(0)
turtle.color('teal')

def circle(x,y,radius):
  turtle.up()
  turtle.goto(x,y-radius)
  turtle.down()
  turtle.seth(0)
  turtle.circle(radius, steps=360)

def two_circles(x,y,radius,orientation):
  turtle.pensize(radius/50)
  if orientation==0:
    circle(x-radius/2,y,radius)
    circle(x+radius/2,y,radius)
  else:
    circle(x,y-radius/2,radius)
    circle(x,y+radius/2,radius)

def gardi_fractal(x,y,radius,orientation,n):
  if n==0: return
  two_circles(x,y,radius,orientation)
  gardi_fractal(x,y,(4-7**0.5)/3*radius,1-orientation,n-1)
  
gardi_fractal(0,0,300,0,6)
screen.update()