-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathiterated_function_system.py
More file actions
129 lines (109 loc) · 4.31 KB
/
iterated_function_system.py
File metadata and controls
129 lines (109 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import matplotlib.patches as patches
import matplotlib.pyplot as plt
import numpy as np
def transform_point(point, scale, rotation, shift):
rotation_matrix = np.array(
[[np.cos(rotation), -np.sin(rotation)], [np.sin(rotation), np.cos(rotation)]]
)
scaled_rotation_matrix = scale * rotation_matrix
transformed_point = np.dot(scaled_rotation_matrix, point) + shift
return transformed_point
def apply_transformations(vertices, transformation_functions):
transformed_polygons = []
for transformation in transformation_functions:
transformed_polygon = [transformation(vertex) for vertex in vertices]
transformed_polygons.append(transformed_polygon)
return transformed_polygons
def iterated_function_system(vertices, transformation_functions, iterations):
point_count = (len(vertices) * len(transformation_functions)) ** iterations
if point_count > 1e7:
print(
f"Warning: The number of points generated ({point_count}) is very large. "
"Consider reducing the number of iterations."
)
polygons = [vertices]
for _ in range(iterations):
new_polygons = []
for polygon in polygons:
new_polygons.extend(
apply_transformations(polygon, transformation_functions)
)
polygons = new_polygons
return polygons
def plot_polygons(polygons, axis=False):
_, ax = plt.subplots()
min_x, min_y = np.inf, np.inf
max_x, max_y = -np.inf, -np.inf
for polygon in polygons:
poly_np = np.array(polygon)
min_x, min_y = min(min_x, poly_np[:, 0].min()), min(min_y, poly_np[:, 1].min())
max_x, max_y = max(max_x, poly_np[:, 0].max()), max(max_y, poly_np[:, 1].max())
patch = patches.Polygon(
polygon,
closed=True,
linewidth=1,
edgecolor="lightblue",
facecolor="lightblue",
)
ax.add_patch(patch)
ax.set_xlim(min_x - 0.1 * abs(min_x), max_x + 0.1 * abs(max_x))
ax.set_ylim(min_y - 0.1 * abs(min_y), max_y + 0.1 * abs(max_y))
ax.set_aspect("equal")
if not axis:
plt.axis("off")
plt.show()
if __name__ == "__main__":
# Example: Dragon curve
horizontal_line = np.array([[0, 0], [1, 0]])
dragon_curve_ifs = [
lambda p: transform_point(p, 1 / np.sqrt(2), np.pi / 4, [0, 0]),
lambda p: transform_point(p, 1 / np.sqrt(2), 3 * np.pi / 4, [1, 0]),
]
# Example: Antlers
vertical_line = np.array([[0, 0], [0, 1]])
antlers = [
lambda p: transform_point(p, 0.5, 0, [0, 0]),
lambda p: transform_point(p, 0.5, np.pi / 4, [0, 1 / 2]),
lambda p: transform_point(p, 0.5, -np.pi / 4, [0, 1 / 2]),
]
# Example: Sierpinski triangle
triangle = np.array([[0, 0], [1, 0], [0.5, np.sqrt(3) / 2]])
sierpinski_triangle_ifs = [
lambda p: transform_point(p, 0.5, 0, [0, 0]),
lambda p: transform_point(p, 0.5, 0, [0.5, 0]),
lambda p: transform_point(p, 0.5, 0, [0.25, np.sqrt(3) / 4]),
]
# Example: Sierpinski carpet
square = np.array(
[
[0, 0],
[1, 0],
[1, 1],
[0, 1],
]
)
sierpinski_carpet_ifs = [
lambda p: transform_point(p, 1 / 3, 0, [0, 0]),
lambda p: transform_point(p, 1 / 3, 0, [1 / 3, 0]),
lambda p: transform_point(p, 1 / 3, 0, [2 / 3, 0]),
lambda p: transform_point(p, 1 / 3, 0, [0, 1 / 3]),
lambda p: transform_point(p, 1 / 3, 0, [2 / 3, 1 / 3]),
lambda p: transform_point(p, 1 / 3, 0, [0, 2 / 3]),
lambda p: transform_point(p, 1 / 3, 0, [1 / 3, 2 / 3]),
lambda p: transform_point(p, 1 / 3, 0, [2 / 3, 2 / 3]),
]
# Example: Koch's snowflake
koch_snowflake_ifs = [
lambda p: transform_point(p, 1 / 3, 0, [0, 0]),
lambda p: transform_point(p, 1 / 3, np.pi / 3, [1 / 3, 0]),
lambda p: transform_point(p, 1 / 3, -np.pi / 3, [0.5, np.sqrt(3) / 6]),
lambda p: transform_point(p, 1 / 3, 0, [2 / 3, 0]),
]
# Pick the initial vertices, iterated function system and iterations
initial_vertices = horizontal_line
transformations = dragon_curve_ifs
iterations = 9
final_polygons = iterated_function_system(
initial_vertices, transformations, iterations
)
plot_polygons(final_polygons)