Это должен быть полный ответ на ваш вопрос. Я не дал реализацию, поэтому может потребоваться продумать, чтобы избежать ненужных делений и т. Д. Пожалуйста, уточните, если что-то неясно. Я строю Джона на идеях CashCommons.
Пусть c - центр сферы с радиусом r. Что нам действительно нужно знать, так это то, что любая точка треугольника T (НЕ только три вершины) ближе к c, чем к единицам r?
Есть три случая для рассмотрения:
- Точка в T, ближайшая к c, является вершиной T. Это просто!
- Точка в T, ближайшая к c, находится внутри T.
- Точка в T, ближайшая к c, находится на одном из ребер T.
Определим некоторые переменные:
- c: центр сферы
- r: радиус сферы
- T: наш треугольник
- v1, v2, v3: вершины T
- t: точка в T, ближайшая к c
- P: уникальная плоскость, содержащая v1, v2, v3
- p: точка в P, ближайшая к c
ШАГ 1: Проверьте все вершины треугольника, на случай, если мы находимся в случае 1.
ШАГ 2: найдите p, точку в P, ближайшую к c. Это можно сделать, проецируя c на P.
ШАГ 3: Если мы находимся в случае 2, мы в основном сделали. Поэтому проверьте, находится ли p в T. (Проверить, находится ли точка в данном треугольнике, относительно легко, но я не знаю ЛУЧШЕГО способа сделать это, поэтому я опущу это.) Если это так, проверьте, dist (p, c)> r, и это дает вам ваш ответ.
Это оставляет только случай 3.
Итак, предположим, что у нас есть p, и что p отсутствует в T. Теперь мы на самом деле знаем что-то конкретное о p из геометрии: линия c -> p перпендикулярна P. (Если бы не было, мы могли бы точка р ', которая ближе к с, чем р.) Из-за этой перпендикулярности мы можем использовать теорему Пифагора:
Dist(c, z)^2 = Dist(c, z)^2 + D(p, z)^2
для любого z в P. В частности, это верно для z = t.
Так что теперь нам просто нужно найти t и проверить:
D(p,t)^2 <= r^2 - D(c,p)^2
Это очень похожая проблема, теперь в двух измерениях. Нужно найти t в T, которое ближе всего к p и, следовательно, к c. Мы уже проверили, что t не находится внутри T или одной из вершин T. Следовательно, оно должно быть на одном из ребер. Итак, мы можем просто попытаться найти его на каждом краю. Если t не в вершине, то линия t -> p будет перпендикулярна стороне, так что это довольно просто сделать.
ШАГ 4: Для каждой стороны v1 -> v2 треугольника выполните следующее:
4,1. Сегмент линии от v1 до v2 задается как
(x,y,z) = (v1x, v1y, v1z) + s * (v2x - v1x, v2y - v1y, v2z - v1z), 0 <= s <= 1
4.2 Нам нужна линия, лежащая в плоскости P, перпендикулярная v1 -> v2 и содержащая p. Эта строка будет иметь вид
(px, py, pz) + s * (qx, qy, qz)
, поэтому нам просто нужно выбрать вектор q, параллельный плоскости P и перпендикулярный v1 -> v2. Принимая
q = (p-->c) x (v1-->v2)
(т. Е. Перекрестное произведение) должно это сделать, поскольку это будет перпендикулярно нормали P, и, следовательно, параллельно P и перпендикулярно v1 -> v2.
4.3. Решить систему уравнений
(tx,ty,tz) = (v1x, v1y, v1z) + s1 * (v2x - v1x, v2y - v1y, v2z - v1z)
(tx,ty,tz) = (px, py, pz) + s2 * (qx, qy, qz)
чтобы найти t, которое лежит на обеих строках. Это действительно означает решение
v1x + s1 * (v2x - v1x) = px + s2 * qx
v1y + s1 * (v2y - v1y) = py + s2 * qy
v1z + s1 * (v2z - v1z) = pz + s2 * qz
для s1 и s2.
4,4. Если s1 находится между 0 и 1, то мы нашли точку t, которая находится между v1 и v2, и это следует проверить.
* * 4,5 тысячу семьдесят пять. Если s1 не находится между 0 и 1, то один из v1 или v2 был ближайшим к p, поэтому мы уже проверили его.