xu3kev commited on
Commit
be3d62e
1 Parent(s): a6be99d

add custom turtle lib

Browse files
Files changed (1) hide show
  1. myturtle.py +139 -0
myturtle.py ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ from PIL import Image
3
+ from matplotlib import pyplot as plt
4
+ import matplotlib as mpl
5
+ import matplotlib.style as mplstyle
6
+ import numpy as np
7
+
8
+ mpl.use('Agg')
9
+ mpl.rcParams["path.simplify_threshold"] = 0.0
10
+ mpl.rcParams['agg.path.chunksize'] = 10000
11
+ mplstyle.use('fast')
12
+
13
+ HALF_INF = 63
14
+ INF = 126
15
+ EPS_DIST = 1/20
16
+ EPS_ANGLE = 2.86
17
+
18
+ class Turtle:
19
+ def __init__(self, ax=None):
20
+ self.x = 0
21
+ self.y = 0
22
+ self.heading = 0
23
+ if ax is None:
24
+ self.fig, self.ax = plt.subplots(1, 1, figsize=(20, 20))
25
+ else:
26
+ self.ax = ax
27
+ self.ax.set_xlim(-50, 50)
28
+ self.ax.set_ylim(-50, 50)
29
+ self.ax.set_xticklabels([])
30
+ self.ax.set_yticklabels([])
31
+ self.ax.set_xticks([])
32
+ self.ax.set_yticks([])
33
+ self.ax.spines['top'].set_visible(False)
34
+ self.ax.spines['bottom'].set_visible(False)
35
+ self.ax.spines['left'].set_visible(False)
36
+ self.ax.spines['right'].set_visible(False)
37
+ self.is_down = True
38
+
39
+ def forward(self, dist):
40
+ x0, y0 = self.x, self.y
41
+ x1 = x0 + dist * np.cos(self.heading)
42
+ y1 = y0 + dist * np.sin(self.heading)
43
+ if self.is_down:
44
+ self.ax.plot([x0, x1], [y0, y1], color='black', linewidth=3)
45
+ self.x = x1
46
+ self.y = y1
47
+
48
+ def left(self, angle):
49
+ self.heading += angle * np.pi / 180
50
+
51
+ def right(self, angle):
52
+ self.heading -= angle * np.pi / 180
53
+
54
+ def penup(self):
55
+ self.is_down = False
56
+
57
+ def pendown(self):
58
+ self.is_down = True
59
+
60
+ def save(self, path):
61
+ self.fig.canvas.draw()
62
+ pil_img = Image.frombytes('RGB', self.fig.canvas.get_width_height(), self.fig.canvas.tostring_rgb())
63
+ if path:
64
+ pil_img.save(path)
65
+ return pil_img
66
+
67
+ class _TurtleState:
68
+ def __init__(self, turtle):
69
+ self.turtle = turtle
70
+ self.position = None
71
+ self.heading = None
72
+ self.pen_status = None
73
+
74
+ def __enter__(self):
75
+ self.position = (self.turtle.x, self.turtle.y)
76
+ self.heading = self.turtle.heading
77
+ self.pen_status = self.turtle.is_down
78
+ return self
79
+
80
+ def __exit__(self, exc_type, exc_val, exc_tb):
81
+ self.turtle.penup()
82
+ self.turtle.x, self.turtle.y = self.position
83
+ self.turtle.heading = self.heading
84
+ if self.pen_status:
85
+ self.turtle.pendown()
86
+
87
+ if __name__ == "__main__":
88
+ turtle = Turtle()
89
+
90
+ def forward(dist):
91
+ turtle.forward(dist)
92
+
93
+ def left(angle):
94
+ turtle.left(angle)
95
+
96
+ def right(angle):
97
+ turtle.right(angle)
98
+
99
+ def penup():
100
+ turtle.penup()
101
+
102
+ def pendown():
103
+ turtle.pendown()
104
+
105
+ def save(path):
106
+ turtle.save(path)
107
+
108
+ def fork_state():
109
+ """
110
+ Clone the current state of the turtle.
111
+
112
+ Usage:
113
+ with clone_state():
114
+ forward(100)
115
+ left(90)
116
+ forward(100)
117
+ """
118
+ return turtle._TurtleState(turtle)
119
+
120
+ # Example usage
121
+ def example_plot():
122
+ forward(5)
123
+
124
+ with fork_state():
125
+ forward(10)
126
+ left(90)
127
+ forward(10)
128
+ with fork_state():
129
+ right(90)
130
+ forward(20)
131
+ left(90)
132
+ forward(10)
133
+ left(90)
134
+ forward(10)
135
+
136
+ right(90)
137
+ forward(50)
138
+ save("test.png")
139
+