как закрасить пересечение прямоугольников

рисуются 2 или несколько прямоугольников нужно по нажатию кнопки закрасить их пересечение

from tkinter import *

def is_cross(a,b):
    ax1,ay1,ax2,ay2 = a[0],a[1],a[2],a[3]          # прямоугольник А
    bx1, by1, bx2, by2 = b[0], b[1], b[2], b[3]    # прямоугольник B

    xA = [ax1,ax2]  # координаты x обеих точек прямоугольника А
    xB = [bx1,bx2]  # координаты x обеих точке прямоугольника В

    yA = [ay1, ay2]  # координаты x обеих точек прямоугольника А
    yB = [by1, by2]  # координаты x обеих точек прямоугольника В

    if max(xA)<min(xB) or max(yA) < min(yB) or min(yA) > max(yB):
        return False    # не пересекаются

    elif max(xA)>min(xB) and min(xA)<min(xB):
        dx = max(xA)-min(xB)
        return True     # пересекаются
    else:
        return True     # пересекаются

def click(click_event):
   global prev
   try:
       canvas.create_rectangle(prev.x, prev.y, click_event.x, click_event.y, width=2)
   except:
       prev = click_event
       return
   prev = click_event


master = Tk()
canvas = Canvas(master, width=600, height=300)
canvas.pack(padx=20, pady=20)
canvas.bind('<Button-1>', click)
but1 = Button(master, text='ок', command=is_cross );
mainloop()

введите сюда описание изображения


Ответы (1 шт):

Автор решения: MiniMax

Вариант № 1.1

Прямоугольники рисуются двумя кликами мыши: первый клик - начало, второй клик - конец. Для хранения координат прямоугольников используются обыкновенный список.

#!/usr/bin/python3

import tkinter as tk

start = None
rectangles = []

def is_cross():
    global rectangles

    a, b = rectangles
    a_left, a_bottom, a_right, a_top = a
    b_left, b_bottom, b_right, b_top = b

    if not (a_left >= b_right or a_bottom <= b_top or
            b_left >= a_right or b_bottom <= a_top):

        left = max(a_left, b_left)
        right = min(a_right, b_right)
        bottom = min(a_bottom, b_bottom)
        top = max(a_top, b_top)

        rectangle = (left, bottom, right, top)
        canvas.create_rectangle(rectangle, fill="red")

    rectangles = []

def click(click_event):
    global start, rectangles

    if start is None:
        start = click_event
    else:
        left, right = (start.x, click_event.x) if start.x < click_event.x else (click_event.x, start.x)
        top, bottom = (start.y, click_event.y) if start.y < click_event.y else (click_event.y, start.y)

        rectangle = (left, bottom, right, top)

        canvas.create_rectangle(rectangle)
        rectangles.append(rectangle)
        start = None


master = tk.Tk()
canvas = tk.Canvas(master, width=600, height=300)
canvas.pack()
canvas.bind('<Button-1>', click)

but1 = tk.Button(master, text='ок', command=is_cross);
but1.pack()
tk.mainloop()

Вариант № 1.2

В отличии от предыдущего варианта, прямоугольники (координаты) не хранятся в списке, а находятся по заданному тегу, после чего из них извлекаются координаты.

import tkinter as tk

start = None

def is_cross():

    a, b = canvas.find_withtag("rctnlg")[-2:]

    a_left, a_top, a_right, a_bottom = canvas.coords(a)
    b_left, b_top, b_right, b_bottom = canvas.coords(b)

    if not (a_left >= b_right or a_bottom <= b_top or
            b_left >= a_right or b_bottom <= a_top):

        left = max(a_left, b_left)
        top = max(a_top, b_top)
        right = min(a_right, b_right)
        bottom = min(a_bottom, b_bottom)

        rectangle = (left, top, right, bottom)
        canvas.create_rectangle(rectangle, fill="red")

