-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspectre.py
84 lines (69 loc) · 2.5 KB
/
spectre.py
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
import numpy as np
import bezier
def calculate_control_points(point, curve_strength):
x, y = point
normal_x, normal_y = y, -x
control1 = [-curve_strength * normal_x + x / 2, -curve_strength * normal_y + y / 2]
control2 = [curve_strength * normal_x + x / 2, curve_strength * normal_y + y / 2]
return control1, control2
def generate_monotile(a, b, curve_strength):
cos_angle = np.cos(np.pi / 3)
sin_angle = np.sin(np.pi / 3)
direction_vectors = [
[cos_angle * b, sin_angle * b],
[b, 0],
[0, a],
[sin_angle * a, cos_angle * a],
[cos_angle * b, -sin_angle * b],
[-cos_angle * b, -sin_angle * b],
[sin_angle * a, -cos_angle * a],
[0, -a],
[0, -a],
[-sin_angle * a, -cos_angle * a],
[-cos_angle * b, sin_angle * b],
[-b, 0],
[0, a],
[-sin_angle * a, cos_angle * a],
]
x_vals, y_vals = [0], [0]
for dx, dy in direction_vectors:
control1, control2 = calculate_control_points([dx, dy], curve_strength)
nodes = np.asfortranarray(
[
[
x_vals[-1],
control1[0] + x_vals[-1],
control2[0] + x_vals[-1],
dx + x_vals[-1],
],
[
y_vals[-1],
control1[1] + y_vals[-1],
control2[1] + y_vals[-1],
dy + y_vals[-1],
],
]
)
curve = bezier.Curve(nodes, degree=3)
s_vals = np.linspace(0.0, 1.0, 50)
x_curve, y_curve = curve.evaluate_multi(s_vals)
x_vals.extend(x_curve.tolist())
y_vals.extend(y_curve.tolist())
# Close the shape by connecting the last point to the first
x_vals.append(x_vals[0])
y_vals.append(y_vals[0])
return np.array(x_vals), np.array(y_vals)
if __name__ == "__main__":
import argparse
import matplotlib.pyplot as plt
parser = argparse.ArgumentParser(
description="Draw a Spectre Monotile with given parameters."
)
parser.add_argument("a", type=float, help="Value for parameter a.")
parser.add_argument("b", type=float, help="Value for parameter b.")
parser.add_argument("curve_strength", type=float, help="Strength of the curve.")
args = parser.parse_args()
x_vals, y_vals = generate_monotile(args.a, args.b, args.curve_strength)
plt.plot(x_vals, y_vals, color="black", linewidth=1)
plt.axis("equal")
plt.show()