Случайная точка на данной сфере - PullRequest
13 голосов
/ 03 апреля 2011

Я хочу выбрать случайные точки на данной сфере. Эта страница объясняет это довольно хорошо:

http://mathworld.wolfram.com/SpherePointPicking.html («Чтобы получить очки, такие, что любая маленькая область на сфере ...»)

Но я не совсем уверен, правильно ли я реализую его в JavaScript, поскольку у меня мало средств для его правильного тестирования:

var u = random();
var v = random();
var angle1 = 2 * Math.PI * u;
var angle2 = Math.pow(Math.cos (2 * v - 1), -1);
X = X0 + (radius * Math.sin(angle1) * Math.cos(angle2));
Y = Y0 + (radius * Math.sin(angle1) * Math.sin(angle1));
Z = Z0 + (radius * Math.cos(angle1));

Я особенно не уверен, правильно ли я понял, что cos (-1) правильно, что я реализовал как "Косинус в степени -1".

Ответы [ 2 ]

29 голосов
/ 24 февраля 2013

Алгоритм куба не даст равномерного распределения по сфере - в частности, области вблизи проекций углов будут иметь наиболее плотное распределение точек, а вблизи центров граней кубов будут самые низкие.

Вы можете понять это интуитивно, поскольку объем куба, проецируемого на нижележащую сферу, больше вблизи углов, которые расположены около центров граней кубов.Фактически, объем маленького кусочка (который проецируется на маленький круг на сфере) пропорционален кубу размера вектора от начала координат через центр малого круга до точки на сфере, которую он пересекает.

Таким образом, относительный объем в центре грани куба (например, (1,0,0)) равен 1, но для угла (например, (1,1,1)) это куб sqrt (3)или 1,73 куба, примерно 5,2, поэтому почти в 5 раз плотнее!

Функция spreadPoints () могла бы работать лучше, но я не уверен.

В вашем JavaScript есть пара ошибок - использование pow (.., -1) функция вместо acos () смешивает углы и пропускает объект Math для вызова random ().

Здесь аналогичный, но правильный JavaScript для выполнения того, что говорит ссылка Wolfram:

/*
Returns a random point of a sphere, evenly distributed over the sphere.
The sphere is centered at (x0,y0,z0) with the passed in radius.
The returned point is returned as a three element array [x,y,z]. 
*/
function randomSpherePoint(x0,y0,z0,radius){
   var u = Math.random();
   var v = Math.random();
   var theta = 2 * Math.PI * u;
   var phi = Math.acos(2 * v - 1);
   var x = x0 + (radius * Math.sin(phi) * Math.cos(theta));
   var y = y0 + (radius * Math.sin(phi) * Math.sin(theta));
   var z = z0 + (radius * Math.cos(phi));
   return [x,y,z];
}
23 голосов
/ 04 апреля 2011

Я думаю, что более простой алгоритм -

  1. Выберите случайную точку внутри [-1,1]x[-1,1]x[-1,1] куба
  2. Если x*x + y*y + z*z > 1 повторить с 1
  3. Нормализовать деление x, y и z на Math.sqrt(x*x + y*y + z*z)

другими словами, просто выберите случайную точку внутри сферы и спроецируйте ее. Не беспокойтесь о «петле», потому что вероятность того, что точка находится вне сферы, составляет около 0,4764, и в среднем петле потребуется менее двух итераций.

Вы можете увидеть этот алгоритм в действии по этой ссылке . Обратите внимание, что если вы используете chrome, то вокруг экватора возникнет некоторая полоса, которая, на мой взгляд, является ошибкой в ​​Math.random или просто случайным генератором низкого качества (отлично работает в Firefox или Safari, но та же проблема видна в браузере Android). Полосы гораздо более заметны с большим количеством точек (например, 10000 вместо 1000 точек, которые я сейчас использую для обеспечения плавности анимации). РЕДАКТИРОВАТЬ: эта ошибка была исправлена ​​в Chrome и Android.

Обратите внимание, что если вы ищете способ равномерного распределения точек по сфере, вы можете сделать что-то более приятное, выбрав десять случайных точек, как описано выше, и затем принять только ту, которая имеет наибольшее расстояние 3d от набора уже выбранных. точки. Это все еще является глобально случайным (то есть вероятность того, что диск с заданным радиусом получит точку, одинакова для всех дисков на сфере), но распределит точки лучше, если вам потребуется выполнить «выборку» сферы. Эта функция кодируется как spreadPoints() в html-файле, указанном по ссылке.

Здесь вы можете увидеть разницу между двумя подходами:

enter image description here

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...