Пересечение отрезков в 2D и 3D

Пересечение отрезков в последнее время стало основным моим занятием. Зафиксирую, почему именно так, а то потом забудется. Как найти пересечения прямых рассмотрено в статье Пересечение прямых, угол и координаты пересечения. Нас интересуют именно отрезки. Решение векторно-алгебраическое, поэтому будет интересно.

Теория

Итак, у нас есть отрезок AB, заданный точками A и B. И отрезок CD, заданный точками C и D соответственно. Необходимо найти точку их пересечения, либо сообщить, что отрезки не пересекаются.

Векторная часть

Представим отрезок AB, как вектор, направленный из A в B. И отрезок CD, тоже как вектор, из C в D. Сразу предположим хороший случай, когда они пересекаются в некоторой точке.

Введём понятие коэффициентов t и u, которые означают часть векторов AB (t) и CD (u) до точки пересечения.

Очевидно, что значения коэффициентов t и u лежат в диапазоне [0..1]. Таким образом, получаем вектора AS и CS, которые сходятся в точке пересечения S.

Введём новый вектор AC, из A в C.

Замечаем, что он является разностью AS и CS:

Таким образом, имеем систему уравнений:

Которую будем решать алгебраически, методом Крамера.

Алгебраическая часть

Имеем следующую систему:

Формулы latex

Latex formula

[свернуть]

Где:

Определители будут такими:

Формулы latex

Latex formula

Latex formula

Latex formula

[свернуть]

Убираем знак минуса в числителе и знаменателе, получаем решение:

Формулы latex

Latex formula

Latex formula

[свернуть]

Если определитель Δab = 0, значит отрезки параллельны друг другу.

Если параметр t=0, значит точка пересечения совпадает с A. При t=1, точка пересечения совпадает с B. Признаком «попадания» в отрезок AB является нахождение параметра t ∈ [0, 1]. Аналогично для параметра u.

Практическая часть

Напишем функцию, которая бы определяла факт пересечения отрезков, и, в случае пересечения, возвращала параметры t и u.

Пересечение отрезков в 2D

Получив факт пересечения, нам достаточно одного параметра t, чтобы вычислить точку пересечения. Если отрезки пересекаются, то использование u для отрезка CD даст нам ту же самую точку. Короче, функция:

Пересечение отрезков в 3D

Если отрезки пересекаются в плоскости XY, далеко не факт, что они пересекутся в координате Z.

Вот тут нам и понадобится параметр u. После того, как мы удостоверились, что отрезки пересекаются в плоскости XY, находим Z-отметки в точках пересечения и сравниваем их:

Приведённая выше функция рассматривает вариант с поиском пересечений только в XY. Но думать, что если нет пересечения в плоскости XY, то и в 3D нет — это неправильно (Данил, спасибо, что обратил внимание!).

Например, в случае, когда отрезки в плоскости XY параллельны, они вполне могут пересечься в плоскости XZ.

Чтобы однозначно найти точку пересечения отрезков в 3D, надо проверить все плоскости: XY, YZ и XZ. В функции ниже мы находим факт пересечения и определитель для каждой плоскости, затем выбираем максимальный по модулю определитель из допустимых. Просто при делении на большее число, получаем более точное значение (деление происходит при вычислении параметров t и u).

Добавим ещё функцию, которая просто возвращает факт пересечения отрезков в 3D, и, в случае успеха, вернёт 3D-точку пересечения:

Для копипаста

Для копипаста в спойлере модуль.

Модуль для нахождения пересечения отрезков

[свернуть]

Демо приложение

Кнопками 2D и 3D меняем вид отображения.

В 2D можем таскать концы отрезков. В 3D крутим сцену (крутилка так себе, но представление о расположении даёт).

Кнопки 0..4 — это для иллюстрации статьи. Показывает векторы.

Если поставить галку на Signal a problem при отсутствии пересечения будет появляться вредный кот. Если в 2D кота нет, это не значит, что в 3D он не появится: Z-отметки отрезков могут не совпадать. В этом случае они будут красными.

Кнопка Set Z for AB подвинет отрезок AB по Z на величину разности Z-отметок в точке пересечения в плоскости XY. Таким образом можно установить полное пересечение по всем трём координатам и изгнать кота.

Есть одна особенность — 2D вид это на самом деле 3D, но с осью Z, направленной строго вертикально. Отображение отрезков в 2D учитывает Z координату и отрисовывается с учётом перспективы. Поэтому, когда захотите расположить их параллельно, и точки пересечения найти не удалось, визуально может казаться, что отрезки на самом деле пересекаются. Имеет смысл перейти в 3D вид и посмотреть, как там дела.


Скачать

Друзья, спасибо за внимание!

Исходник (zip) 90 Кб. Delphi XE 7

Исполняемый файл (zip) 1.24 Мб (Скомпилирован в XE 7 x64)

Касперский снова истерит на 32


5 3 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии