2017-01-19 24 views
0

Я ищу алгоритм, который может создавать точки в конусе с плоским дном (диском).Равномерная выборка (по объему) внутри конуса

У меня есть нормализованная ось, вдоль которой создается конус (для наших целей давайте просто скажем, что это ось у так (0, 1, 0) и угол конуса (скажем, это 45 градусов)

Единственные ресурсы, которые я смог найти в Интернете, генерируют векторы внутри конуса, но они основаны на выборке сферы, поэтому внизу вы получаете своего рода эффект «снежного конуса» вместо диска внизу .

Это делается с помощью следующего псевдокода:

// Sample phi uniformly on [0, 2PI] 
float phi = rand(0, 1) * 2 * PI 

// Sample u uniformly from [cos(angle), 1] 
float u = rand(0, 1) * (1 - cos(angle * PI/180)) + cos(angle * PI/180) 

vec3 = vec3(sqrt(1 - u^2) * cos(phi), u, sqrt(1 - u^2) * sin(phi))) 

Ниже показано, что я собираюсь сделать. Имея возможность создавать образцы либо на поверхности или внутри будет хорошо, как хорошо:

enter image description here

+0

Вы рассматривали Монте Carloing это? –

+0

Не могли бы вы уточнить? – Kinru

+0

Создайте случайную точку. Отбросьте его, если он не в конусе. –

ответ

4

Я мог бы объяснить свое решение в деталях с помощью интегралов и распределения вероятностей, но отсутствие MathJax на этом сайте, делает это сложно. Я буду объяснять на простом уровне, но это должно быть ясно. Я также сделаю решение немного более общим, чем вы спрашиваете: нам нужна случайная точка внутри правого кругового конуса высотой a и радиус основания b, и мы хотим, чтобы точка была однородной выборкой по объему этого конуса. Этот метод напрямую выбирает случайную точку в конусе без какого-либо отклонения.

Сначала рассмотрим небольшой конус высоты h внутри этого большего конуса, оба конуса с одинаковой вершиной и параллельными основаниями. Два конуса, конечно, аналогичные фигуры, а закон квадратного куба говорит, что объем меньшего конуса изменяется как куб его высоты. Эта высота колеблется от 0 до a, и мы хотим, чтобы ее куб был однородным в этом диапазоне. Поэтому мы выбираем h изменяться с корнем куба равномерной случайной величины, и мы получаем (в Python 3 кода),

h = a * (random()) ** (1/3) 

Далее мы рассмотрим круговую область, которая является основой этого меньшего конуса высота h. Радиус этого основания равен (b/a) * h, аналогичными треугольниками. Теперь подумайте о меньшей круговой области радиуса r внутри этой большей круговой области, обеих окружностей в одной и той же плоскости и с тем же центром. Площадь меньшего круга меняется с квадратом его радиуса, поэтому для получения однородной области над ее диапазоном мы принимаем квадратный корень равномерной случайной величины. Мы получаем

r = (b/a) * h * sqrt(random()) 

Теперь мы хотим, чтобы угол t (для тета) точки на окружности, что меньший круг радиуса r. Угол в радианах, очевидно, не зависит от других факторов, поэтому мы просто используем равномерную случайную переменную, чтобы получить

t = 2 * pi * random() 

Теперь мы используем эти три случайные величины h, r и t выбрать нашу точку внутри старта конус.Если вершина конуса находится в начале координат, а ось конуса лежит вдоль положительной оси y, так что центр основания равен (0, a, 0), а точка на окружности основания равна (б, а, 0), вы можете выбрать

x = r * cos(t) 
y = h 
z = r * sin(t) 

Когда вы спросили о создании образцов «на поверхности» вы не уточнялось, если вы имеете в виду только сторона (или это «стороны»?) конуса, только основание или всю поверхность. Ваш второй рисунок означает только сторону, но я дам код для всех трех.

сторона только

Снова мы используем меньший конус высоты h внутри больший конус. Его площадь поверхности изменяется как квадрат ее высоты, поэтому мы берем квадратный корень из равномерной случайной величины. Круг в его основании фиксирован, если наша точка должна быть на поверхности, и снова угол является однородным. Таким образом, мы получаем

h = a * sqrt(random()) 
r = (b/a) * h 
t = 2 * pi * random() 

Используйте один и тот же код для x, y и z я выше для внутренней части конуса, чтобы получить конечную случайную точку на боковой поверхности конуса.

База только

Это так же, как выбрать точку в интерьере, за исключением того, высота предопределено равной высоты всего конуса. Мы получаем следующее, несколько упрощенный код:

h = a 
r = b * sqrt(random()) 
t = 2 * pi * random() 

Опять же, использовать предыдущий код для окончательного x, y и z.

Вся поверхность

Здесь мы можем сначала решить, в случайном порядке, независимо от того, чтобы разместить нашу точку на базе или на поверхности, затем поместите точку в одном из двух способов, указанных выше. Площадь основания конуса высоты a и радиуса основания b составляет pi * b * b, а площадь поверхности конуса равна pi * b * sqrt(a*a + b*b). Мы используем отношение основания к общему количеству этих областей, чтобы выбрать, какие подповерхностный использовать для нашей точки:

if random() < b/(b + sqrt(a*a + b*b)): 
    return point_on_base(a, b) 
else: 
    return point_on_side(a, b) 

Используйте свои коды выше для стороны и основания, чтобы завершить этот код.


Вот простые Matplotlib 3D разброс участков из 10000 случайных точек, сначала внутри конуса, то на его боковой поверхности. Обратите внимание, что я сделал угол вершины 45 °, так как ваш текст указывает, но в отличие от ваших изображений. Просмотр этих изображений с других углов, по-видимому, подтверждает, что они однородны по объему или площади.

enter image description here

enter image description here

 Смежные вопросы

  • Нет связанных вопросов^_^