Здравствуйте, Dima_Ru, Вы писали:
D_R>Привет!
D_R>Возник вопрос как определить (быстро) лежит ли определенная точка (пространства) в
D_R>произвольной треугольной пирамиде.
Идеологически "правильный" подход заключается в том, что мы условие внутри-снаружи выражаем в терминах некоторых базовых предикатов.
В данном случае всё можно выразить через предикат orient3d.
orient3d(a,b,c,d) > 0, если вектора ab,ac,ad ориентированы правильно.
orient3d(a,b,c,d) < 0, если вектора ab,ac,ad ориентированы неправильно.
orient3d(a,b,c,d) = 0, если a,b,c,d лежат в одной плоскости
Тогда тест "внутри" может быть выражен так:
orient3d(v0,v1,v2,v3) и orient3d(v0,v1,v2,x) имеют разные знаки => снаружи
orient3d(v1,v2,v3,v0) и orient3d(v1,v2,v3,x) имеют разные знаки => снаружи
orient3d(v2,v3,v0,v1) и orient3d(v2,v3,v0,x) имеют разные знаки => снаружи
orient3d(v3,v0,v1,v2) и orient3d(v3,v0,v1,x) имеют разные знаки => снаружи
Иначе внутри
В зависимости от того, как классифицировать точки на границе, стоит внести коррективы в этот алгоритм.
Заметим, что знак orient3d(v0,v1,v2,v3)=знак orient3d(v1,v2,v3,v0)=знак orient3d(v2,v3,v0,v1)=знак orient3d(v3,v0,v1,v2)
Проблемы:
выраженный наивным образом, предикат orient3d(v0,v1,v2,v3)=смешанное произведение(v1-v0,v2-v0,v3-v0).
В 99% это работает более или менее нормально, и подходит для решаемой задачи.
Однако нужно быть готовым к тому, что временами этот тест будет давать неправильный результат (точка реально над плоскостью, а тест даёт под...)
Это связано с ошибками вычислений с плавающей точкой. Если необходимо, чтобы тест работал правильно, придётся копать в сторону адаптивных предикатов, точных вычислений,...
См. например отсюда
The CGAL Philosophy.