Turtle Graphics – Retrieve Color of Overlapping Shapes

Question:

I have a red star partially inscribed within a purple square that contains an orange circle. I am extracting the color of the point that the user clicks on. When I click on the circle inside the square, the color that is returned is purple, not orange. The program also returns purple when I click on the part of the red star that is inside the square. How can I rectify this issue? Thank you.

import turtle

def border(height,color):

    height = float(height)
    length = height *(1.9)
    length = round(length,2)

    # Draws a rectangle.
    turtle.begin_fill()
    turtle.color(color)
    turtle.down()
    turtle.forward(length)
    turtle.right(90)
    turtle.forward(height)
    turtle.right(90)
    turtle.forward(length)
    turtle.right(90)
    turtle.forward(height)
    turtle.right(90)
    turtle.end_fill()

def big_shape(vertices, steps, length):
    turtle.color("red")
    turtle.begin_fill()
    for i in range(vertices):
        turtle.forward(length)
        turtle.right(steps*360.0/vertices)
    turtle.end_fill()

def textbox_click(rawx,rawy):
    turtle.up()
    turtle.setposition(rawx,rawy)
    turtle.down()
    rawy = -rawy
    canvas = turtle.getcanvas()
    canvas.pack(fill="both", expand=True)
    ids = canvas.find_overlapping(rawx, rawy, rawx, rawy)
    if ids: # if list is not empty
        index = ids[0]
        color = canvas.itemcget(index, "fill")
        if color != '':
            print(color.lower())

def getcoordinates():
    turtle.onscreenclick(turtle.goto)
    turtle.onscreenclick(modifyglobalvariables) # Here's the change!
    turtle.onscreenclick(textbox_click)

def modifyglobalvariables(rawx,rawy):
    global xclick
    global yclick
    xclick = int(rawx//1)
    yclick = int(rawy//1)
    print(xclick)
    print(yclick)

def main():
    border(150,"purple") 
    turtle.begin_fill()
    turtle.down()
    turtle.color("purple")
    turtle.up()

    # Creates the big shape

    x1=150
    y1=3
    turtle.setposition(x1,y1) 
    big_shape(5,2,50)
    turtle.begin_fill()
    turtle.down()
    turtle.up()

    # Circle
    x1=70
    y1=-107
    turtle.setposition(x1,y1) 
    turtle.begin_fill()
    turtle.circle(50)
    turtle.color("orange")
    turtle.end_fill()

    getcoordinates()

    turtle.done()
main()
Asked By: rtob

||

Answers:

I see two problems

First: see my code from previous question – you have to get last element ids[-1], not first ids[0], to get topmost element.

Second: you move turtle to clicked place so now turle is topmost – so you could move mouse after you get color and then you can still use

 index = ids[-1]

or you have to get second from the end ids[-2] but then you have to check if ids has at least two elements

if len(ids) > 1:     # if list has more than only turtle
    index = ids[-2]  # get second from the end
Answered By: furas

I suggest a different approach to this problem. Rather than use tkinter underpinnings to find the color of inactive objects (from turtle’s perspective), I recommend you work completely within turtle and make the drawn objects active. We can do this by making each drawing a turtle cursor so that we’re clicking on turtles, and interrogating their color, which is a simpler problem:

import turtle

def rectangle(height):
    length = height * 2

    turtle.begin_poly()
    for _ in range(2):
        turtle.forward(length)
        turtle.right(90)
        turtle.forward(height)
        turtle.right(90)
    turtle.end_poly()

    return turtle.get_poly()

def star(vertices, steps, length):
    angle = steps * 360.0 / vertices

    turtle.begin_poly()
    for _ in range(vertices):
        turtle.forward(length)
        turtle.right(angle)
    turtle.end_poly()

    return turtle.get_poly()

def circle(radius):
    turtle.begin_poly()
    turtle.circle(radius)
    turtle.end_poly()

    return turtle.get_poly()

def display_color(turtle):
    print(turtle.fillcolor())

def main():
    # Use the "default" turtle to draw the others
    turtle.penup()
    turtle.hideturtle()
    turtle.setheading(90)
    turtle.speed('fastest')

    screen.register_shape('rectangle', rectangle(150))
    screen.register_shape('star', star(5, 2, 50))
    screen.register_shape('circle', circle(50))

    rectangle_turtle = turtle.Turtle('rectangle')
    rectangle_turtle.penup()
    rectangle_turtle.color('purple')
    rectangle_turtle.onclick(lambda x, y: display_color(rectangle_turtle))

    star_turtle = turtle.Turtle('star')
    star_turtle.penup()
    star_turtle.setposition(150, 3)
    star_turtle.color('red')
    star_turtle.onclick(lambda x, y: display_color(star_turtle))

    circle_turtle = turtle.Turtle('circle')
    circle_turtle.penup()
    circle_turtle.setposition(70, -107)
    circle_turtle.color('orange')
    circle_turtle.onclick(lambda x, y: display_color(circle_turtle))

screen = turtle.Screen()

main()

screen.mainloop()

Now you should be able to click on any of the filled colored areas and you’ll see the name of the color printed in the console window. (After you click on the window itself to make it active.)

enter image description here

Answered By: cdlane
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.