2.4 Examples in Python
The examples presented in this chapter repeat the assembly of three atomic transformations – shift, rescale and rotate.
Below are the definitions of these three transformations. In the examples below, x
is a two-element vector.
import numpy as np
import matplotlib.pyplot as plt
# Move point x by vector delta.
def shift(x, delta):
return np.add(x, delta)
# Scale coordinates of point x by ratio.
def scale(x, ratio):
return np.multiply(x, ratio)
# Rotate by angle of alpha (in degrees).
def rotate(x, alpha):
= math.pi * alpha / 180
adeg = [
rotation_matrix -np.sin(adeg)],
[np.cos(adeg),
[np.sin(adeg), np.cos(adeg)]]return np.matmul(x, rotation_matrix)
2.4.1 Sierpinski triangle
As we wrote at the beginning of this chapter, fractals can be built from ordinary dots, we do not need more sophisticated polygons. Let’s introduce this on the basis of the Sierpiński triangle.
\[ y_1 = x * \left[\begin{smallmatrix} 0.5 & 0\\ 0 & 0.5 \end{smallmatrix}\right] \]
\[ y_2 = x * \left[\begin{smallmatrix} 0.5 & 0\\ 0 & 0.5 \end{smallmatrix}\right] + \left[\begin{smallmatrix} 0.5 \\ 0 \end{smallmatrix}\right] \]
\[ y_3 = x * \left[\begin{smallmatrix} 0.5 & 0\\ 0 & 0.5 \end{smallmatrix}\right] + \left[\begin{smallmatrix} 0.25 \\ \sqrt3/4 \end{smallmatrix}\right] \]
The following program repeats the composition of these depth functions many times. In theory we would do this indefinitely, but it only takes a few steps to get a clear picture. The number of points grows exponentially, so after \(k\) steps it’s equal to \(3^k\).
import matplotlib.pyplot as plt
import numpy as np
# Move point x by vector delta.
def shift(x, delta):
return np.add(x, delta)
# Scale coordinates of point x by ratio.
def scale(x, ratio):
return np.multiply(x, ratio)
def sierpinski(x, depth):
if depth > 1:
= scale(shift(x, [0, 0]), [0.5, 0.5])
x1 - 1)
sierpinski(x1, depth = scale(shift(x, [0.5, 0]), [0.5, 0.5])
x2 - 1)
sierpinski(x2, depth = scale(shift(x, [0.25, 0.5]), [0.5, 0.5])
x3 - 1)
sierpinski(x3, depth else:
0], x[1], marker='o',
plt.plot(x[="black", markersize=3)
color
# Initialize the drawing and draw the Sierpiński triangle.
plt.figure() 0,0], depth = 7)
sierpinski([ plt.show()
2.4.2 Sierpinski pentagon
import math
import numpy as np
import matplotlib.pyplot as plt
# Move point x by vector delta.
def shift(x, delta):
return np.add(x, delta)
# Scale coordinates of point x by ratio.
def scale(x, ratio):
return np.multiply(x, ratio)
def pentagon(x, depth, col="black"):
if depth > 1:
= shift(scale(x, [0.382,0.382]), [0,0])
x1 -1, col="red")
pentagon(x1, depth= shift(scale(x, [0.382,0.382]), [0.618,0])
x2 -1, col="blue")
pentagon(x2, depth= shift(scale(x, [0.382,0.382]), [0.809,0.588])
x3 -1, col="green")
pentagon(x3, depth= shift(scale(x, [0.382,0.382]), [0.309,0.951])
x4 -1, col="orange")
pentagon(x4, depth= shift(scale(x, [0.382,0.382]), [-0.191,0.588])
x5 -1, col="brown")
pentagon(x5, depthelse:
0],x[1], marker='o', color=col, markersize=3)
plt.plot(x[
plt.figure()0,0], depth=6, col)
pentagon([ plt.show()
2.4.3 Heighway’s Dragon
import math
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as plt
# Move point x by vector delta.
def shift(x, delta):
return np.add(x, delta)
# Scale coordinates of point x by ratio.
def scale(x, ratio):
return np.multiply(x, ratio)
# Rotate by angle of alpha (in degrees).
def rotate(x, alpha):
= math.pi * alpha / 180
adeg = [
rotation_matrix -np.sin(adeg)],
[np.cos(adeg),
[np.sin(adeg), np.cos(adeg)]]return np.matmul(x, rotation_matrix)
def heighway(x, depth, col="black"):
if depth > 1:
= rotate(x, -45)
x1 = scale(x1, [np.sqrt(0.5), np.sqrt(0.5)])
x1 -1, col="blue")
heighway(x1, depth= rotate(x, -135)
x2 = scale(x2, [np.sqrt(0.5), np.sqrt(0.5)])
x2 = shift(x2, [0.75, 0.25])
x2 -1, col="red")
heighway(x2, depthelse:
0], x[1], marker='o', color=col, markersize=3)
plt.plot(x[
plt.figure()0,0], depth=14)
heighway([ plt.show()
2.4.4 Symmetric binary tree / Pythagoras’ tree
import numpy as np
import matplotlib.pyplot as plt
# Move point x by vector delta.
def shift(x, delta):
return np.add(x, delta)
# Scale coordinates of point x by ratio.
def scale(x, ratio):
return np.multiply(x, ratio)
# Rotate by angle of alpha (in degrees).
def rotate(x, alpha):
= math.pi * alpha / 180
adeg = [
rotation_matrix -np.sin(adeg)],
[np.cos(adeg),
[np.sin(adeg), np.cos(adeg)]]return np.matmul(x, rotation_matrix)
def sbt(x, depth, col="black"):
if depth > 1:
= rotate(x, -45)
x1 = shift(scale(x1, [0.7, 0.7]), [0, 1])
x1 -1, col="blue")
sbt(x1, depth= rotate(x, 45)
x2 = shift(scale(x2, [0.7, 0.7]), [0, 1])
x2 -1, col="red")
sbt(x2, depthelse:
0], x[1], marker='o', color=col, markersize=3)
plt.plot(x[
plt.figure()0,0], depth = 14)
sbt([ plt.show()