Как определить, в какую из треугольных областей попадает координата?

Моя идея в том, чтобы зная только x и y координаты мыши проверять в какой из областей экрана находится курсор, разделить нужно в таком виде:экран

Необязательна полная реализации в виде кода, но хотя бы решение в теоретическом виде.


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

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

Интересная задача, так что решил сделать для вас небольшой пример.

Код:

from collections import namedtuple
import ctypes
import win32con
import win32api
import win32gui
import atexit
# pip install pywin32

MouseEvent = namedtuple('MouseEvent', ['event_type', 'x', 'y'])
handlers = []

def listen():
    def low_level_handler(nCode, wParam, lParam):
        point = ctypes.cast(lParam, ctypes.POINTER(ctypes.c_long * 2)).contents
        x = point[0]
        y = point[1]
        event = MouseEvent(wParam, x, y)

        for handler in handlers:
            handler(event)
        
        return ctypes.windll.user32.CallNextHookEx(hook_id, nCode, wParam, lParam)

    CMPFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.POINTER(ctypes.c_void_p))
    ctypes.windll.user32.SetWindowsHookExW.argtypes = (
        ctypes.c_int,
        CMPFUNC,
        ctypes.c_void_p,
        ctypes.c_uint
    )
    pointer = CMPFUNC(low_level_handler)

    hook_id = ctypes.windll.user32.SetWindowsHookExW(win32con.WH_MOUSE_LL, pointer,
                                                     win32api.GetModuleHandle(None), 0)

    atexit.register(ctypes.windll.user32.UnhookWindowsHookEx, hook_id)
    win32gui.GetMessage(None, 0, 0)
    

def get_screen_resolution():
    user32 = ctypes.windll.user32
    user32.SetProcessDPIAware()  
    screen_width = user32.GetSystemMetrics(0)
    screen_height = user32.GetSystemMetrics(1)
    return screen_width, screen_height


def get_triangles(screen_width, screen_height):
    top_left = (0, 0)
    top_right = (screen_width, 0)
    bottom_right = (screen_width, screen_height)
    bottom_left = (0, screen_height)
    
    center = (screen_width // 2, screen_height // 2)
    
    triangles = [
        ("Triangle 1", bottom_left, center, top_left),
        ("Triangle 2", top_left, center, top_right),
        ("Triangle 3", top_right, center, bottom_right),
        ("Triangle 4", bottom_right, center, bottom_left),
    ]
    
    return triangles


screen_width, screen_height = get_screen_resolution()
triangles = get_triangles(screen_width, screen_height)


def is_in_triangle(x, y, v1, v2, v3):
    x1, y1 = v1
    x2, y2 = v2
    x3, y3 = v3

    def is_same_side(x2, y2, x3, y3):
        return (x - x3) * (y2 - y3) - (x2 - x3) * (y - y3) < 0

    bool1 = is_same_side(x1, y1, x2, y2)
    bool2 = is_same_side(x2, y2, x3, y3)
    bool3 = is_same_side(x3, y3, x1, y1)
 
    return bool1 == bool2 == bool3


def find_triangle(x, y):
    for name, v1, v2, v3 in triangles:
        if is_in_triangle(x, y, v1, v2, v3):
            return name
    return "Outside"
 

if __name__ == '__main__':
    def print_event(event):
        print(f"Position: ({event.x}, {event.y})")
        print(find_triangle(event.x, event.y)) 

    handlers.append(print_event)
    listen()
  • listen() - ставим хук для получения (x,y)
  • print_event(event)- коллбэк в который возвращаем (x,y)
  • get_screen_resolution() - вернём размеры экрана.
  • get_triangles(screen_width, screen_height) - получим вершины всех 4 треугольников.
  • find_triangle(x, y)/is_in_triangle(x, y, v1, v2, v3) - тут уже будем вычислять, попали ли (x,y) в треугольник и если да, то в какой.

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

→ Ссылка
Автор решения: Ivan Polevikov

В общем посидел подумал над предложением с уравнениями и написал вот такой код.

import win32api
import pyautogui
import time

width, height = 2560, 1440
# k1 = width/height
# k2 = height/width
k = height/width

while True:
    if win32api.GetKeyState(0x01) < 0:
        x, y = pyautogui.position()
        if y < (width - x) * k:
            if x * k < y:
                print(1) # число - четверть согласно рисунку
            else:
                print(2)
        else:
            if x * k > y:
                print(3)
            else:
                print(4)
    time.sleep(0.1)

k1 и k2 это коэффициенты где x = y * k1 и y = x * k2. (Функции диагоналей)

→ Ссылка