1 Востаннє редагувалося mamkin haker (09.09.2021 13:13:46)

Тема: pygame | координати перетину двох ліній

Доброго дня.
Почув цікаву штучку (щось про визначені інтеграли)
Вирішив зробити щось подібне.
Ось: (прикріплені файли)

скрін того що вийшло

Синя полоска то місце куди я нажав мишкою
https://replace.org.ua/extensions/om_images/img/6139ead3ca4bb/51c5f3c61c7ce5ceb93dd544ce92125a.png

проблема: неможу знайти точку перетину двох ліній

спроби:

№1

Зайшов у вікіпедію, почитав про точки перетину і як їх знаходити за координатама, щось не вийшло

def get_cord(rect1_cord, rect2_cord) -> float:
    x1 = rect1_cord[0][0]
    y1 = rect1_cord[0][1]
    x2 = rect1_cord[1][0]
    y2 = rect1_cord[1][1]

    x3 = rect2_cord[0][0]
    y3 = rect2_cord[0][1]
    x4 = int(rect2_cord[1][0])
    y4 = int(rect2_cord[1][1])
    
    matrix = [
        [x2 - x1, x4 - x3, x3 - x1],
        [y2 - y1, y4 - y3, y3 - y1]
    ]

    delta_x = matrix[0][2] * matrix[1][1] - matrix[0][1] * matrix[1][2]
    delta_y = matrix[1][2] * matrix[0][0] + matrix[1][0] * matrix[0][2]
    delta   = matrix[1][1] * matrix[0][0] - matrix[1][0] * matrix[0][1]

    if delta_x > 0 and delta_y > 0 and delta > 0:
        return (delta_x / delta, delta_y / delta)
Спроба №2

