Warm tip: This article is reproduced from stackoverflow.com, please click
canvas python tkinter overlap

How can I find overlapping objects on a tkinter canvas?

发布于 2020-04-10 16:08:26

is there any easy way to find the objects ids that are overlapped? Here's an example of the code:

import tkinter as tk
import random as rand


class GUI:
    def __init__(self, master, width, height):
        self.master = master
        self.w = width
        self.h = height
        self.canvas = tk.Canvas(master, width=width, height=height)
        self.canvas.pack()
        self.create_objects()

    def create_objects(self):
        r = 5
        for i in range(100):
            x = rand.uniform(0,1)*width
            y = rand.uniform(0,1)*height
            self.canvas.create_oval(x-r,y-r,x+r,y+r, fill="red")

    def find_overlaps(self):
        pass


width = 800
height = 600

root = tk.Tk()
app = GUI(root, width, height)
root.mainloop()

I would like for the find_overlaps function to give me the pairs of the object ids that are overlapped (or tripplets if such case happen). Is there any easy/efficient way to do it?

Questioner
Daniel Casasampera
Viewed
459
mathfux 2020-02-02 05:42

Here are steps that is possible for you to do here:

  1. Get the tuples of ids of objects you have created on canvas. You can do it using canvas.find_all() method.
  2. Get coordinates of these objects using canvas.coords(id).

I have checked out standard find_overlapping method of canvas. It helps to determine which object are overlapped with specific rectangle only and I guess you need to solve problem you mentioned using some mathematics with a help of this method. Although, I have found a nice alternative, not based on find_overlapping:

def find_overlaps(self):
    r = 5
    X = []
    tags = self.canvas.find_all() #finds tags of all the object created
    for tag in tags:
        x0, y0, x1, y1 = self.canvas.coords(tag) # corresponding coordinates
        center = [(x0+x1)/2, (y0+y1)/2] #centers of objects
        X.append(center)

    tree = cKDTree(X)
    print(tree.query_pairs(2*r))

Output

This is a set of couples of tags:

{(2, 63), (10, 93), (70, 82), (8, 45)}

Note

from scipy.spatial import cKDTree is required