равномерное формирование трехмерных точек на цилиндре / конусе - PullRequest
6 голосов
/ 21 апреля 2010

Я хочу, чтобы случайно и равномерно генерировать точки на цилиндре и конусе (отдельно). Цилиндр определяется его центром, радиусом и высотой. Те же характеристики для конуса. Я могу получить ограничивающий прямоугольник для каждой фигуры, поэтому я думал о создании точек внутри ограничивающего прямоугольника. Однако я не уверен, как проецировать их на цилиндр / конус или это лучшая идея.

Есть предложения?

Спасибо.

Ответы [ 7 ]

4 голосов
/ 21 апреля 2010

Корпус цилиндра тривиален. Если цилиндр радиуса r> 0 и высоты h> 0 является образом (x, y, z) = (r cos φ, r sin φ, z) на φ ∈ [0, 2π [и z ∈ [-h / 2, h / 2], то просто выберите φ и z случайным образом на этих интервалах. Конечно, можно просто параметризовать конус, используя стандартную параметризацию, но тогда элемент площади не будет постоянным на плоскости параметров, и поэтому распределение точек не будет случайным. Таким образом, вам нужно найти другую параметризацию. Я подробно обсудил эту тему для сферы на моем сайте AlgoSim .

2 голосов
/ 21 апреля 2010

Один из способов думать об этом состоит в том, что и цилиндр, и конус можно развернуть на плоские поверхности - просто разрежьте каждую из них прямой линией сверху вниз.

Цилиндр разворачивается в прямоугольник (если вы используете верх и низ, добавьте пару дисков).

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

Достаточно просто внедрить эти плоские поверхности в прямоугольник R на плоскости xy. Создайте равномерно распределенные точки в R и, когда они находятся внутри плоских поверхностей, сопоставьте их с исходными поверхностями.

Не упустите некоторые другие ответы здесь, которые пытаются скоординировать конус с точки зрения угла и высоты. Хотя точки будут равномерно распределены по углу и высоте, они не будут распределены равномерно по отношению к поверхности. площадь. Они будут более плотно распределены на кончике.

2 голосов
/ 21 апреля 2010

Было бы проще генерировать точки непосредственно на цилиндре или конусе.

Прошло много времени с тех пор, как я это сделал, но параметризовать ось цилиндра, а затем для каждой точки параметризировать круг на этой высоте. Это создаст точки на поверхности. Радиус круга - это радиус цилиндра.

Для конуса необходимо уменьшить радиус круга при перемещении от основания к вершине.

0 голосов
/ 21 апреля 2010

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

Для этого вы можете начать с выбора расстояния между точками.При перемещении вдоль оси конуса вы вычисляете окружность на этой высоте, а затем делите окружность на линейное расстояние между точками, чтобы получить количество точек.Затем вы делите 2pi радиана (или 360 градусов, или что-то еще) на количество точек, чтобы получить угловое расстояние для этого радиуса.

В зависимости от необходимой точности вы можете отслеживать остаток от одного кругапока вы вычисляете следующий круг.Например, если у вас есть два круга подряд, которые работают с точками xxx.4, вы округлили бы каждый из них, если смотреть на них изолированно - но если смотреть на них вместе, у вас есть точки xxx.8, поэтому вам следуетокруглите один вниз, а другой вверх, чтобы общая плотность была как можно ближе к правильному значению.

Обратите внимание, что, хотя это не так очевидно, последнее может также применяться к цилиндру - обычно выиметь некоторые округления при распределении каждого круга точек.

0 голосов
/ 21 апреля 2010

Для однородных точек на окружности или конусе радиуса R и высоты / высоты H:

generate:
  angle= uniform_random(0,2*pi)
  value= uniform_random(0,1)

in either case, let:
  r= R * sqrt(value)

then (using separate random numbers for each):
  circle_point= point3d( r*cos(angle), r*sin(angle), H )
or:
  cone_point= point3d( r*cos(angle), r*sin(angle), r*H )

Обратите внимание, что если вы хотите основание на конусе, вам нужно будет сделать это отдельно от изогнутой формы. Чтобы убедиться, что плотность точек одинакова для разных деталей, проще всего рассчитать площади деталей и сгенерировать пропорциональное количество точек для каждой детали.

sqrt (значение) - это то, что обеспечивает равномерность плотности ваших случайных точек. Как уже упоминалось в других вопросах, для этого вам нужно треугольное распределение ; взятие sqrt () превращает равномерное распределение на [0,1) в треугольное.

Для цилиндра вам не нужен sqrt (); изогнутая часть:

  cylinder_point= point3d( R*cos(angle), R*sin(angle), H*value )
0 голосов
/ 21 апреля 2010

Пусть точка определяется по координатам r , a , h , где r - это «радиус» (расстояние от вертикальная ось, проходящая от центра), a - это угол, как в полярных координатах, а h - его высота.

Для цилиндра (радиус R и высота H ): выберите независимо

  • a равномерное в [0, 2pi),
  • ч униформа в [0, H ] и
  • r с "треугольной плотностью": f ( r ) = 2 r / R , если 0 <= <em>r <= <em>R , 0 в противном случае (плотность при r должна быть пропорциональна длине окружности радиуса r ).

Не должно быть трудностей для выборки из такого треугольного распределения, поскольку его кумулятивное распределение (квадратичный моном) легко обратимо (см. в этой статье ). Кроме того, этот ответ основан на интуиции, но не должно быть трудно доказать, что распределение, которое вы получаете на цилиндре, является равномерным.

Для конуса (радиус R и высота H ): выберите

  • a униформа в [0, 2pi),
  • ч с плотностью, выполненной с сегментом параболы: f ( ч ) = 3 ( H - ч ) ^ 2 / H ^ 3, если 0 <= <em>h <= <em>H , 0 в противном случае (плотность при h должна быть пропорциональна площадь круглого сечения на высоте ч ),
  • let r ( h ) = ( H - h ) R / H (радиус сечения на высоте ч ); затем выберите r с "треугольным распределением" f ( r ) = 2 r / r ( ч ) если 0 <= <em>r <= <em>r ( h ), 0 в противном случае.

Опять же, выборка ч должна быть легкой, поскольку кумулятивное распределение легко обратимо.

EDIT. Если вы хотите создать точки на поверхности фигур, то решение будет проще:

Цилиндр : выберите

  • a равномерное в [0, 2pi),
  • ч униформа в [0, Н ],
  • r = R .

Конус : выберите

  • a равномерное в [0, 2pi),
  • ч с треугольной плотностью: f ( ч ) = 2 ( Н - ч ) / Н ^ 2, если 0 <= <em>ч <= <em>Н , 0 в противном случае (плотность при ч должна быть пропорциональна длине окружности на высоте ч ).
  • r = r ( ч ) = ( H - ч ) R / H = радиус на высоте ч .
0 голосов
/ 21 апреля 2010

Чтобы поместить эти ответы в псевдокод:

Для цилиндра, заданного цилиндраРадиус и цилиндрВысота:

angle = random number between 0 & 360

x = cos(pi/180*angle)*cylinderRadius
y = sin(pi/180*angle)*cylinderRadius
z = random number between 0 and cylinderHeight.

Для конуса, заданного coneRadius, coneHeight:

angle = random number between 0 & 360

z = random number between 0 and coneHeight

thisRadius = coneRadius * (1-(z/coneHeight)); //This gives a decreasing radius as height increases.

x = cos(pi/180*angle)*thisRadius
y = sin(pi/180*angle)*thisRadius

Каждая точка (x, y, z) будет лежать на цилиндре / конусе. Создайте достаточное количество этих точек, и вы сможете породить частицы на поверхности цилиндра / конуса, но это может не дать точно равномерное распределение ...

...