Рассчитать 2D точку пересечения двух бесконечных линий - PullRequest
0 голосов
/ 16 декабря 2018

Используя формулу y = mx + b, я написал приведенный ниже код для решения точки пересечения для двух бесконечных линий без использования каких-либо зависимостей, таких как numpy.Я специально ищу решение для решения без зависимостей.

К сожалению, оно последовательно возвращает неверный результат при поиске для Y-пересечения каждой строки, и, следовательно, все, что после этого будет неправильным в результате.После того, как мы потратили несколько дней, настало время поставить его здесь, чтобы кто-нибудь еще посмотрел на него.

Линии определяются точкой происхождения и радианой того, в каком направлении они наклонены. Обратите вниманиечто я намеренно удалил проверки для линий, параллельных оси Y (у таких линий нет наклона) и других краевых случаев для лучшей читаемости в этом примере.

Код написан с переменными длинной формы для дальнейшегоясность.Я посмотрел на многие вопросы, касающиеся подобных проблем и других веб-сайтов, и ответы почти всегда кодифицированы в математической записи, предположим, что вы знаете, что представляют собой переменные, или предполагается, что Оператор знает, как решать неизвестные переменные / уравнения баланса.Я очень мало знаю о таких вещах, мне пришлось заново учить себя алгебре, чтобы попытаться решить эту проблему.Моя цель здесь - обеспечить максимальную ясность, чтобы другие пользователи с этой проблемой могли понять, как взять формулу и решить ее как код Python.

import math

origin_a = [0.9292893218813453, 0.07071]
origin_b = [3.121320343559643, 2.121320343559643]

radian_a = math.pi/4
radian_b = 2.748893571891069

X = 0
Y = 1
Z = 2


"""Returns Vector2 around a circle"""
def get_position_from_radian(radian, radius):
    rotated_pos = [0.0, 0.0, 0.0]
    rotated_pos[X] = math.cos(math.pi-radian) * radius
    rotated_pos[Y] = math.sin(math.pi-radian) * radius
    return(rotated_pos)


"""Returns Vector2"""
def get_slope_from_radian(radian):
    slope = (get_position_from_radian(radian, 1)) #Get a position along line to calculate slope from
    #We want slope to be scalar for simplicity, so we will divide Y by X and assume X=1
    slope = slope[Y] / slope[X]
    return(slope)


"""Returns Vector2 where two 2D rays intersect using y=mx+b (slope intercept)"""
def get_position_from_line_intersect_2d(origin_a, radian_a, origin_b, radian_b):
    #Slope is the 'm' in y=mx+b
    slope_a = get_slope_from_radian(radian_a)
    slope_b = get_slope_from_radian(radian_b)

    #Trig to find the slope of our lines. We assume length x=1 
    angle_a = math.pi - math.pi/2 - radian_a
    angle_b = math.pi - math.pi/2 - radian_b
    #We must determine if angle is + or - X
    if radian_a > math.pi:
        slope_a *= -1 
    if radian_b > math.pi:  
        slope_b *= -1
    print("SLOPE", slope_a, slope_b)

    #These represent the Y intercept
    intercept_y_a = origin_a[Y] + -(slope_a * origin_a[X])
    intercept_y_b = origin_b[Y] + -(slope_b * origin_b[X])
    print("Y INTERCEPT", intercept_y_a, intercept_y_b)

    #These represent the X intercept
    intercept_x_a = slope_a * intercept_y_a
    intercept_x_b = slope_b * intercept_y_b
    print("X INTERCEPT", intercept_x_a, intercept_x_b)

    #This is the position at which our two lines intersect
    intercept = [0.0, 0.0]
    intercept[X] = ((intercept_y_a*-1) + intercept_y_b) / (slope_a (slope_b*-1))
    intercept[Y] = ((intercept_x_a*-1) + intercept_x_b) / (slope_a (slope_b*-1))

    return(intercept)

print(get_position_from_line_intersect_2d(origin_a, radian_a, origin_b, radian_b))

Ответы [ 2 ]

0 голосов
/ 16 декабря 2018

Чтобы узнать, как реализовать , ответ типа '1002 *', пожалуйста, посмотрите на мой первый ответ.Здесь я попытаюсь объяснить, почему ваша реализация не работает с математической точки зрения

Сначала убедитесь, что
math.pi-radian на самом деле является вашим предполагаемым поведением в (этоэквивалентно определению всего вашего угла как отрицательного)