Вирішив, чому б не знайти попіксельно де вони перетинаються за допомогою цикла for і функції яка каже чи перетинаються фігури

    def __get_cord(self):
        x = self.rect2_cord[0][0]

        for y in range(int(self.y_1 * 9)):
            if y < self.y_1:
                continue

            rect = pygame.draw.rect(self.screen, self.lucky_color, ((x * self.x_1, y), (1, 1)))

            if rect.colliderect(self.rect1):
                return (x - 1, 9 - (y // self.y_1))

теж невдача, воно чомусь зупиняєтся коли доходить до y = FUNCTION_END_POS[1]

також шукав в інтернеті метод який би вирішив цю проблему
результат негативний =(

можливо я для цеї задачки вибра не ту бібліотеку, а може навіть і не ту мову ?(

upd: забув код скинути :D :D :D
файлами можна кинути лише 1 файл, тому...

Прихований текст

DecardSystem.py

import pygame
import consts

class DecardSystem():

    def __init__(
        self, *,
        main_color         = consts.MAIN_COLOR,
        decard_y           = consts.DECARD_Y,
        decard_x           = consts.DECARD_X,
        size_font          = consts.SIZE_FONT
        ):

        self.main_color    = pygame.Color(main_color)
        self.decard_y      = decard_y
        self.decard_x      = decard_x
        self.size_font     = size_font

    def draw(self, screen, font) -> None:
        pygame.draw.rect(screen, self.main_color, self.decard_y)
        pygame.draw.rect(screen, self.main_color, self.decard_x)

        lens_y = self.decard_y[1] +  self.decard_y[0] - (self.size_font/4)
        lens_x = self.decard_x[0] - (self.size_font/4)

        for i in range(9):
            text = font.render(str(i), True, self.main_color)

            #for y
            lens_y -= self.decard_y[0]
            screen.blit(text, [self.decard_y[0] - (self.size_font/2), lens_y])

            if i == 0: continue #skip x == 0 but y == 0 too

            #for x
            lens_x += self.decard_x[0]
            screen.blit(text, [lens_x, (self.decard_x[0] * 9) + (self.size_font/4)])
Прихований текст

Function.py

import pygame
import consts

class Function():

    def __init__(
        self, *,
        x_1                     = consts.X_1,
        y_1                     = consts.Y_1,
        main_color              = consts.MAIN_COLOR,
        red_color               = consts.RED_COLOR,
        green_color             = consts.GREEN_COLOR,
        function_start_pos      = consts.FUNCTION_START_POS,
        function_end_pos        = consts.FUNCTION_END_POS,
        ):

        self.x_1                = x_1
        self.y_1                = y_1 * 9
        self.main_color         = pygame.Color(main_color)
        self.red_color          = pygame.Color(red_color)
        self.green_color        = pygame.Color(green_color)
        self.function_start_pos = function_start_pos
        self.function_end_pos   = function_end_pos

    #ЗЕЛЕНИЙ ПРЯМОКУТНИК
    def __bottom_defined_integral(self) -> pygame.Rect:
        if self.function_end_pos[1] > self.function_start_pos[1]:
            color = self.red_color
        else:
            color = self.green_color

        pygame.draw.rect(
            self.screen,
            color,
            (
                self.function_start_pos[0],
                self.function_end_pos[1],
                self.function_end_pos[0] - self.function_start_pos[0],
                self.y_1 - self.function_end_pos[1]
            ),
            5 #len green rect
        )

    #ЧЕРВОНИЙ ПРЯМОКУТНИК
    def __upper_defined_integral(self) -> pygame.Rect:
        if self.function_end_pos[1] < self.function_start_pos[1]:
            color = self.red_color
        else:
            color = self.green_color

        pygame.draw.rect(
            self.screen,
            color,
            (
                self.function_start_pos[0],
                self.function_start_pos[1],
                self.function_end_pos[0] - self.function_start_pos[0],
                self.y_1 - self.function_start_pos[1]
            ),
            3 #len red rect
        )


    def draw(self, screen) -> pygame.Rect:
        self.screen = screen

        rect1 = pygame.draw.aaline(
            self.screen,
            self.main_color,
            self.function_start_pos,
            self.function_end_pos
        )

        self.__bottom_defined_integral()
        self.__upper_defined_integral()

        return rect1
Прихований текст

Mouse.py

import pygame
import consts

class Mouse():

    def __init__(
        self, *,
        x_1                     = consts.X_1,
        y_1                     = consts.Y_1,
        blue_color              = consts.BLUE_COLOR
        ):

        self.x_1                = x_1
        self.y_1                = y_1
        self.blue_color         = pygame.Color(blue_color)
        self.size_line          = 7

        self.y_start = 0
        self.y_end   = 8

    #МАЛЮВАННЯ СИНЬОЇ ЛІНІЇ
    def draw_click(self, screen, mouse_pos) -> pygame.Rect:
        add0 = 0
        if (mouse_pos[0] % self.x_1) > (self.x_1 / 2):
            add0 = self.x_1 
        
        mouse = (mouse_pos[0] - (mouse_pos[0] % self.x_1) + add0, self.y_1)
        rect2 = pygame.draw.line(screen, self.blue_color, mouse, (mouse[0], self.y_1 * 9), self.size_line)

        return rect2, ((mouse[0] // self.x_1, self.y_start), (mouse[0] // self.x_1, self.y_end)) 
Прихований текст

consts.py

WIDTH              = 800
HEIGHT             = WIDTH
SIZE               = 1
SIZE_FONT          = 30
FPS                = 30 #Frame pres second

CORDS_FIRST        = (1, 1) #first dot
CORDS_LAST         = (5, 5) #last dot

#DONT CHANGE
X_1                = WIDTH / 10
Y_1                = HEIGHT / 10

LEN_LINE_Y         = X_1 * 8
LEN_LINE_X         = Y_1 * 8

#координата Х, координата У, ширина, довжина
DECARD_Y           = (X_1, Y_1*9, LEN_LINE_Y, SIZE)
DECARD_X           = (X_1, Y_1,   SIZE, LEN_LINE_X)

FUNCTION_START_POS = (X_1 + X_1 * CORDS_FIRST[0], HEIGHT - Y_1 - Y_1 * CORDS_FIRST[1])
FUNCTION_END_POS   = (X_1 + X_1 * CORDS_LAST[0], HEIGHT - Y_1 - Y_1 * CORDS_LAST[1])

BACKGROUND_COLOR = "#000000"
MAIN_COLOR       = "#FFFFFF"
RED_COLOR        = "#FF0000"
GREEN_COLOR      = "#00FF00"
BLUE_COLOR       = "#0000FF"
LUCKY_COLOR      = (80, 80, 80)
CAPTION          = "TEST"
Post's attachments

main.py 4.02 kb, 145 downloads since 2021-09-09 

2

Re: pygame | координати перетину двох ліній

уже непотрібно
я здався
втратив увесь інтузіазм
=(

але якщо знайдете рішення то киньте, хоч подивлюсь який я тупий, що незміг таку простеньку штучку зробити

3 Востаннє редагувалося mamkin haker (09.09.2021 13:57:28)

Re: pygame | координати перетину двох ліній

Забув ще цю додати
Спроба №3

Прихований текст

уже нестав в код робити томущо помилка в рішенні
k1 = 1, d1 = 0
k2 та d2 ділятся на 0 #помилка
https://replace.org.ua/uploads/images/11470/daa4b06531ed50aeef896339672261e4.jpg

4 Востаннє редагувалося koala (09.09.2021 14:55:19)

Re: pygame | координати перетину двох ліній

Знайдіть рівняння прямих у формі

ax+by+c=0

і розв'яжіть як систему лінійних рівнянь.
У вашому підході проблема - знаменник може бути нулем.

Власне, при цьому ви прийдете до того ж самого матричного представлення.

Подякували: 0xDADA11C7, FakiNyan2

5

Re: pygame | координати перетину двох ліній

mamkin haker написав:
  if delta_x > 0 and delta_y > 0 and delta > 0:
        return (delta_x / delta, delta_y / delta)

А для від'ємних де?

6 Востаннє редагувалося mamkin haker (09.09.2021 15:11:59)

Re: pygame | координати перетину двох ліній

koala написав:
mamkin haker написав:
  if delta_x > 0 and delta_y > 0 and delta > 0:
        return (delta_x / delta, delta_y / delta)

А для від'ємних де?

а відємних неможе бути :D
там в мейні є такі стріки (114)

if self.rect1.colliderect(self.rect2):

воно перевіряє чи належить хоч якась точка обєкта self.rect2 обєкту serl.rect1
так як self.rect2 100% пряма паралельна 0y то вона або пересікає self.rect1 або не перетинає
також з скріншота видно, що існує лише перша чверть декартової системи координат

7 Востаннє редагувалося mamkin haker (09.09.2021 15:16:33)

Re: pygame | координати перетину двох ліній

koala написав:

Знайдіть рівняння прямих у формі

ax+by+c=0

і розв'яжіть як систему лінійних рівнянь.
У вашому підході проблема - знаменник може бути нулем.

Власне, при цьому ви прийдете до того ж самого матричного представлення.

оце я тупий :D
дякую що просвітили мене, неука в якого iq як у буханця хліба
тепер залишилось написати алгоритм який перетворє координати у те рівння, розвязування системи методом крамера у мене вже є такщо піду посплю, а цим займусь завтра :D

8 Востаннє редагувалося koala (09.09.2021 15:19:59)

Re: pygame | координати перетину двох ліній

Так, тепер спочатку. У вас яка задача - знайти точку перетину двох прямих на площині, так? І для представлення цих прямих ви використовуєте об'єкт, що містить пару точок - але це не пряма, а прямокутник зі сторонами, паралельними осям координат; і його (прямокутника) методи не стосуються вашої задачі. Чи вам треба точку перетину двох відрізків, а не прямих? Чи точку перетину діагоналей двох прямокутників, якщо ці прямокутники перетинаються (але, можливо, діагоналі не перетинаються, лише їхні продовження)? Визначайтеся. У будь-якому разі знак виразу буде залежати не від наявності перетину, а від послідовності точок: прямі (x1,y1)-(x2,y2) і (x2,y2)-(x1,y1) тотожні, а от вирази для них будуть мати протилежні знаки.

9

Re: pygame | координати перетину двох ліній

mamkin haker написав:

дякую що просвітили мене, неука в якого iq як у буханця хліба

це не так, бо ви пишете код та здатні до розв'язання завдань, а у нас на форумі є ті, хто нічого з цього не вміє, а тільки лялякає і сує свої нікому непотрібні 5 коп. куди його не просять, тому не відбирайте у нього звання неука, в якого iq, як у буханця хліба

10

Re: pygame | координати перетину двох ліній

koala написав:

Так, тепер спочатку. У вас яка задача - знайти точку перетину двох прямих на площині, так? І для представлення цих прямих ви використовуєте об'єкт, що містить пару точок - але це не пряма, а прямокутник зі сторонами, паралельними осям координат; і його (прямокутника) методи не стосуються вашої задачі. Чи вам треба точку перетину двох відрізків, а не прямих? Чи точку перетину діагоналей двох прямокутників, якщо ці прямокутники перетинаються (але, можливо, діагоналі не перетинаються, лише їхні продовження)? Визначайтеся. У будь-якому разі знак виразу буде залежати не від наявності перетину, а від послідовності точок: прямі (x1,y1)-(x2,y2) і (x2,y2)-(x1,y1) тотожні, а от вирази для них будуть мати протилежні знаки.

точку перетину 2х відрізків
перші координати знаходятся у consts.py

CORDS_FIRST        = (1, 1) #first dot
CORDS_LAST         = (5, 5) #last dot

а ту синеньку лінію отримую коли користувач клацає на координатній площині Mouse.py (20 - 30)

    #МАЛЮВАННЯ СИНЬОЇ ЛІНІЇ
    def draw_click(self, screen, mouse_pos) -> pygame.Rect:
        add0 = 0
        if (mouse_pos[0] % self.x_1) > (self.x_1 / 2):
            add0 = self.x_1 
        
        mouse = (mouse_pos[0] - (mouse_pos[0] % self.x_1) + add0, self.y_1)
        rect2 = pygame.draw.line(screen, self.blue_color, mouse, (mouse[0], self.y_1 * 9), self.size_line)

        return rect2, ((mouse[0] // self.x_1, self.y_start), (mouse[0] // self.x_1, self.y_end)) 

11

Re: pygame | координати перетину двох ліній

перший спосіб це доречі з вікіпедії про точку перетину 2х відрізків у просторі
https://uk.wikipedia.org/wiki/%D0%9F%D0 … %96%D1%8F)
це я за тими формулами сформував матрицю, і потім за методом крамера знаходив координати
https://uk.wikipedia.org/wiki/%D0%9C%D0 … 2'%7F

12 Востаннє редагувалося mamkin haker (09.09.2021 15:37:47)

Re: pygame | координати перетину двох ліній

koala написав:

Визначайтеся.

є функція(в даному випадку пряма) визначена на проміжку від 1х по 5х
і є користувач який клікає мишкою по координатній площині створюючи прямі які паралельні 0у

мені потрібно знайти їх координати точки перетену якщо вони перетинаються

частини прямих(відрізки) відображаються за допомогою метода pygame.draw.line(екран, колір, координати почтку, координати кінця, товщина)

13

Re: pygame | координати перетину двох ліній

Синенька завжди вертикальна? Тоді просто підставляєте її координату x в перше рівняння і отримуєте y перетину.

14 Востаннє редагувалося mamkin haker (10.09.2021 07:19:53)

Re: pygame | координати перетину двох ліній

Відповідь:

def get_cord(rect2_cord) -> float:
    x = rect2_cord[0][0]

    x1 = consts.CORDS_FIRST[0]
    y1 = consts.CORDS_FIRST[1]
    x2 = consts.CORDS_LAST[0]
    y2 = consts.CORDS_LAST[1]

    if x1 > x2 or y1 > y2:
        x1, y1, x2, y2 = x2, y2, x1, y1

    y = (((x - x1) / (x2 - x1)) * (y2 - y1) ) + y1

    if x1 > x2 or y1 > y2:
        y += 2

    return (x * consts.X_1, 10 * consts.Y_1 - y * consts.Y_1)

Виводи:

while True:
    print("я тупий")

15

Re: pygame | координати перетину двох ліній

Ні, висновок - сьогодні ви вивчили щось нове. В принципі, те, що мали б вивчити в 7-8 класі, але краще так, ніж ніколи.

16

Re: pygame | координати перетину двох ліній

знаючи себе, я вже то забув :D
але я запямятав де знайти відповідь на подібну "задачку"