Определение, пересекает ли сфера объект или нет
У меня есть замкнутый объект, описанный поверхностным представлением треугольников (описанным тремя вершинами, которые образуют правое правило с нормалью, указывающей на "снаружи" объекта). Я помещаю сферу некоторого радиуса в 3D-пространство где-то близко к поверхности объекта. Я хочу определить, пересекает ли сфера объект или нет.
Я придумал 3 способа определить это, но у каждого из них есть свои недостатки, и ни один из них не идеален.
1) I можно определить" сторону", на которой будет размещена сфера, оттуда я могу вычислить сетку расстояний от плоскости отсчета до расстояния, на котором объект впервые встречается. Я могу сделать то же самое для противоположной "стороны" сферы, а затем просто проверить, всегда ли расстояние до объекта больше, чем расстояние до поверхности сферы. Если расстояние до объекта всегда больше, сфера не пересекает объект ни в одной из точек сетки.
преимущество в том, что это довольно быстро, но так как я вычисляю только сдержанные точки, его не абсолютный. Если разрешение моей сетки слишком конечно, есть шанс, что сфера пересечется в точке, которая находится между моими узлами сетки.
2) я могу взять все вершины всех треугольников и проверить их по уравнению сферы, которую я разместил. Если вершина обнаружена внутри сферы, сфера будет абсолютно частично находиться внутри объекта.
преимущество этого в том, что он довольно быстрый, но также очень склонен к сбою. Сфера может пересекать объект внутри треугольника и пропускать все вершины вместе.
3) я могу рассчитать кластер точек на поверхности сферы. Затем я могу проверить, находится ли каждая точка внутри объекта или нет (используя 3D-версию точки внутри полигонального алгоритма). Если какая-то одна точка находится внутри объекта, то часть сферы находится внутри объекта.
в преимущество этого в том, что он может быть очень точным, в зависимости от того, сколько точек я использую на поверхности моей сферы (более высокая плотность точек = больше точности). Однако точка внутри объектного алгоритма довольно дорогая, особенно когда количество треугольников увеличивается. Этот метод был бы лучшим (даже сказал бы мне, где и сколько сферы пересекает объект), но он был бы очень медленным.
есть ли какой-либо алгоритм или метод, который вы, ребята, можете знать, чтобы решить такую проблема? Моя главная цель-точность, мне нужно знать, коснется ли сфера объекта или нет. Также было бы неплохо знать, где сфера соприкасается или, по крайней мере, общая область. Наконец, скорость - это всегда хорошая вещь.
спасибо
-Faken
7 ответов
это должен быть полный ответ на ваш вопрос. Я не дал реализацию, поэтому может потребоваться подумать, чтобы избежать ненужных разделений и т. д. Пожалуйста, попросите разъяснений, что-то неясно. Я строю на идеях Джона из 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. (Если бы это было не так, мы могли бы найти точку p', которая ближе к c, чем 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
это очень похожая проблема, теперь в 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, поэтому мы уже проверили его.
хорошо, я попробую еще раз. ;)
Если вам нужна точность, и если вы точно знаете вершин, тогда вы можете использовать кратчайшее расстояние до плоскости чтобы увидеть, касается ли сфера любой из плоскостей, определенных любым набором из трех вершин, которые дают вам ваши треугольники. Для тех, кто это делает, вы видите, действительно ли точка ближайшего подхода лежит внутри треугольника.
Я думаю, что вы можете сделать это с помощью CGAL. Сначала вычислите сумму Минковского сферы и объекта, затем вы можете просто проверить, находится ли центр сферы (как опорная точка) внутри или снаружи объекта. Это можно сделать в произвольной арифметике точности, поэтому вы можете быть точны, если вам нужно.
пересечение сферы и плоскости-это набор.
следовательно, принимая идею Джона "ближе всего к плоскости", если сфера и треугольник пересекаются, и если оба они закрыты, то либо:
- ближайшая точка на плоскости лежит внутри треугольника
- сфера пересекает по крайней мере один из краев треугольника (потому что по связности существует непрерывный путь в пределах пересечения плоскости / сферы от некоторых точка внутри треугольника, к какой-то точке вне треугольника. Этот путь должен пересечь границу, и точка, в которой он это делает, находится в сфере).
пересечение шара и линии-это набор.
таким образом, расширьте край до линии так же, как мы расширили треугольник до плоскости. Если сфера пересекает край, то либо:
- ближайшая точка на линии лежит внутри края
- сфера пересекает по крайней мере одну из вершин треугольника.
Итак, если какая-либо из 4 ближайших точек (1 плоскость, три линии) лежит в сфере и треугольнике, то, конечно, они пересекаются. В противном случае: если все четыре находятся вне сферы, то два не пересекаются, и если любой из них находится внутри сферы, то они пересекаются, если любая из вершин треугольника лежит в сфере.
к сожалению, делать это для каждого треугольника только говорит вам, является ли сфера и поверхность твердого тела пересекается. Он не рассматривает случай, когда сфера полностью находится внутри твердого тела. Поэтому, наконец (или, возможно, сначала), вы также должны проверить, находится ли центр сферы внутри твердого тела.
Это может быть неэффективно, конечно - я не эксперт в геометрии программирования. И, как указывает Эндрю Макгрегор, вычисления с плавающей запятой не обязательно дают последовательные результаты.
будет ли объединение (2), а также тестирование центра треугольной грани в качестве другой вершины работать для вас?
сделать гибрид. Найдите замкнутый треугольник / точку с методом 2 и проверьте все комбинации пересечений со всеми треугольниками рядом с треугольником.