def click(click_event):
    global start

    if start is None:
        start = click_event
    else:
        left, right = (start.x, click_event.x) if start.x < click_event.x else (click_event.x, start.x)
        top, bottom = (start.y, click_event.y) if start.y < click_event.y else (click_event.y, start.y)

        coords = (left, top, right, bottom)

        canvas.create_rectangle(coords, tags=("rctnlg"))

        start = None

master = tk.Tk()
canvas = tk.Canvas(master, width=600, height=300)
canvas.pack()
canvas.bind('<Button-1>', click)

but1 = tk.Button(master, text='ок', command=is_cross);
but1.pack()

tk.mainloop()

Вариант № 2

Прямоугольники рисуются с помощью растягивания мышкой. Взял и доработал код из этого ответа

import tkinter as tk

class App(tk.Frame):
    def __init__(self, parent):
        super().__init__(parent)

        self._createVariables(parent)
        self._createCanvas()
        self._createCanvasBinding()

        self.btn1 = tk.Button(self.parent, text='ок', command=self.is_cross);
        self.btn1.grid(row=1, column=0)

    def is_cross(self):
        a, b = self.rectangles

        a_left, a_bottom, a_right, a_top = a
        b_left, b_bottom, b_right, b_top = b

        if not (a_left >= b_right or a_bottom <= b_top or
                b_left >= a_right or b_bottom <= a_top):

            left = max(a_left, b_left)
            right = min(a_right, b_right)
            bottom = min(a_bottom, b_bottom)
            top = max(a_top, b_top)

            rectangle = (left, bottom, right, top)
            self.canvas.create_rectangle(rectangle, fill="red")

        self.rectangles = []

    def _createVariables(self, parent):
        self.parent = parent
        self.rect_x0 = 0
        self.rect_y0 = 0
        self.rect_x1 = 0
        self.rect_y1 = 0
        self.rectid = None
        self.rectangles = []

    def _createCanvas(self):
        self.canvas = tk.Canvas(self.parent, width = 800, height = 400, bg = "white" )
        self.canvas.grid(row=0, column=0, sticky='nsew')

    def _createCanvasBinding(self):
        self.canvas.bind("<Button-1>", self.startRect )
        self.canvas.bind("<ButtonRelease-1>", self.stopRect )
        self.canvas.bind("<B1-Motion>", self.movingRect )

    def startRect(self, event):
        #Translate mouse screen x0,y0 coordinates to canvas coordinates
        self.rect_x0 = self.canvas.canvasx(event.x)
        self.rect_y0 = self.canvas.canvasy(event.y) 
        #Create rectangle

        self.rectid = self.canvas.create_rectangle(self.rect_x0, self.rect_y0, self.rect_x0, self.rect_y0)

    def movingRect(self, event):
        #Translate mouse screen x1,y1 coordinates to canvas coordinates
        self.rect_x1 = self.canvas.canvasx(event.x)
        self.rect_y1 = self.canvas.canvasy(event.y)
        #Modify rectangle x1, y1 coordinates
        self.canvas.coords(self.rectid, self.rect_x0, self.rect_y0,
                      self.rect_x1, self.rect_y1)

    def stopRect(self, event):
        #Translate mouse screen x1,y1 coordinates to canvas coordinates
        self.rect_x1 = self.canvas.canvasx(event.x)
        self.rect_y1 = self.canvas.canvasy(event.y)
        #Modify rectangle x1, y1 coordinates
        self.canvas.coords(self.rectid, self.rect_x0, self.rect_y0,
                      self.rect_x1, self.rect_y1)

        left, right = (self.rect_x0, self.rect_x1) if self.rect_x0 < self.rect_x1 else (self.rect_x1, self.rect_x0)
        top, bottom = (self.rect_y1, self.rect_y0) if self.rect_y1 < self.rect_y0 else (self.rect_y0, self.rect_y1)

        rectangle = (left, bottom, right, top)
        self.rectangles.append(rectangle)


if __name__ == "__main__":
    root = tk.Tk()
    root.geometry("800x500")
    app = App(root)
    root.mainloop()
→ Ссылка