1 # LogoMation-like turtle graphics
3 from math
import * # Also for export
5 class Error(Exception):
10 def __init__(self
, canvas
):
18 def degrees(self
, fullcircle
=360.0):
19 self
._fullcircle
= fullcircle
20 self
._invradian
= pi
/ (fullcircle
* 0.5)
27 width
= canvas
.winfo_width()
28 height
= canvas
.winfo_height()
30 width
= canvas
['width']
32 height
= canvas
['height']
33 self
._origin
= float(width
)/2.0, float(height
)/2.0
34 self
._position
= self
._origin
43 canvas
._root
().tkraise()
56 def tracer(self
, flag
):
62 def forward(self
, distance
):
63 x0
, y0
= start
= self
._position
64 x1
= x0
+ distance
* cos(self
._angle
*self
._invradian
)
65 y1
= y0
- distance
* sin(self
._angle
*self
._invradian
)
68 def backward(self
, distance
):
69 self
.forward(-distance
)
71 def left(self
, angle
):
72 self
._angle
= (self
._angle
+ angle
) % self
._fullcircle
75 def right(self
, angle
):
84 def width(self
, width
):
85 self
._width
= float(width
)
87 def color(self
, *args
):
89 raise Error
, "no color arguments"
92 if type(color
) == type(""):
93 # Test the color first
95 id = self
._canvas
.create_line(0, 0, 0, 0, fill
=color
)
96 except Tkinter
.TclError
:
97 raise Error
, "bad color string: %s" % `color`
98 self
._set
_color
(color
)
103 raise Error
, "bad color sequence: %s" % `color`
108 raise Error
, "bad color arguments: %s" % `args`
114 self
._set
_color
("#%02x%02x%02x" % (int(r
*x
+y
), int(g
*x
+y
), int(b
*x
+y
)))
116 def _set_color(self
,color
):
121 def write(self
, arg
, move
=0):
122 x
, y
= start
= self
._position
123 x
= x
-1 # correction -- calibrated for Windows
124 item
= self
._canvas
.create_text(x
, y
,
125 text
=str(arg
), anchor
="sw",
127 self
._items
.append(item
)
129 x0
, y0
, x1
, y1
= self
._canvas
.bbox(item
)
133 def fill(self
, flag
):
135 path
= tuple(self
._path
)
136 smooth
= self
._filling
< 0
138 item
= self
._canvas
._create
('polygon', path
,
139 {'fill': self
._color
,
141 self
._items
.append(item
)
142 self
._canvas
.lower(item
)
144 for item
in self
._tofill
:
145 self
._canvas
.itemconfigure(item
, fill
=self
._color
)
146 self
._items
.append(item
)
151 self
._path
.append(self
._position
)
153 def circle(self
, radius
, extent
=None):
155 extent
= self
._fullcircle
156 x0
, y0
= self
._position
157 xc
= x0
- radius
* sin(self
._angle
* self
._invradian
)
158 yc
= y0
- radius
* cos(self
._angle
* self
._invradian
)
160 start
= self
._angle
- 90.0
162 start
= self
._angle
+ 90.0
165 if abs(extent
) >= self
._fullcircle
:
166 item
= self
._canvas
.create_oval(xc
-radius
, yc
-radius
,
167 xc
+radius
, yc
+radius
,
170 self
._tofill
.append(item
)
171 item
= self
._canvas
.create_arc(xc
-radius
, yc
-radius
,
172 xc
+radius
, yc
+radius
,
178 self
._tofill
.append(item
)
180 if abs(extent
) >= self
._fullcircle
:
181 item
= self
._canvas
.create_oval(xc
-radius
, yc
-radius
,
182 xc
+radius
, yc
+radius
,
185 self
._items
.append(item
)
186 item
= self
._canvas
.create_arc(xc
-radius
, yc
-radius
,
187 xc
+radius
, yc
+radius
,
193 self
._items
.append(item
)
194 angle
= start
+ extent
195 x1
= xc
+ abs(radius
) * cos(angle
* self
._invradian
)
196 y1
= yc
- abs(radius
) * sin(angle
* self
._invradian
)
197 self
._angle
= (self
._angle
+ extent
) % self
._fullcircle
198 self
._position
= x1
, y1
200 self
._path
.append(self
._position
)
202 def goto(self
, *args
):
207 raise Error
, "bad point argument: %s" % `args
[0]`
212 raise Error
, "bad coordinates: %s" % `args
[0]`
213 x0
, y0
= self
._origin
214 self
._goto
(x0
+x
, y0
-y
)
216 def _goto(self
, x1
, y1
):
217 x0
, y0
= start
= self
._position
218 self
._position
= map(float, (x1
, y1
))
220 self
._path
.append(self
._position
)
225 distance
= hypot(dx
, dy
)
226 nhops
= int(distance
)
227 item
= self
._canvas
.create_line(x0
, y0
, x0
, y0
,
232 for i
in range(1, 1+nhops
):
233 x
, y
= x0
+ dx
*i
/nhops
, y0
+ dy
*i
/nhops
234 self
._canvas
.coords(item
, x0
, y0
, x
, y
)
235 self
._draw
_turtle
((x
,y
))
236 self
._canvas
.update()
237 self
._canvas
.after(10)
239 self
._canvas
.coords(item
, x0
, y0
, x1
, y1
)
240 self
._canvas
.itemconfigure(item
, arrow
="none")
241 except Tkinter
.TclError
:
242 # Probably the window was closed!
245 item
= self
._canvas
.create_line(x0
, y0
, x1
, y1
,
249 self
._items
.append(item
)
252 def _draw_turtle(self
,position
=[]):
253 if not self
._tracing
:
256 position
= self
._position
259 dx
= distance
* cos(self
._angle
*self
._invradian
)
260 dy
= distance
* sin(self
._angle
*self
._invradian
)
261 self
._delete
_turtle
()
262 self
._arrow
= self
._canvas
.create_line(x
-dx
,y
+dy
,x
,y
,
267 self
._canvas
.update()
269 def _delete_turtle(self
):
271 self
._canvas
.delete(self
._arrow
)
283 global _root
, _canvas
286 _root
.wm_protocol("WM_DELETE_WINDOW", self
._destroy
)
288 # XXX Should have scroll bars
289 _canvas
= Tkinter
.Canvas(_root
, background
="white")
290 _canvas
.pack(expand
=1, fill
="both")
291 RawPen
.__init
__(self
, _canvas
)
294 global _root
, _canvas
, _pen
295 root
= self
._canvas
._root
()
310 def degrees(): _getpen().degrees()
311 def radians(): _getpen().radians()
312 def reset(): _getpen().reset()
313 def clear(): _getpen().clear()
314 def tracer(flag
): _getpen().tracer(flag
)
315 def forward(distance
): _getpen().forward(distance
)
316 def backward(distance
): _getpen().backward(distance
)
317 def left(angle
): _getpen().left(angle
)
318 def right(angle
): _getpen().right(angle
)
319 def up(): _getpen().up()
320 def down(): _getpen().down()
321 def width(width
): _getpen().width(width
)
322 def color(*args
): apply(_getpen().color
, args
)
323 def write(arg
, move
=0): _getpen().write(arg
, move
)
324 def fill(flag
): _getpen().fill(flag
)
325 def circle(radius
, extent
=None): _getpen().circle(radius
, extent
)
326 def goto(*args
): apply(_getpen().goto
, args
)
334 # draw 3 squares; the last filled
350 # move out of the way
360 write("startstart", 1)
379 if __name__
== '__main__':
382 if __name__
== '__main__':