1 # LogoMation-like turtle graphics
3 from math
import * # Also for export
10 def __init__(self
, canvas
):
17 def degrees(self
, fullcircle
=360.0):
18 self
._fullcircle
= fullcircle
19 self
._invradian
= pi
/ (fullcircle
* 0.5)
26 width
= canvas
.winfo_width()
27 height
= canvas
.winfo_height()
29 width
= canvas
['width']
31 height
= canvas
['height']
32 self
._origin
= float(width
)/2.0, float(height
)/2.0
33 self
._position
= self
._origin
42 canvas
._root
().tkraise()
52 def tracer(self
, flag
):
55 def forward(self
, distance
):
56 x0
, y0
= start
= self
._position
57 x1
= x0
+ distance
* cos(self
._angle
*self
._invradian
)
58 y1
= y0
- distance
* sin(self
._angle
*self
._invradian
)
61 def backward(self
, distance
):
62 self
.forward(-distance
)
64 def left(self
, angle
):
65 self
._angle
= (self
._angle
+ angle
) % self
._fullcircle
67 def right(self
, angle
):
76 def width(self
, width
):
77 self
._width
= float(width
)
79 def color(self
, *args
):
81 raise Error
, "no color arguments"
84 if type(color
) == type(""):
85 # Test the color first
87 id = self
._canvas
.create_line(0, 0, 0, 0, fill
=color
)
89 raise Error
, "bad color string: %s" % `color`
95 raise Error
, "bad color sequence: %s" % `color`
100 raise Error
, "bad color arguments: %s" % `args`
106 self
._color
= "#%02x%02x%02x" % (int(r
*x
+y
), int(g
*x
+y
), int(b
*x
+y
))
108 def write(self
, arg
, move
=0):
109 x
, y
= start
= self
._position
110 x
= x
-1 # correction -- calibrated for Windows
111 item
= self
._canvas
.create_text(x
, y
,
112 text
=str(arg
), anchor
="sw",
114 self
._items
.append(item
)
116 x0
, y0
, x1
, y1
= self
._canvas
.bbox(item
)
119 def fill(self
, flag
):
121 path
= tuple(self
._path
)
122 smooth
= self
._filling
< 0
124 item
= self
._canvas
._create
('polygon', path
,
125 {'fill': self
._color
,
127 self
._items
.append(item
)
128 self
._canvas
.lower(item
)
130 for item
in self
._tofill
:
131 self
._canvas
.itemconfigure(item
, fill
=self
._color
)
132 self
._items
.append(item
)
137 self
._path
.append(self
._position
)
139 def circle(self
, radius
, extent
=None):
141 extent
= self
._fullcircle
142 x0
, y0
= self
._position
143 xc
= x0
- radius
* sin(self
._angle
* self
._invradian
)
144 yc
= y0
- radius
* cos(self
._angle
* self
._invradian
)
146 start
= self
._angle
- 90.0
148 start
= self
._angle
+ 90.0
151 if abs(extent
) >= self
._fullcircle
:
152 item
= self
._canvas
.create_oval(xc
-radius
, yc
-radius
,
153 xc
+radius
, yc
+radius
,
156 self
._tofill
.append(item
)
157 item
= self
._canvas
.create_arc(xc
-radius
, yc
-radius
,
158 xc
+radius
, yc
+radius
,
164 self
._tofill
.append(item
)
166 if abs(extent
) >= self
._fullcircle
:
167 item
= self
._canvas
.create_oval(xc
-radius
, yc
-radius
,
168 xc
+radius
, yc
+radius
,
171 self
._items
.append(item
)
172 item
= self
._canvas
.create_arc(xc
-radius
, yc
-radius
,
173 xc
+radius
, yc
+radius
,
179 self
._items
.append(item
)
180 angle
= start
+ extent
181 x1
= xc
+ abs(radius
) * cos(angle
* self
._invradian
)
182 y1
= yc
- abs(radius
) * sin(angle
* self
._invradian
)
183 self
._angle
= (self
._angle
+ extent
) % self
._fullcircle
184 self
._position
= x1
, y1
186 self
._path
.append(self
._position
)
188 def goto(self
, *args
):
193 raise Error
, "bad point argument: %s" % `args
[0]`
198 raise Error
, "bad coordinates: %s" % `args
[0]`
199 x0
, y0
= self
._origin
200 self
._goto
(x0
+x
, y0
-y
)
202 def _goto(self
, x1
, y1
):
203 x0
, y0
= start
= self
._position
204 self
._position
= map(float, (x1
, y1
))
206 self
._path
.append(self
._position
)
211 distance
= hypot(dx
, dy
)
212 nhops
= int(distance
)
213 item
= self
._canvas
.create_line(x0
, y0
, x0
, y0
,
219 for i
in range(1, 1+nhops
):
220 x
, y
= x0
+ dx
*i
/nhops
, y0
+ dy
*i
/nhops
221 self
._canvas
.coords(item
, x0
, y0
, x
, y
)
222 self
._canvas
.update()
223 self
._canvas
.after(10)
224 self
._canvas
.itemconfigure(item
, arrow
="none")
226 # Probably the window was closed!
229 item
= self
._canvas
.create_line(x0
, y0
, x1
, y1
,
233 self
._items
.append(item
)
243 global _root
, _canvas
246 _root
.wm_protocol("WM_DELETE_WINDOW", self
._destroy
)
248 # XXX Should have scroll bars
249 _canvas
= Tk
.Canvas(_root
, background
="white")
250 _canvas
.pack(expand
=1, fill
="both")
251 RawPen
.__init
__(self
, _canvas
)
254 global _root
, _canvas
, _pen
255 root
= self
._canvas
._root
()
270 def degrees(): _getpen().degrees()
271 def radians(): _getpen().radians()
272 def reset(): _getpen().reset()
273 def clear(): _getpen().clear()
274 def tracer(flag
): _getpen().tracer(flag
)
275 def forward(distance
): _getpen().forward(distance
)
276 def backward(distance
): _getpen().backward(distance
)
277 def left(angle
): _getpen().left(angle
)
278 def right(angle
): _getpen().right(angle
)
279 def up(): _getpen().up()
280 def down(): _getpen().down()
281 def width(width
): _getpen().width(width
)
282 def color(*args
): apply(_getpen().color
, args
)
283 def write(arg
, move
=0): _getpen().write(arg
, move
)
284 def fill(flag
): _getpen().fill(flag
)
285 def circle(radius
, extent
=None): _getpen().circle(radius
, extent
)
286 def goto(*args
): apply(_getpen().goto
, args
)
294 # draw 3 squares; the last filled
310 # move out of the way
320 write("startstart", 1)
339 if __name__
== '__main__':
342 if __name__
== '__main__':