Skip to content

Instantly share code, notes, and snippets.

@ekm507
Created November 5, 2022 21:56
Show Gist options
  • Save ekm507/4787e25942ae73ac4f659a9958ec8cd6 to your computer and use it in GitHub Desktop.
Save ekm507/4787e25942ae73ac4f659a9958ec8cd6 to your computer and use it in GitHub Desktop.
kochs snowflake with linear mapping in python
import numpy as np
from matplotlib import pyplot as plt
# define the initial line. it has two points and its length should be 1 to normalize everything.
points = []
first_points = [np.array([0, 0]), np.array([1, 0])]
points += first_points
# number of iterations in making fractal. how deep do you want it to be?
# for Koch's snowflake, if level is set to 1, it should draw something like this: _/\_
levels = 5
# angle of rotation in snowflake. standart value is Pi/3 but you can try it with Pi/2.5 and Pi/4
rotation_angle = np.pi / 3
# make rotation matrices. one for clockwise, other for counter-clockwise.
sin_r = np.sin(rotation_angle)
cos_r = np.cos(rotation_angle)
rm1 = np.array([
[cos_r, sin_r],
[-sin_r, cos_r]
])
rm2 = np.array([
[cos_r, -sin_r],
[sin_r, cos_r]
])
# make displacement vectors
d0 = np.array([0, 0])
d1 = np.array([1, 0])
d2 = np.array([1 + np.cos(rotation_angle), np.sin(rotation_angle)])
d3 = np.array([1 + 2 * np.cos(rotation_angle), 0])
# calculate scaling factor for each itteration. it is not 1/2 because the shape is a fractal
scale_factor = 1/(2 + 2 * np.cos(rotation_angle))
# this fractal repeats itself 4 times. this function generates one of the sides by mapping points.
def one_side_of_fractal(points, which_side):
output = []
for point in points:
if which_side == 0:
output.append(point)
elif which_side == 1:
point_rotate = np.matmul(point, rm1) + d1
output.append(point_rotate)
elif which_side == 2:
point_rotate = np.matmul(point, rm2) + d2
output.append(point_rotate)
elif which_side == 3:
point_rotate = point + d3
output.append(point_rotate)
return output
# one iteration of fractal.
# this function generates 4 copies of the fractal and joins them together. finally scales the fractal.
def one_level_deeper_koch(points):
output = []
for i in range(4):
output += one_side_of_fractal(points, i)
return list(np.array(output) * scale_factor)
# get an initial line and turn it into a fractal. this is only one side of snowflake. because I am too lazy to make other sides too!
def make_koch(points, levels):
for _ in range(levels):
points = one_level_deeper_koch(points)
return points
#
for i in range(levels):
# scale_factor = float(input())
points = [] + first_points
points = make_koch(points, i)
points_x = [point[0] for point in points]
points_y = [point[1] for point in points]
plt.plot(points_x, points_y)
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment