File size: 3,063 Bytes
be3d62e
6f70e6f
be3d62e
 
 
 
 
6f70e6f
be3d62e
 
6f70e6f
 
 
be3d62e
6f70e6f
be3d62e
 
 
6f70e6f
be3d62e
6f70e6f
 
be3d62e
6f70e6f
 
be3d62e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6f70e6f
 
be3d62e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6f70e6f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
130
131
132
import numpy as np
import cv2

HALF_INF = 63
INF = 126
EPS_DIST = 1/20
EPS_ANGLE = 2.86
SCALE = 15.5

class Turtle:
    def __init__(self, canvas_size=(2000, 2000)):
        self.x = canvas_size[0] // 2
        self.y = canvas_size[1] // 2
        self.heading = 0
        self.canvas = np.ones((canvas_size[1], canvas_size[0], 3), dtype=np.uint8) * 255
        self.is_down = True

    def forward(self, dist):
        dist = dist * SCALE
        x0, y0 = self.x, self.y
        x1 = int(x0 + dist * np.cos(self.heading))
        y1 = int(y0 - dist * np.sin(self.heading))
        if self.is_down:
            cv2.line(self.canvas, (x0, y0), (x1, y1), (0, 0, 0), 3)
        self.x, self.y = x1, 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):
        if path:
            cv2.imwrite(path, self.canvas)
        return self.canvas

    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("test2.png")

    def plot2():
        for j in range(2):
            forward(2)
            left(0.0)
            for i in range(4):
                forward(2)
                left(90)
            forward(0)
            left(180.0)
            forward(2)
            left(180.0)
        FINAL_IMAGE = turtle.save("")

    example_plot()
    # plot2()