Search code examples
pythonturtle-graphicspolygons

Python turtle end_poly() does not work


Turtle docs say when end_poly() is reached:

Stop recording the vertices of a polygon. Current turtle position is last vertex of polygon. This will be connected with the first vertex.

With my example, the final line is not drawn from the last vertex back to the first vertex. It acts the same in 2.7 and 3.7 Python.

from turtle import *

print("position 0:",position())
width(5)
pencolor("red")
fillcolor("blue")
begin_fill()
begin_poly()
fd(100)
print("position 1:",position())
left(90)
fd(100)
print("position 2:",position())
end_poly()
end_fill()

p = get_poly()
print("poly p:",p)
register_shape("myShape",p)
shapes_ = getshapes()
print("shapes_:", shapes_)

Output:

position 0: (0.00,0.00)
position 1: (100.00,0.00)
position 2: (100.00,100.00)
poly p: ((0.00,0.00), (100.00,0.00), (100.00,100.00))
shapes_: ['arrow', 'blank', 'circle', 'classic', 'myShape', 'square', 'triangle', 'turtle']

Image of polygon


Solution

  • I believe this is an error in the documentation, but an understandable one.

    First, you clearly can draw what you want by closing the figure yourself:

    from turtle import Turtle, Screen
    
    screen = Screen()
    turtle = Turtle(visible=False)
    
    turtle.width(5)
    turtle.color("red", "blue")
    
    position = turtle.position()
    
    turtle.begin_fill()
    turtle.forward(100)
    turtle.left(90)
    turtle.forward(100)
    turtle.goto(position)
    turtle.end_fill()
    
    screen.exitonclick()
    

    So what's the deal with polygons? Well, unless you implement the code yourself, there's nothing turtle can do, by default, with polygons, except use them as turtle cursors. In which case it's passing them onto tkinter which is responsible for the closing the polygon:

    from turtle import Turtle, Screen
    
    screen = Screen()
    turtle = Turtle(visible=False)
    turtle.penup()
    
    turtle.begin_poly()
    turtle.forward(100)
    turtle.left(90)
    turtle.forward(100)
    turtle.end_poly()
    
    screen.register_shape("myShape", turtle.get_poly())
    
    turtle.shape("myShape")  # when the polygon gets closed
    turtle.shapesize(outline=5)
    turtle.color("red", "blue")
    
    turtle.stamp()
    
    screen.exitonclick()
    

    (I'm guessing it's in tkinter's canvas.coords() where the polygon gets closed.) Note that your width(5) means nothing in this case, nor does *_fill() as a cursor's outline width is set using shapesize() and a cursor is naturally filled. It doesn't need a color specified at polygon creation time, you can wait until the new cursor is deployed.

    I believe this statement in the end_poly() documentation:

    last vertex of polygon. This will be connected with the first vertex.

    Should really reside in the polygon section of turtle's register_shape() documentation. But you can understand the error as turtle only thinks the role of *_poly() is for creating new cursors. Whereas polygons should be a first class, flexible datatype in turtle.