# LogoMation-like turtle graphics """Turtle graphics is a popular way for introducing programming tokids. It was part of the original Logo programming language developedby Wally Feurzeig and Seymour Papert in 1966. Imagine a robotic turtle starting at (0, 0) in the x-y plane. Give itthe command turtle.forward(15), and it moves (on-screen!) 15 pixels inthe direction it is facing, drawing a line as it moves. Give it thecommand turtle.left(25), and it rotates in-place 25 degrees clockwise. By combining together these and similar commands, intricate shapes andpictures can easily be drawn.""" from math import * # Also for exportimport Tkinter speeds = ['fastest', 'fast', 'normal', 'slow', 'slowest'] class Error(Exception): pass class RawPen: def __init__(self, canvas): self._canvas = canvas self._items = [] self._tracing = 1 self._arrow = 0 self._delay = 10 # default delay for drawing self._angle = 0.0 self.degrees() self.reset() def degrees(self, fullcircle=360.0): """ Set angle measurement units to degrees. Example: >>> turtle.degrees() """ # Don't try to change _angle if it is 0, because # _fullcircle might not be set, yet if self._angle: self._angle = (self._angle / self._fullcircle) * fullcircle self._fullcircle = fullcircle self._invradian = pi / (fullcircle * 0.5) def radians(self): """ Set the angle measurement units to radians. Example: >>> turtle.radians() """ self.degrees(2.0*pi) def reset(self): """ Clear the screen, re-center the pen, and set variables to the default values. Example: >>> turtle.position() [0.0, -22.0] >>> turtle.heading() 100.0 >>> turtle.reset() >>> turtle.position() [0.0, 0.0] >>> turtle.heading() 0.0 """ canvas = self._canvas self._canvas.update() width = canvas.winfo_width() height = canvas.winfo_height() if width <= 1: width = canvas['width'] if height <= 1: height = canvas['height'] self._origin = float(width)/2.0, float(height)/2.0 self._position = self._origin self._angle = 0.0 self._drawing = 1 self._width = 1 self._color = "black" self._filling = 0 self._path = [] self.clear() canvas._root().tkraise() def clear(self): """ Clear the screen. The turtle does not move. Example: >>> turtle.clear() """ self.fill(0) canvas = self._canvas items = self._items self._items = [] for item in items: canvas.delete(item) self._delete_turtle() self._draw_turtle() def tracer(self, flag): """ Set tracing on if flag is True, and off if it is False. Tracing means line are drawn more slowly, with an animation of an arrow along the line. Example: >>> turtle.tracer(False) # turns off Tracer """ self._tracing = flag if not self._tracing: self._delete_turtle() self._draw_turtle() def forward(self, distance): """ Go forward distance steps. Example: >>> turtle.position() [0.0, 0.0] >>> turtle.forward(25) >>> turtle.position() [25.0, 0.0] >>> turtle.forward(-75) >>> turtle.position() [-50.0, 0.0] """ x0, y0 = start = self._position x1 = x0 + distance * cos(self._angle*self._invradian) y1 = y0 - distance * sin(self._angle*self._invradian) self._goto(x1, y1) def backward(self, distance): """ Go backwards distance steps. The turtle's heading does not change. Example: >>> turtle.position() [0.0, 0.0] >>> turtle.backward(30) >>> turtle.position() [-30.0, 0.0] """ self.forward(-distance) def left(self, angle): """ Turn left angle units (units are by default degrees, but can be set via the degrees() and radians() functions.) When viewed from above, the turning happens in-place around its front tip. Example: >>> turtle.heading() 22 >>> turtle.left(45) >>> turtle.heading() 67.0 """ self._angle = (self._angle + angle) % self._fullcircle self._draw_turtle() def right(self, angle): """ Turn right angle units (units are by default degrees, but can be set via the degrees() and radians() functions.) When viewed from above, the turning happens in-place around its front tip. Example: >>> turtle.heading() 22 >>> turtle.right(45) >>> turtle.heading() 337.0 """ self.left(-angle) def up(self): """ Pull the pen up -- no drawing when moving. Example: >>> turtle.up() """ self._drawing = 0 def down(self): """ Put the pen down -- draw when moving. Example: >>> turtle.down() """ self._drawing = 1 def width(self, width): """ Set the line to thickness to width. Example: >>> turtle.width(10) """ self._width = float(width) def color(self, *args): """ Set the pen color. Three input formats are allowed: color(s) s is a Tk specification string, such as "red" or "yellow" color((r, g, b)) *a tuple* of r, g, and b, which represent, an RGB color, and each of r, g, and b are in the range [0..1] color(r, g, b) r, g, and b represent an RGB color, and each of r, g, and b are in the range [0..1] Example: >>> turtle.color('brown') >>> tup = (0.2, 0.8, 0.55) >>> turtle.color(tup) >>> turtle.color(0, .5, 0) """ if not args: raise Error, "no color arguments" if len(args) == 1: color = args[0] if type(color) == type(""): # Test the color first try: id = self._canvas.create_line(0, 0, 0, 0, fill=color) except Tkinter.TclError: raise Error, "bad color string: %r" % (color,) self._set_color(color) return try: r, g, b = color except: raise Error, "bad color sequence: %r" % (color,) else: try: r, g, b = args except: raise Error, "bad color arguments: %r" % (args,) assert 0 <= r <= 1 assert 0 <= g <= 1 assert 0 <= b <= 1 x = 255.0 y = 0.5 self._set_color("#%02x%02x%02x" % (int(r*x+y), int(g*x+y), int(b*x+y))) def _set_color(self,color): self._color = color self._draw_turtle() def write(self, text, move=False): """ Write text at the current pen position. If move is true, the pen is moved to the bottom-right corner of the text. By default, move is False. Example: >>> turtle.write('The race is on!') >>> turtle.write('Home = (0, 0)', True) """ x, y = self._position x = x-1 # correction -- calibrated for Windows item = self._canvas.create_text(x, y, text=str(text), anchor="sw", fill=self._color) self._items.append(item) if move: x0, y0, x1, y1 = self._canvas.bbox(item) self._goto(x1, y1) self._draw_turtle() def fill(self, flag): """ Call fill(1) before drawing the shape you want to fill, and fill(0) when done. Example: >>> turtle.fill(1) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.fill(0) """ if self._filling: path = tuple(self._path) smooth = self._filling < 0 if len(path) > 2: item = self._canvas._create('polygon', path, {'fill': self._color, 'smooth': smooth}) self._items.append(item) self._path = [] self._filling = flag if flag: self._path.append(self._position) def begin_fill(self): """ Called just before drawing a shape to be filled. Must eventually be followed by a corresponding end_fill() call. Otherwise it will be ignored. Example: >>> turtle.begin_fill() >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.end_fill() """ self._path = [self._position] self._filling = 1 def end_fill(self): """ Called after drawing a shape to be filled. Example: >>> turtle.begin_fill() >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.end_fill() """ self.fill(0) def circle(self, radius, extent = None): """ Draw a circle with given radius. The center is radius units left of the turtle; extent determines which part of the circle is drawn. If not given, the entire circle is drawn. If extent is not a full circle, one endpoint of the arc is the current pen position. The arc is drawn in a counter clockwise direction if radius is positive, otherwise in a clockwise direction. In the process, the direction of the turtle is changed by the amount of the extent. >>> turtle.circle(50) >>> turtle.circle(120, 180) # half a circle """ if extent is None: extent = self._fullcircle frac = abs(extent)/self._fullcircle steps = 1+int(min(11+abs(radius)/6.0, 59.0)*frac) w = 1.0 * extent / steps w2 = 0.5 * w l = 2.0 * radius * sin(w2*self._invradian) if radius < 0: l, w, w2 = -l, -w, -w2 self.left(w2) for i in range(steps): self.forward(l) self.left(w) self.right(w2) def heading(self): """ Return the turtle's current heading. Example: >>> turtle.heading() 67.0 """ return self._angle def setheading(self, angle): """ Set the turtle facing the given angle. Here are some common directions in degrees: 0 - east 90 - north 180 - west 270 - south Example: >>> turtle.setheading(90) >>> turtle.heading() 90 >>> turtle.setheading(128) >>> turtle.heading() 128 """ self._angle = angle self._draw_turtle() def window_width(self): """ Returns the width of the turtle window. Example: >>> turtle.window_width() 640 """ width = self._canvas.winfo_width() if width <= 1: # the window isn't managed by a geometry manager width = self._canvas['width'] return width def window_height(self): """ Return the height of the turtle window. Example: >>> turtle.window_height() 768 """ height = self._canvas.winfo_height() if height <= 1: # the window isn't managed by a geometry manager height = self._canvas['height'] return height def position(self): """ Return the current (x, y) location of the turtle. Example: >>> turtle.position() [0.0, 240.0] """ x0, y0 = self._origin x1, y1 = self._position return [x1-x0, -y1+y0] def setx(self, xpos): """ Set the turtle's x coordinate to be xpos. Example: >>> turtle.position() [10.0, 240.0] >>> turtle.setx(10) >>> turtle.position() [10.0, 240.0] """ x0, y0 = self._origin x1, y1 = self._position self._goto(x0+xpos, y1) def sety(self, ypos): """ Set the turtle's y coordinate to be ypos. Example: >>> turtle.position() [0.0, 0.0] >>> turtle.sety(-22) >>> turtle.position() [0.0, -22.0] """ x0, y0 = self._origin x1, y1 = self._position self._goto(x1, y0-ypos) def towards(self, *args): """Returs the angle, which corresponds to the line from turtle-position to point (x,y). Argument can be two coordinates or one pair of coordinates or a RawPen/Pen instance. Example: >>> turtle.position() [10.0, 10.0] >>> turtle.towards(0,0) 225.0 """ if len(args) == 2: x, y = args else: arg = args[0] if isinstance(arg, RawPen): x, y = arg.position() else: x, y = arg x0, y0 = self.position() dx = x - x0 dy = y - y0 return (atan2(dy,dx) / self._invradian) % self._fullcircle def goto(self, *args): """ Go to the given point. If the pen is down, then a line will be drawn. The turtle'sLines 1–500 of 956. Load more
# LogoMation-like turtle graphics """ Turtle graphics is a popular way for introducing programming to kids. It was part of the original Logo programming language developed by Wally Feurzeig and Seymour Papert in 1966. Imagine a robotic turtle starting at (0, 0) in the x-y plane. Give it the command turtle.forward(15), and it moves (on-screen!) 15 pixels in the direction it is facing, drawing a line as it moves. Give it the command turtle.left(25), and it rotates in-place 25 degrees clockwise. By combining together these and similar commands, intricate shapes and pictures can easily be drawn. """ from math import * # Also for export import Tkinter speeds = ['fastest', 'fast', 'normal', 'slow', 'slowest'] class Error(Exception): pass class RawPen: def __init__(self, canvas): self._canvas = canvas self._items = [] self._tracing = 1 self._arrow = 0 self._delay = 10 # default delay for drawing self._angle = 0.0 self.degrees() self.reset() def degrees(self, fullcircle=360.0): """ Set angle measurement units to degrees. Example: >>> turtle.degrees() """ # Don't try to change _angle if it is 0, because # _fullcircle might not be set, yet if self._angle: self._angle = (self._angle / self._fullcircle) * fullcircle self._fullcircle = fullcircle self._invradian = pi / (fullcircle * 0.5) def radians(self): """ Set the angle measurement units to radians. Example: >>> turtle.radians() """ self.degrees(2.0*pi) def reset(self): """ Clear the screen, re-center the pen, and set variables to the default values. Example: >>> turtle.position() [0.0, -22.0] >>> turtle.heading() 100.0 >>> turtle.reset() >>> turtle.position() [0.0, 0.0] >>> turtle.heading() 0.0 """ canvas = self._canvas self._canvas.update() width = canvas.winfo_width() height = canvas.winfo_height() if width <= 1: width = canvas['width'] if height <= 1: height = canvas['height'] self._origin = float(width)/2.0, float(height)/2.0 self._position = self._origin self._angle = 0.0 self._drawing = 1 self._width = 1 self._color = "black" self._filling = 0 self._path = [] self.clear() canvas._root().tkraise() def clear(self): """ Clear the screen. The turtle does not move. Example: >>> turtle.clear() """ self.fill(0) canvas = self._canvas items = self._items self._items = [] for item in items: canvas.delete(item) self._delete_turtle() self._draw_turtle() def tracer(self, flag): """ Set tracing on if flag is True, and off if it is False. Tracing means line are drawn more slowly, with an animation of an arrow along the line. Example: >>> turtle.tracer(False) # turns off Tracer """ self._tracing = flag if not self._tracing: self._delete_turtle() self._draw_turtle() def forward(self, distance): """ Go forward distance steps. Example: >>> turtle.position() [0.0, 0.0] >>> turtle.forward(25) >>> turtle.position() [25.0, 0.0] >>> turtle.forward(-75) >>> turtle.position() [-50.0, 0.0] """ x0, y0 = start = self._position x1 = x0 + distance * cos(self._angle*self._invradian) y1 = y0 - distance * sin(self._angle*self._invradian) self._goto(x1, y1) def backward(self, distance): """ Go backwards distance steps. The turtle's heading does not change. Example: >>> turtle.position() [0.0, 0.0] >>> turtle.backward(30) >>> turtle.position() [-30.0, 0.0] """ self.forward(-distance) def left(self, angle): """ Turn left angle units (units are by default degrees, but can be set via the degrees() and radians() functions.) When viewed from above, the turning happens in-place around its front tip. Example: >>> turtle.heading() 22 >>> turtle.left(45) >>> turtle.heading() 67.0 """ self._angle = (self._angle + angle) % self._fullcircle self._draw_turtle() def right(self, angle): """ Turn right angle units (units are by default degrees, but can be set via the degrees() and radians() functions.) When viewed from above, the turning happens in-place around its front tip. Example: >>> turtle.heading() 22 >>> turtle.right(45) >>> turtle.heading() 337.0 """ self.left(-angle) def up(self): """ Pull the pen up -- no drawing when moving. Example: >>> turtle.up() """ self._drawing = 0 def down(self): """ Put the pen down -- draw when moving. Example: >>> turtle.down() """ self._drawing = 1 def width(self, width): """ Set the line to thickness to width. Example: >>> turtle.width(10) """ self._width = float(width) def color(self, *args): """ Set the pen color. Three input formats are allowed: color(s) s is a Tk specification string, such as "red" or "yellow" color((r, g, b)) *a tuple* of r, g, and b, which represent, an RGB color, and each of r, g, and b are in the range [0..1] color(r, g, b) r, g, and b represent an RGB color, and each of r, g, and b are in the range [0..1] Example: >>> turtle.color('brown') >>> tup = (0.2, 0.8, 0.55) >>> turtle.color(tup) >>> turtle.color(0, .5, 0) """ if not args: raise Error, "no color arguments" if len(args) == 1: color = args[0] if type(color) == type(""): # Test the color first try: id = self._canvas.create_line(0, 0, 0, 0, fill=color) except Tkinter.TclError: raise Error, "bad color string: %r" % (color,) self._set_color(color) return try: r, g, b = color except: raise Error, "bad color sequence: %r" % (color,) else: try: r, g, b = args except: raise Error, "bad color arguments: %r" % (args,) assert 0 <= r <= 1 assert 0 <= g <= 1 assert 0 <= b <= 1 x = 255.0 y = 0.5 self._set_color("#%02x%02x%02x" % (int(r*x+y), int(g*x+y), int(b*x+y))) def _set_color(self,color): self._color = color self._draw_turtle() def write(self, text, move=False): """ Write text at the current pen position. If move is true, the pen is moved to the bottom-right corner of the text. By default, move is False. Example: >>> turtle.write('The race is on!') >>> turtle.write('Home = (0, 0)', True) """ x, y = self._position x = x-1 # correction -- calibrated for Windows item = self._canvas.create_text(x, y, text=str(text), anchor="sw", fill=self._color) self._items.append(item) if move: x0, y0, x1, y1 = self._canvas.bbox(item) self._goto(x1, y1) self._draw_turtle() def fill(self, flag): """ Call fill(1) before drawing the shape you want to fill, and fill(0) when done. Example: >>> turtle.fill(1) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.fill(0) """ if self._filling: path = tuple(self._path) smooth = self._filling < 0 if len(path) > 2: item = self._canvas._create('polygon', path, {'fill': self._color, 'smooth': smooth}) self._items.append(item) self._path = [] self._filling = flag if flag: self._path.append(self._position) def begin_fill(self): """ Called just before drawing a shape to be filled. Must eventually be followed by a corresponding end_fill() call. Otherwise it will be ignored. Example: >>> turtle.begin_fill() >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.end_fill() """ self._path = [self._position] self._filling = 1 def end_fill(self): """ Called after drawing a shape to be filled. Example: >>> turtle.begin_fill() >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.left(90) >>> turtle.forward(100) >>> turtle.end_fill() """ self.fill(0) def circle(self, radius, extent = None): """ Draw a circle with given radius. The center is radius units left of the turtle; extent determines which part of the circle is drawn. If not given, the entire circle is drawn. If extent is not a full circle, one endpoint of the arc is the current pen position. The arc is drawn in a counter clockwise direction if radius is positive, otherwise in a clockwise direction. In the process, the direction of the turtle is changed by the amount of the extent. >>> turtle.circle(50) >>> turtle.circle(120, 180) # half a circle """ if extent is None: extent = self._fullcircle frac = abs(extent)/self._fullcircle steps = 1+int(min(11+abs(radius)/6.0, 59.0)*frac) w = 1.0 * extent / steps w2 = 0.5 * w l = 2.0 * radius * sin(w2*self._invradian) if radius < 0: l, w, w2 = -l, -w, -w2 self.left(w2) for i in range(steps): self.forward(l) self.left(w) self.right(w2) def heading(self): """ Return the turtle's current heading. Example: >>> turtle.heading() 67.0 """ return self._angle def setheading(self, angle): """ Set the turtle facing the given angle. Here are some common directions in degrees: 0 - east 90 - north 180 - west 270 - south Example: >>> turtle.setheading(90) >>> turtle.heading() 90 >>> turtle.setheading(128) >>> turtle.heading() 128 """ self._angle = angle self._draw_turtle() def window_width(self): """ Returns the width of the turtle window. Example: >>> turtle.window_width() 640 """ width = self._canvas.winfo_width() if width <= 1: # the window isn't managed by a geometry manager width = self._canvas['width'] return width def window_height(self): """ Return the height of the turtle window. Example: >>> turtle.window_height() 768 """ height = self._canvas.winfo_height() if height <= 1: # the window isn't managed by a geometry manager height = self._canvas['height'] return height def position(self): """ Return the current (x, y) location of the turtle. Example: >>> turtle.position() [0.0, 240.0] """ x0, y0 = self._origin x1, y1 = self._position return [x1-x0, -y1+y0] def setx(self, xpos): """ Set the turtle's x coordinate to be xpos. Example: >>> turtle.position() [10.0, 240.0] >>> turtle.setx(10) >>> turtle.position() [10.0, 240.0] """ x0, y0 = self._origin x1, y1 = self._position self._goto(x0+xpos, y1) def sety(self, ypos): """ Set the turtle's y coordinate to be ypos. Example: >>> turtle.position() [0.0, 0.0] >>> turtle.sety(-22) >>> turtle.position() [0.0, -22.0] """ x0, y0 = self._origin x1, y1 = self._position self._goto(x1, y0-ypos) def towards(self, *args): """Returs the angle, which corresponds to the line from turtle-position to point (x,y). Argument can be two coordinates or one pair of coordinates or a RawPen/Pen instance. Example: >>> turtle.position() [10.0, 10.0] >>> turtle.towards(0,0) 225.0 """ if len(args) == 2: x, y = args else: arg = args[0] if isinstance(arg, RawPen): x, y = arg.position() else: x, y = arg x0, y0 = self.position() dx = x - x0 dy = y - y0 return (atan2(dy,dx) / self._invradian) % self._fullcircle def goto(self, *args): """ Go to the given point. If the pen is down, then a line will be drawn. The turtle's