Spaces:
Runtime error
Runtime error
| import re | |
| from PIL import Image | |
| from matplotlib import pyplot as plt | |
| import matplotlib as mpl | |
| import matplotlib.style as mplstyle | |
| import numpy as np | |
| mpl.use('Agg') | |
| mpl.rcParams["path.simplify_threshold"] = 0.0 | |
| mpl.rcParams['agg.path.chunksize'] = 10000 | |
| mplstyle.use('fast') | |
| HALF_INF = 63 | |
| INF = 126 | |
| EPS_DIST = 1/20 | |
| EPS_ANGLE = 2.86 | |
| class Turtle: | |
| def __init__(self, ax=None): | |
| self.x = 0 | |
| self.y = 0 | |
| self.heading = 0 | |
| if ax is None: | |
| self.fig, self.ax = plt.subplots(1, 1, figsize=(20, 20)) | |
| else: | |
| self.ax = ax | |
| self.ax.set_xlim(-50, 50) | |
| self.ax.set_ylim(-50, 50) | |
| self.ax.set_xticklabels([]) | |
| self.ax.set_yticklabels([]) | |
| self.ax.set_xticks([]) | |
| self.ax.set_yticks([]) | |
| self.ax.spines['top'].set_visible(False) | |
| self.ax.spines['bottom'].set_visible(False) | |
| self.ax.spines['left'].set_visible(False) | |
| self.ax.spines['right'].set_visible(False) | |
| self.is_down = True | |
| def forward(self, dist): | |
| x0, y0 = self.x, self.y | |
| x1 = x0 + dist * np.cos(self.heading) | |
| y1 = y0 + dist * np.sin(self.heading) | |
| if self.is_down: | |
| self.ax.plot([x0, x1], [y0, y1], color='black', linewidth=3) | |
| self.x = x1 | |
| self.y = y1 | |
| def left(self, angle): | |
| self.heading += angle * np.pi / 180 | |
| def right(self, angle): | |
| self.heading -= angle * np.pi / 180 | |
| def penup(self): | |
| self.is_down = False | |
| def pendown(self): | |
| self.is_down = True | |
| def save(self, path): | |
| self.fig.canvas.draw() | |
| pil_img = Image.frombytes('RGB', self.fig.canvas.get_width_height(), self.fig.canvas.tostring_rgb()) | |
| if path: | |
| pil_img.save(path) | |
| return pil_img | |
| class _TurtleState: | |
| def __init__(self, turtle): | |
| self.turtle = turtle | |
| self.position = None | |
| self.heading = None | |
| self.pen_status = None | |
| def __enter__(self): | |
| self.position = (self.turtle.x, self.turtle.y) | |
| self.heading = self.turtle.heading | |
| self.pen_status = self.turtle.is_down | |
| return self | |
| def __exit__(self, exc_type, exc_val, exc_tb): | |
| self.turtle.penup() | |
| self.turtle.x, self.turtle.y = self.position | |
| self.turtle.heading = self.heading | |
| if self.pen_status: | |
| self.turtle.pendown() | |
| if __name__ == "__main__": | |
| turtle = Turtle() | |
| def forward(dist): | |
| turtle.forward(dist) | |
| def left(angle): | |
| turtle.left(angle) | |
| def right(angle): | |
| turtle.right(angle) | |
| def penup(): | |
| turtle.penup() | |
| def pendown(): | |
| turtle.pendown() | |
| def save(path): | |
| turtle.save(path) | |
| def fork_state(): | |
| """ | |
| Clone the current state of the turtle. | |
| Usage: | |
| with clone_state(): | |
| forward(100) | |
| left(90) | |
| forward(100) | |
| """ | |
| return turtle._TurtleState(turtle) | |
| # Example usage | |
| def example_plot(): | |
| forward(5) | |
| with fork_state(): | |
| forward(10) | |
| left(90) | |
| forward(10) | |
| with fork_state(): | |
| right(90) | |
| forward(20) | |
| left(90) | |
| forward(10) | |
| left(90) | |
| forward(10) | |
| right(90) | |
| forward(50) | |
| save("test.png") | |