def get_position_from_radian(radian, radius):
    rotated_pos = [0.0, 0.0, 0.0]
    rotated_pos[X] = math.cos(math.pi-radian) * radius
    rotated_pos[Y] = math.sin(math.pi-radian) * radius
    return(rotated_pos)

Также вы действительно должны удалить это.

if radian_a > math.pi:
    slope_a *= -1 
if radian_b > math.pi:  
    slope_b *= -1

Правильный способ получить наклон - m = tan(angle) = sin(angle)/cos(angle).
Для простоты давайте поставим b=0, теперь давайте представим, что у вас есть один угол как pi / 4.Вы получите m = sqrt(2)/2 > 0, что хорошо, поскольку 0 < angle < pi or pi < angle < 3/2 * pi определит линию в 1-м и 3-м разделе вашего графика.
Теперь давайте возьмем угол pi + pi/4.Это даст вам ту же самую линию, что и раньше, а касательная все равно даст вам m = sqrt(2)/2 > 0, так как и cos и sin отрицательны в 3-м разделе.Если вы поменяете знак, потому что angle>pi вы на самом деле получите неправильный результат.

Теперь вы решаете эту систему уравнений:

y = m1 * x + b1
y = m2 * x + b2

, что приводит к x_itercept = (b2-b1) / (m1-m2).
До сих пор ваша формула кажется правильной (кроме отсутствующих + в реализации) intercept[X] = ((intercept_y_a*-1) + intercept_y_b) / (slope_a (slope_b*-1)).

Проблема начинается, когда вы пытаетесь переключить ось и использовать точно такую ​​же формулу для пересечения у.
Для этого давайте инвертируем уравнение строки y(x) --> x(y) (что мы можем сделать, поскольку это монотонная функция с одним отличным значением y для каждого x.

x = (y - b1) / m1
x = (y - b2) / m2

Давайте изменим некоторые имена, чтобы привести это в наиболее распространенную форму x = slope * y + b

m' = 1/m
b' = -b/m
x = m1' * y + b1'
x = m2' * y + b2'

Теперь мы можем решить эту систему точно так же, как первую, и получим

y_intercept = (b2' - b1') / (m1' - m2')

Структура формулы такая же, как и у используемой вами, но, как вы можете видеть, переменные в ней разные !!!!!!!
Вы получаете правильные значения b1 'и b2'как вы рассчитываете пересечение линии с осью х, ноВы по-прежнему используете m1 и m2 в качестве наклона вместо 1 / m1 и 1 / m2

0 голосов
/ 16 декабря 2018

Вот как я бы это реализовал, начиная с вашего кода

import math

origin_a = [0.9292893218813453, 0.07071]
origin_b = [3.121320343559643, 2.121320343559643]

radian_a = math.pi/4
radian_b = 2.748893571891069

X = 0
Y = 1
Z = 2

"""Returns Vector2 where two 2D rays intersect using y=mx+b (slope intercept)"""
def get_position_from_line_intersect_2d(origin_a, radian_a, origin_b, radian_b):
    #Slope is the 'm' in y=mx+b
    m1 = math.tan( radian_a) # get_slope_from_radian(radian_a)
    m2 = math.tan( radian_b) # get_slope_from_radian(radian_b)

    print("SLOPE", m1, m2)

    #These represent the Y intercept
    b1 = origin_a[Y] - (m1 * origin_a[X])
    b2 = origin_b[Y] - (m2 * origin_b[X])
    print("Y INTERCEPT", b1, b2)

    #This is the position at which our two lines intersect
    iX = (b2 - b1) / ( m1 - m2)
    iY = m1 * iX + b1

    return( iX, iY)

a,b = get_position_from_line_intersect_2d(origin_a, radian_a, origin_b, radian_b)

Есть пара вещей, которые не совсем понятны в вашей реализации:

  • Почему вы используете math.pi-radian вместо просто radian.Если это ваше предполагаемое поведение, то вы можете просто взять -m1 и -m2 относительно того, как я определил их из tan(pi - a) = -tan(a)
  • Нет необходимости проверять углы больше, чем pi.Наклон всегда будет определяться как тангенс угла
  • Нет необходимости вычислять точку пересечения с x = 0, который вы просто решаете для y1= b1*x + m1, y2= b2*x + m2, затем y1=y2 --> x_intercept=(b2-b1)/(m1-m2) и, наконец, y_intercept = m1 *x_i +b1 = m2 *x_i + b2

enter image description here

Корпус с определением pi - rad:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...