Как определить, пересекаются ли 2 луча?

Dec 03 2020

Нам даны двухмерные координаты двух точек: первая точка - это точка начала луча, и он проходит через вторую точку. Таким же образом нам дается другой луч. Как определить, есть ли у них точка пересечения? Я хотел бы знать общий алгоритм и его объяснение, не обращайте внимания на крайние случаи (например, когда лучи имеют одну и ту же начальную точку). PS Я видел аналогичный вопрос на другом обмене стеками, но ответы не были подтверждены объяснением.

Ответы

2 BiswajitBanerjee Dec 03 2020 at 12:36

Не уверен, что это ответ на ваш вопрос, но вот кое-что, что я написал несколько лет назад для статьи.

Позволять $\mathbf{p}_0$ а также $\mathbf{p}_1$ - конечные точки первого отрезка, и пусть $\mathbf{q}_0$ а также $\mathbf{q}_1$быть конечными точками второго отрезка. Тогда параметрические уравнения двух линий имеют вид$$ \mathbf{p}(t_p) = (1 - t_p) \mathbf{p}_0 + t_p \mathbf{p}_1 \quad \text{and}\quad \mathbf{q}(t_q) = (1 - t_q) \mathbf{q}_0 + t_q \mathbf{q}_1 \,. $$ В точке пересечения $\mathbf{p} = \mathbf{q}$, т.е. $$ (1 - t_p) \mathbf{p}_0 + t_p \mathbf{p}_1 = (1 - t_q) \mathbf{q}_0 + t_q \mathbf{q}_1 \,. $$ Перестановка уравнения дает $$ \mathbf{q}_0 - \mathbf{p}_0 = \begin{bmatrix}\mathbf{p}_1 - \mathbf{p}_0 & -(\mathbf{q}_1 - \mathbf{q}_0)\end{bmatrix} \begin{bmatrix} t_p \\ t_q \end{bmatrix} \,. $$ Следовательно, $$ \begin{bmatrix} t_p \\ t_q \end{bmatrix} = \begin{bmatrix}\mathbf{p}_1 - \mathbf{p}_0 & -(\mathbf{q}_1 - \mathbf{q}_0)\end{bmatrix}^{-1} (\mathbf{q}_0 - \mathbf{p}_0) $$ Как только мы решили $t_p$ а также $t_q$мы легко можем найти точку пересечения. Если точка пересечения находится за пределами$\mathbf{p}$ линия тогда $t_p \notin [0, 1]$. Аналогично, для другого сегмента, если точка пересечения находится за пределами сегмента, тогда$t_q \notin [0, 1]$.

PhilipRoe Dec 04 2020 at 05:37

Поскольку любые две непараллельные линии должны где-то пересекаться (согласно Евклиду), я полагаю, что ОП намеревался немного другой вопрос. Например, пересекаются ли лучи в выпуклой оболочке четырех заданных (на самом деле подразумеваемых) точек? (выпуклая оболочка - это область, окруженная эластичной лентой, натянутой вокруг всех четырех точек без пересечения.) Эту проблему решил Бисваджит Банерджи. Вам действительно нужно знать, где находится перекресток.

causative Dec 03 2020 at 13:57

Если вам нужно только знать, пересекаются ли лучи, вам не нужно искать точку пересечения. Следующее может быть более стабильным и эффективным, чем решение уравнений для точки пересечения, поскольку оно включает только вычитание и скалярные произведения, а не деление.

Ваш первый луч начинается с $p_0$ и иду в сторону $p_1$ (и бесконечно дальше $p_1$), а ваш второй луч, начиная с $q_0$ и иду в сторону $q_1$ (и бесконечно дальше $q_1$). Подумайте об этом визуально. Для фиксированного$p_0$, $p_1$, а также $q_0$, которые значения $q_1$привести к перекрестку? Ответ в том, что$q_1$должен лежать в клиновидной области плоскости. Одна сторона клина - это линия между$q_0$ а также $p_0$, а другая сторона клина параллельна первому лучу. На диаграмме$q_1$ должны находиться в синей области, чтобы лучи пересекались.

Мы можем выразить одну сторону клина, сказав, что $q_1$ должен быть на той же стороне $q_0$ к $p_0$ линия как $p_1$является. Если$p_0 - q_0 = (l_x, l_y)$, тогда мы можем повернуть $(l_x, l_y)$ 90 градусов, чтобы получить вектор, перпендикулярный линии: $(-l_y, l_x)$. Затем, чтобы проверить, что$q_1$ а также $p_1$ находятся на одной стороне, проверяем, что $(q_1 - q_0) \cdot (-l_y, l_x)$ имеет тот же знак, что и $(p_1 - q_0) \cdot (-l_y, l_x)$.

Мы можем выразить другую сторону клина, посмотрев на линию, проходящую через $q_0$ а также $q_0 + (p_1 - p_0)$. $q_1$ а также $p_1$должен быть по ту же сторону от этой линии. Вектор, параллельный прямой, равен$p_1 - p_0 = (m_x, m_y)$ который мы поворачиваем на 90 градусов, чтобы получить $(-m_y, m_x)$. Чтобы проверить это$q_1$ а также $p_1$ находятся по одну сторону от этой линии, мы проверяем, что $(p_1 - q_0) \cdot (-m_y, m_x)$ имеет тот же знак, что и $(q_1 - q_0) \cdot (-m_y, m_x)$.

Итак, подведем итог: два луча пересекаются тогда и только тогда, когда $(q_1 - q_0) \cdot (-l_y, l_x)$ имеет тот же знак, что и $(p_1 - q_0) \cdot (-l_y, l_x)$, а также $(p_1 - q_0) \cdot (-m_y, m_x)$ имеет тот же знак, что и $(q_1 - q_0) \cdot (-m_y, m_x)$.