Skip to content

Instantly share code, notes, and snippets.

@cheind
Last active July 24, 2023 13:01
Show Gist options
  • Save cheind/81861ac99e19e4629583fb552112da90 to your computer and use it in GitHub Desktop.
Save cheind/81861ac99e19e4629583fb552112da90 to your computer and use it in GitHub Desktop.
Fractals from #Numberphile/Chaos Theory
import numpy as np
import matplotlib.pyplot as plt
def sierpinski_triangle():
"""Generates a Sierpinski triangle.
Given 3 anchor points and a trace point, the
next trace point is half-way between its current
location and a randomly chosen anchor.
"""
anchors = np.array([[0, 0], [1, 0], [0.5, 0.5]])
t = np.array([0.2, 0.2])
pts = [t]
ids = np.random.choice(len(anchors), size=10000)
for idx in ids:
pts.append((pts[-1] + anchors[idx]) * 0.5)
pts = np.stack(pts)
plt.scatter(pts[:, 0], pts[:, 1], c="b", s=1)
plt.scatter(anchors[:, 0], anchors[:, 1], c="r", s=1)
plt.show()
def barnsley_fern():
"""Generates a Barnsley fern.
Randomly chooses one of four affine transformations and
applies it to the current location of the trace point
to advance to the next trace point.
"""
f1 = np.array([[0, 0, 0], [0, 0.16, 0], [0, 0, 1]])
f2 = np.array([[0.85, 0.04, 0], [-0.04, 0.85, 1.6], [0, 0, 1]])
f3 = np.array([[0.2, -0.26, 0], [0.23, 0.22, 1.6], [0, 0, 1]])
f4 = np.array([[-0.15, 0.28, 0], [0.26, 0.24, 0.44], [0, 0, 1]])
fs = [f1, f2, f3, f4]
ps = np.array([0.01, 0.85, 0.7, 0.7])
ids = np.random.choice(len(fs), size=1000000, p=ps / ps.sum())
pts = [np.array([0.0, 0.0, 1.0])]
for idx in ids:
pts.append(fs[idx] @ pts[-1])
pts = np.stack(pts)
plt.gca().set_aspect("equal")
plt.scatter(pts[:, 0], pts[:, 1], c="b", s=1)
plt.show()
if __name__ == "__main__":
sierpinski_triangle()
barnsley_fern()
@cheind
Copy link
Author

cheind commented Jul 24, 2023

The episode is here
https://www.youtube.com/watch?v=kbKtFN71Lfs

Outputs:

Triangle

triangle

Fern

fern

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment