1 # LogoMation-like turtle graphics
3 from math
import * # Also for export
6 class Error(Exception):
11 def __init__(self
, canvas
):
19 def degrees(self
, fullcircle
=360.0):
20 self
._fullcircle
= fullcircle
21 self
._invradian
= pi
/ (fullcircle
* 0.5)
29 width
= canvas
.winfo_width()
30 height
= canvas
.winfo_height()
32 width
= canvas
['width']
34 height
= canvas
['height']
35 self
._origin
= float(width
)/2.0, float(height
)/2.0
36 self
._position
= self
._origin
45 canvas
._root
().tkraise()
57 def tracer(self
, flag
):
63 def forward(self
, distance
):
64 x0
, y0
= start
= self
._position
65 x1
= x0
+ distance
* cos(self
._angle
*self
._invradian
)
66 y1
= y0
- distance
* sin(self
._angle
*self
._invradian
)
69 def backward(self
, distance
):
70 self
.forward(-distance
)
72 def left(self
, angle
):
73 self
._angle
= (self
._angle
+ angle
) % self
._fullcircle
76 def right(self
, angle
):
85 def width(self
, width
):
86 self
._width
= float(width
)
88 def color(self
, *args
):
90 raise Error
, "no color arguments"
93 if type(color
) == type(""):
94 # Test the color first
96 id = self
._canvas
.create_line(0, 0, 0, 0, fill
=color
)
97 except Tkinter
.TclError
:
98 raise Error
, "bad color string: %s" % `color`
99 self
._set
_color
(color
)
104 raise Error
, "bad color sequence: %s" % `color`
109 raise Error
, "bad color arguments: %s" % `args`
115 self
._set
_color
("#%02x%02x%02x" % (int(r
*x
+y
), int(g
*x
+y
), int(b
*x
+y
)))
117 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
)
206 def setheading(self
, angle
):
210 def window_width(self
):
211 width
= self
._canvas
.winfo_width()
212 if width
<= 1: # the window isn't managed by a geometry manager
213 width
= self
._canvas
['width']
216 def window_height(self
):
217 height
= self
._canvas
.winfo_height()
218 if height
<= 1: # the window isn't managed by a geometry manager
219 height
= self
._canvas
['height']
223 x0
, y0
= self
._origin
224 x1
, y1
= self
._position
225 return [x1
-x0
, -y1
+y0
]
227 def setx(self
, xpos
):
228 x0
, y0
= self
._origin
229 x1
, y1
= self
._position
230 self
._goto
(x0
+xpos
, y1
)
232 def sety(self
, ypos
):
233 x0
, y0
= self
._origin
234 x1
, y1
= self
._position
235 self
._goto
(x1
, y0
-ypos
)
237 def goto(self
, *args
):
242 raise Error
, "bad point argument: %s" % `args
[0]`
247 raise Error
, "bad coordinates: %s" % `args
[0]`
248 x0
, y0
= self
._origin
249 self
._goto
(x0
+x
, y0
-y
)
251 def _goto(self
, x1
, y1
):
252 x0
, y0
= start
= self
._position
253 self
._position
= map(float, (x1
, y1
))
255 self
._path
.append(self
._position
)
260 distance
= hypot(dx
, dy
)
261 nhops
= int(distance
)
262 item
= self
._canvas
.create_line(x0
, y0
, x0
, y0
,
267 for i
in range(1, 1+nhops
):
268 x
, y
= x0
+ dx
*i
/nhops
, y0
+ dy
*i
/nhops
269 self
._canvas
.coords(item
, x0
, y0
, x
, y
)
270 self
._draw
_turtle
((x
,y
))
271 self
._canvas
.update()
272 self
._canvas
.after(10)
274 self
._canvas
.coords(item
, x0
, y0
, x1
, y1
)
275 self
._canvas
.itemconfigure(item
, arrow
="none")
276 except Tkinter
.TclError
:
277 # Probably the window was closed!
280 item
= self
._canvas
.create_line(x0
, y0
, x1
, y1
,
284 self
._items
.append(item
)
287 def _draw_turtle(self
,position
=[]):
288 if not self
._tracing
:
291 position
= self
._position
294 dx
= distance
* cos(self
._angle
*self
._invradian
)
295 dy
= distance
* sin(self
._angle
*self
._invradian
)
296 self
._delete
_turtle
()
297 self
._arrow
= self
._canvas
.create_line(x
-dx
,y
+dy
,x
,y
,
302 self
._canvas
.update()
304 def _delete_turtle(self
):
306 self
._canvas
.delete(self
._arrow
)
318 global _root
, _canvas
321 _root
.wm_protocol("WM_DELETE_WINDOW", self
._destroy
)
323 # XXX Should have scroll bars
324 _canvas
= Tkinter
.Canvas(_root
, background
="white")
325 _canvas
.pack(expand
=1, fill
="both")
326 RawPen
.__init
__(self
, _canvas
)
329 global _root
, _canvas
, _pen
330 root
= self
._canvas
._root
()
345 def degrees(): _getpen().degrees()
346 def radians(): _getpen().radians()
347 def reset(): _getpen().reset()
348 def clear(): _getpen().clear()
349 def tracer(flag
): _getpen().tracer(flag
)
350 def forward(distance
): _getpen().forward(distance
)
351 def backward(distance
): _getpen().backward(distance
)
352 def left(angle
): _getpen().left(angle
)
353 def right(angle
): _getpen().right(angle
)
354 def up(): _getpen().up()
355 def down(): _getpen().down()
356 def width(width
): _getpen().width(width
)
357 def color(*args
): apply(_getpen().color
, args
)
358 def write(arg
, move
=0): _getpen().write(arg
, move
)
359 def fill(flag
): _getpen().fill(flag
)
360 def circle(radius
, extent
=None): _getpen().circle(radius
, extent
)
361 def goto(*args
): apply(_getpen().goto
, args
)
362 def heading(): return _getpen().heading()
363 def setheading(angle
): _getpen().setheading(angle
)
364 def position(): return _getpen().position()
365 def window_width(): return _getpen().window_width()
366 def window_height(): return _getpen().window_height()
367 def setx(xpos
): _getpen().setx(xpos
)
368 def sety(ypos
): _getpen().sety(ypos
)
376 # draw 3 squares; the last filled
392 # move out of the way
402 write("startstart", 1)
421 if __name__
== '__main__':
424 if __name__
== '__main__':