Я пытаюсь определить, пересекает ли линейный сегмент (т.е. между двумя точками) сферу. Меня не интересует положение пересечения, просто пересекает ли сегмент поверхность сферы. Есть ли у кого-нибудь предложения относительно того, какой алгоритм для этого будет наиболее эффективным? (Мне интересно, есть ли какие-либо алгоритмы, которые проще, чем обычные алгоритмы пересечения лучевой сферы, поскольку меня не интересует положение пересечения)
Проверка того, пересекает ли линейный сегмент сферу
Ответы (4)
Я не знаю, что это за стандартный способ, но если вы хотите знать, пересекается ли оно, вот что я бы сделал.
Общее правило ... избегайте выполнения sqrt () или других дорогостоящих операций. По возможности работайте с квадратом радиуса.
- Определите, находится ли начальная точка внутри радиуса сферы. Если вы знаете, что это не так, пропустите этот шаг. Если вы внутри, ваш луч пересечет сферу.
С этого момента ваша отправная точка находится за пределами сферы.
- Теперь представьте себе маленькую коробку, которая уместится в сфере. Если вы находитесь за пределами этого поля, проверьте направление x, y и z луча, чтобы увидеть, будет ли он пересекать сторону прямоугольника, с которой начинается ваш луч. Это должна быть простая проверка знаков или сравнение с нулем. Если вы находитесь вне и удаляетесь от него, вы никогда не пересечете его.
С этого момента вы находитесь в более сложной фазе. Ваша отправная точка находится между воображаемым ящиком и сферой. Вы можете получить упрощенное выражение, используя исчисление и геометрию.
Суть того, что вы хотите сделать, это определить, меньше ли кратчайшее расстояние между вашим лучом и сферой, чем радиус сферы.
Пусть ваш луч представлен в виде (x0 + i t, y0 + j t, z0 + k t), а центр вашей сферы находится в точке (xS, yS, zS). Итак, мы хотим найти t такое, чтобы получить наименьшее из (xS - x0 - i t, yS - y0 - j t, zS - z0 - k t).
Пусть x = xS - x0, y = yX - y0, z = zS - z0, D = величина вектора в квадрате
D = x^2 -2*xit + (i*t)^2 + y^2 - 2*yjt + (j*t)^2 + z^2 - 2*zkt + (k*t)^2
D = (i^2 + j^2 + k^2)t^2 - (xi + yj + zk)*2*t + (x^2 + y^2 + z^2)
dD/dt = 0 = 2*t*(i^2 + j^2 + k^2) - 2*(xi + yj + z*k)
t = (xi + yj + z*k) / (i^2 + j^2 + k^2)
Подставьте t обратно в уравнение для D = .... Если результат меньше или равен квадрату радиуса сферы, у вас есть пересечение. Если больше, то пересечения нет.
Если вас интересует только знание того, пересекается ли он или нет, тогда ваш основной алгоритм будет выглядеть так ...
Предположим, у вас есть вектор лучевой линии, A -> B.
Вы знаете, что кратчайшее расстояние между этим вектором и центром сферы находится на пересечении вашего вектора луча и вектора, который находится под углом 90 градусов к этому вектору, который проходит через центр сферы.
Таким образом, у вас есть два вектора, уравнения которых полностью определены. Вы можете определить точку пересечения векторов с помощью линейной алгебры и, следовательно, длину линии (или, что более эффективно, квадрат длины линии) и проверить, меньше ли она радиуса (или квадрата радиуса ) вашей сферы.
На этой странице есть точное решение этой проблемы. По сути, вы подставляете уравнение для линии в уравнение для сферы, а затем вычисляете дискриминант полученной квадратичной кривой. Значения дискриминанта указывают на пересечение.
вы все равно должны работать с этой позицией, если хотите точности. Единственный способ алгоритмически улучшить скорость - это переключиться с пересечения лучевой сферы на пересечение лучевого ограничивающего прямоугольника.
Или вы можете пойти глубже и попытаться улучшить sqrt и другие внутренние вызовы функций.
http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection