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
)
154 def circle(self
, radius
, extent
=None):
156 extent
= self
._fullcircle
157 x0
, y0
= self
._position
158 xc
= x0
- radius
* sin(self
._angle
* self
._invradian
)
159 yc
= y0
- radius
* cos(self
._angle
* self
._invradian
)
161 start
= self
._angle
- 90.0
163 start
= self
._angle
+ 90.0
166 if abs(extent
) >= self
._fullcircle
:
167 item
= self
._canvas
.create_oval(xc
-radius
, yc
-radius
,
168 xc
+radius
, yc
+radius
,
171 self
._tofill
.append(item
)
172 item
= self
._canvas
.create_arc(xc
-radius
, yc
-radius
,
173 xc
+radius
, yc
+radius
,
179 self
._tofill
.append(item
)
181 if abs(extent
) >= self
._fullcircle
:
182 item
= self
._canvas
.create_oval(xc
-radius
, yc
-radius
,
183 xc
+radius
, yc
+radius
,
186 self
._items
.append(item
)
187 item
= self
._canvas
.create_arc(xc
-radius
, yc
-radius
,
188 xc
+radius
, yc
+radius
,
194 self
._items
.append(item
)
195 angle
= start
+ extent
196 x1
= xc
+ abs(radius
) * cos(angle
* self
._invradian
)
197 y1
= yc
- abs(radius
) * sin(angle
* self
._invradian
)
198 self
._angle
= (self
._angle
+ extent
) % self
._fullcircle
199 self
._position
= x1
, y1
201 self
._path
.append(self
._position
)
207 def setheading(self
, angle
):
211 def window_width(self
):
212 width
= self
._canvas
.winfo_width()
213 if width
<= 1: # the window isn't managed by a geometry manager
214 width
= self
._canvas
['width']
217 def window_height(self
):
218 height
= self
._canvas
.winfo_height()
219 if height
<= 1: # the window isn't managed by a geometry manager
220 height
= self
._canvas
['height']
224 x0
, y0
= self
._origin
225 x1
, y1
= self
._position
226 return [x1
-x0
, -y1
+y0
]
228 def setx(self
, xpos
):
229 x0
, y0
= self
._origin
230 x1
, y1
= self
._position
231 self
._goto
(x0
+xpos
, y1
)
233 def sety(self
, ypos
):
234 x0
, y0
= self
._origin
235 x1
, y1
= self
._position
236 self
._goto
(x1
, y0
-ypos
)
238 def goto(self
, *args
):
243 raise Error
, "bad point argument: %s" % `args
[0]`
248 raise Error
, "bad coordinates: %s" % `args
[0]`
249 x0
, y0
= self
._origin
250 self
._goto
(x0
+x
, y0
-y
)
252 def _goto(self
, x1
, y1
):
253 x0
, y0
= start
= self
._position
254 self
._position
= map(float, (x1
, y1
))
256 self
._path
.append(self
._position
)
261 distance
= hypot(dx
, dy
)
262 nhops
= int(distance
)
263 item
= self
._canvas
.create_line(x0
, y0
, x0
, y0
,
268 for i
in range(1, 1+nhops
):
269 x
, y
= x0
+ dx
*i
/nhops
, y0
+ dy
*i
/nhops
270 self
._canvas
.coords(item
, x0
, y0
, x
, y
)
271 self
._draw
_turtle
((x
,y
))
272 self
._canvas
.update()
273 self
._canvas
.after(10)
275 self
._canvas
.coords(item
, x0
, y0
, x1
, y1
)
276 self
._canvas
.itemconfigure(item
, arrow
="none")
277 except Tkinter
.TclError
:
278 # Probably the window was closed!
281 item
= self
._canvas
.create_line(x0
, y0
, x1
, y1
,
285 self
._items
.append(item
)
288 def _draw_turtle(self
,position
=[]):
289 if not self
._tracing
:
292 position
= self
._position
295 dx
= distance
* cos(self
._angle
*self
._invradian
)
296 dy
= distance
* sin(self
._angle
*self
._invradian
)
297 self
._delete
_turtle
()
298 self
._arrow
= self
._canvas
.create_line(x
-dx
,y
+dy
,x
,y
,
303 self
._canvas
.update()
305 def _delete_turtle(self
):
307 self
._canvas
.delete(self
._arrow
)
319 global _root
, _canvas
322 _root
.wm_protocol("WM_DELETE_WINDOW", self
._destroy
)
324 # XXX Should have scroll bars
325 _canvas
= Tkinter
.Canvas(_root
, background
="white")
326 _canvas
.pack(expand
=1, fill
="both")
327 RawPen
.__init
__(self
, _canvas
)
330 global _root
, _canvas
, _pen
331 root
= self
._canvas
._root
()
346 def degrees(): _getpen().degrees()
347 def radians(): _getpen().radians()
348 def reset(): _getpen().reset()
349 def clear(): _getpen().clear()
350 def tracer(flag
): _getpen().tracer(flag
)
351 def forward(distance
): _getpen().forward(distance
)
352 def backward(distance
): _getpen().backward(distance
)
353 def left(angle
): _getpen().left(angle
)
354 def right(angle
): _getpen().right(angle
)
355 def up(): _getpen().up()
356 def down(): _getpen().down()
357 def width(width
): _getpen().width(width
)
358 def color(*args
): _getpen().color(*args
)
359 def write(arg
, move
=0): _getpen().write(arg
, move
)
360 def fill(flag
): _getpen().fill(flag
)
361 def circle(radius
, extent
=None): _getpen().circle(radius
, extent
)
362 def goto(*args
): _getpen().goto(*args
)
363 def heading(): return _getpen().heading()
364 def setheading(angle
): _getpen().setheading(angle
)
365 def position(): return _getpen().position()
366 def window_width(): return _getpen().window_width()
367 def window_height(): return _getpen().window_height()
368 def setx(xpos
): _getpen().setx(xpos
)
369 def sety(ypos
): _getpen().sety(ypos
)
377 # draw 3 squares; the last filled
393 # move out of the way
403 write("startstart", 1)
422 if __name__
== '__main__':
425 if __name__
== '__main__':