Нахождение точки на линии
Чтобы получить пересечение 2 плоскостей, вам нужна точка на линии и направление этой линии.
Нахождение направления этой линиидействительно просто, просто пересечь 2 нормали двух плоскостей, которые пересекаются.
lineDir = n1 × n2
Но эта линия проходит через начало координат, а линия, проходящая вдоль пересечений ваших плоскостей, может и не пройти.Таким образом, ответ Мартиньо обеспечивает отличное начало для нахождения точки на линии пересечения (в основном любая точка, находящаяся на обеих плоскостях).
В случае, если вы хотеличтобы увидеть вывод, как решить эту проблему, вот математика:
Сначала позвольте x = 0.Теперь у нас есть 2 неизвестных в 2 уравнениях вместо 3 неизвестных в 2 уравнениях (мы произвольно выбрали одно из неизвестных).
Тогда плоские уравнения (члены были исключены, так как мы выбрали x = 0):
B 1 y + C 1 z + D 1 = 0
B 2 y + C 2 z + D 2 = 0
Мы хотим, чтобы y и z были такими, чтобы оба уравнения были решены правильно (= 0)для заданного значения B 1 , C 1 .
Итак, просто умножьте верхнее выражение на (-B 2 / B 1 ) чтобы получить
-B 2 y + (-B 2 / B 1 ) * C 1 z + (-B 2 / B 1 ) * D 1 = 0
B 2 y + C 2 z + D 2 = 0
Добавьте уравнения, чтобы получить
z =((-B 2 / B 1 ) * D 1 - D 2 ) / (C 2 * B 2 / B 1 ) * C 1 )
Бросокz теперь вы найдете в 1-м уравнении, чтобы найти y как
y = (-D 1 - C 1 z) / B 1
Обратите внимание, что переменная best , равная 0, - это переменная с низшими коэффициентами, поскольку она все равно не несет никакой информации.Поэтому, если C 1 и C 2 оба равны 0, лучше выбрать z = 0 (вместо x = 0).
Приведенное выше решение можетвсе еще облажаться, если B 1 = 0 (что не исключено).Вы можете добавить в некоторые операторы if, которые проверяют, если B 1 = 0, и если это так, убедитесь, что вместо этого решите для одной из других переменных.
Решение с использованием пересечения 3 плоскостей
Из пользовательского ответа решение для закрытой формы для пересечения 3-х плоскостей было фактически в Graphics Gems 1. Формула:
P_intersection = ((point_on1 • n1) (n2 × n3) + (point_on2 • n2) (n3 × n1) + (point_on3 • n3) (n1 × n2)) / det (n1, n2, n3)
Фактически point_on1 • n1 = -d1 (при условии, что вы пишете свои плоскости Ax + By + Cz + D = 0, а не = -D).Таким образом, вы можете переписать его как:
P_intersection = ((-d1) (n2 × n3) + (-d2) (n3 × n1) + (-d3) (n1 × n2))/ det (n1, n2, n3)
Функция, которая пересекает 3 плоскости:
// Intersection of 3 planes, Graphics Gems 1 pg 305
static Vector3f getIntersection( const Plane& plane1, const Plane& plane2, const Plane& plane3 )
{
float det = Matrix3f::det( plane1.normal, plane2.normal, plane3.normal ) ;
// If the determinant is 0, that means parallel planes, no intn.
if( det == 0.f ) return 0 ; //could return inf or whatever
return ( plane2.normal.cross( plane3.normal )*-plane1.d +
plane3.normal.cross( plane1.normal )*-plane2.d +
plane1.normal.cross( plane2.normal )*-plane3.d ) / det ;
}
Доказательство того, что это работает (желтая точка - это пересечение плоскостей rgb здесь)
Получение линии
Если у вас есть точка пересечения, общая для двух плоскостей, линия просто идет
P + t* d
Где P - точка пересечения, t может идти от (-inf, inf), а d - вектор направления, который является перекрестным произведением нормалей двух исходных плоскостей.
Линия пересечения между красной и синей плоскостями выглядит следующим образом
Эффективность и стабильность
«Надежный» (2-й способ) по моим подсчетам берет 48 элементарных операций против 36 элементарных операций, которые использует 1-й способ (изоляция x, y).Есть компромисс между стабильностью и # вычислениями между этими двумя способами.
Это было быдовольно катастрофично получить (0, inf, inf) обратно от вызова к 1-му способу в случае, если B 1 было 0, а вы не проверяли. Таким образом, добавление операторов if
и отсутствие деления на 0 для 1-го способа может дать вам стабильность за счет раздувания кода и дополнительного ветвления (что может быть довольно дорогим). Метод пересечения с 3 плоскостями почти не имеет ответвлений и не даст вам бесконечности.