Равномерное распределение n точек на сфере

Мне нужен алгоритм, который может дать мне положение вокруг сферы для N точек (возможно, менее 20), что смутно распространяет их. Нет необходимости в «совершенстве», но мне просто нужно, чтобы никто из них не был сгруппирован.

  • Этот вопрос обеспечил хороший код, но я не мог найти способ сделать эту форму, поскольку это казалось на 100% рандомизированным.
  • Это рекомендуемое сообщение в блоге имело два способа, позволяющих вводить количество точек на сфере, но алгоритм Saff и Kuijlaars точно в psuedocode, который я мог бы расшифровать, и в примере кода, который я нашел, содержится «node [k]», что я не мог см. объясненную и разрушенную эту возможность. Вторым примером блога была «Золотая секция», которая дала мне странные, сгруппированные результаты, без четкого определения постоянного радиуса.
  • Этот алгоритм из этого вопроса кажется, что он может работать, но я не могу объединить то, что на этой странице, в psuedocode или что-то еще.

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

Итак, я ищу простой псевдокод для равномерного распределения N точек вокруг единичной сферы, которая либо возвращается в сферических, либо декартовых координатах. Еще лучше, если он может даже распределить с небольшим количеством рандомизации (подумайте о планетах вокруг звезды, прилично разложите, но с комнатой для освобождения).

В этом примере node[k] кода node[k] является только k-й узел. Вы генерируете массив N точек, а node[k] – kth (от 0 до N-1). Если это все, что вас путает, надеюсь, вы можете использовать это сейчас.

(другими словами, k представляет собой массив размера N, который определяется до начала fragmentа кода и который содержит список точек).

В качестве альтернативы , опираясь на другой ответ здесь (и используя Python):

 > cat ll.py from math import asin nx = 4; ny = 5 for x in range(nx): lon = 360 * ((x+0.5) / nx) for y in range(ny): midpt = (y+0.5) / ny lat = 180 * asin(2*((y+0.5)/ny-0.5)) print lon,lat > python2.7 ll.py 45.0 -166.91313924 45.0 -74.0730322921 45.0 0.0 45.0 74.0730322921 45.0 166.91313924 135.0 -166.91313924 135.0 -74.0730322921 135.0 0.0 135.0 74.0730322921 135.0 166.91313924 225.0 -166.91313924 225.0 -74.0730322921 225.0 0.0 225.0 74.0730322921 225.0 166.91313924 315.0 -166.91313924 315.0 -74.0730322921 315.0 0.0 315.0 74.0730322921 315.0 166.91313924 

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

Это не то же самое, что и все точки, имеющие примерно одинаковое расстояние до своих соседей (о чем я думаю, о чем говорят ваши ссылки), но этого может быть достаточно для того, что вы хотите и улучшаете, просто создавая единую сетку lat / lon ,

Алгоритм сферы Фибоначчи отлично подходит для этого. Это быстро и дает результаты, которые с первого взгляда легко обманут человеческий глаз. Вы можете увидеть пример, выполненный с обработкой, который будет показывать результат с течением времени по мере добавления точек. Вот еще один отличный интерактивный пример, сделанный @gman. И вот быстрая версия python с простым вариантом рандомизации:

 import math, random def fibonacci_sphere(samples=1,randomize=True): rnd = 1. if randomize: rnd = random.random() * samples points = [] offset = 2./samples increment = math.pi * (3. - math.sqrt(5.)); for i in range(samples): y = ((i * offset) - 1) + (offset / 2); r = math.sqrt(1 - pow(y,2)) phi = ((i + rnd) % samples) * increment x = math.cos(phi) * r z = math.sin(phi) * r points.append([x,y,z]) return points 

1000 образцов дают вам следующее:

введите описание изображения здесь

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

  1. Создайте симуляцию . Рассматривайте каждую точку как электрон, ограниченный сферой, затем запускайте симуляцию для определенного количества шагов. Отталкивание электронов, естественно, приведет систему к более стабильному состоянию, где точки примерно так же далеки друг от друга, как они могут получить.
  2. Отказ Hypercube . Этот фантастический метод на самом деле очень прост: вы равномерно выбираете точки (намного больше, чем n из них) внутри куба, окружающего сферу, а затем отклоняете точки вне сферы. Обработайте оставшиеся точки в виде векторов и нормализуйте их. Это ваши «образцы» – выберите n из них, используя какой-либо метод (случайно, жадный и т. Д.).
  3. Спиральные аппроксимации . Вы прослеживаете спираль вокруг сферы и равномерно распределяете точки вокруг спирали. Из-за вовлеченной математики это сложнее понять, чем симуляция, но гораздо быстрее (и, вероятно, связано с меньшим количеством кода). Самым популярным, по-видимому, является Saff, et al .

Более подробную информацию об этой проблеме можно найти здесь.

Золотой спиральный метод

Вы сказали, что не можете заставить золотой спиральный метод работать, и это позор, потому что это действительно, очень хорошо. Я хотел бы дать вам полное представление об этом, чтобы, может быть, вы могли понять, как удержать это от «смятия».

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

Грунтовка: спирали на подсолнечном диске

Чтобы понять этот алгоритм, я сначала приглашаю вас взглянуть на 2D-алгоритм спирали подсолнечника. Это основано на том, что самым иррациональным числом является золотое соотношение (1 + sqrt(5))/2 и если кто-то испускает точки подходом «стоять в центре», поворачивайте золотое соотношение целых оборотов, затем излучайте другое точка в этом направлении “, естественно, создается спираль, которая, как вы добираетесь до более высокого и большего числа точек, тем не менее отказывается иметь четко определенные« бары », на которые указывают точки. (Примечание 1)

Алгоритм равномерного интервала на диске,

 from numpy import pi, cos, sin, sqrt, arange import matplotlib.pyplot as pp num_pts = 100 indices = arange(0, num_pts, dtype=float) + 0.5 r = sqrt(indices/num_pts) theta = pi * (1 + 5**0.5) * indices pp.scatter(r*cos(theta), r*sin(theta)) pp.show() 

и он дает результаты, которые выглядят как (n = 100 и n = 1000):

введите описание изображения здесь

Расстояние между точками

Ключевой странной особенностью является формула r = sqrt(indices / num_pts) ; как я пришел к этому? (Заметка 2.)

Ну, я использую здесь квадратный корень, потому что я хочу, чтобы у них было равномерное расстояние вокруг сферы. Это то же самое, что сказать, что в пределе большого N я хочу, чтобы небольшая область R ∈ ( r , r + d r ), Θ ∈ ( θ , θ + ) содержала несколько точек, пропорциональных ее площади, что r r r d θ . Теперь, если мы притворимся, что речь идет о случайной переменной здесь, это имеет прямое толкование, говоря, что совместная плотность вероятности для ( R , Θ ) является просто cr для некоторой константы c . Нормализация на единичном диске затем приводит к c = 1 / π.

Теперь позвольте мне представить трюк. Он исходит из теории вероятностей, где она известна как выборка обратного CDF : предположим, что вы хотели создать случайную переменную с плотностью вероятности f ( z ), и у вас есть случайная величина U ~ Uniform (0, 1), как и выход из random() в большинстве языков программирования. Как ты делаешь это?

  1. Во-первых, превратите вашу плотность в кумулятивную функцию распределения F ( z ), которая, помните, monoтонно возрастает от 0 до 1 с производной f ( z ).
  2. Затем вычислите обратную функцию CDF F -1 ( z ).
  3. Вы обнаружите, что Z = F -1 ( U ) распределяется в соответствии с целевой плотностью. (Заметка 3).

Теперь спиральный трюк с золотым соотношением пробегает точки в хорошо четкой схеме для θ, поэтому давайте интегрируем это; для единичного круга мы остаемся с F ( r ) = r 2 . Таким образом, обратная функция F -1 ( u ) = u 1/2 , и поэтому мы будем генерировать случайные точки на сфере в полярных координатах с r = sqrt(random()); theta = 2 * pi * random() r = sqrt(random()); theta = 2 * pi * random() .

Теперь, вместо случайной выборки этой обратной функции, мы равномерно ее отбираем, и хорошая вещь об однородной выборке состоит в том, что наши результаты о том, как точки распределяются в пределе больших N, будут вести себя так, как если бы мы случайно опробовали ее. Эта комбинация – это трюк. Вместо random() мы используем (arange(0, num_pts, dtype=float) + 0.5)/num_pts , так что, скажем, если мы хотим пробовать 10 баллов, они равны r = 0.05, 0.15, 0.25, ... 0.95 , Мы равномерно пробуем r, чтобы получить расстояние между равными участками, и мы используем приращение подсолнечника, чтобы избежать ужасных «баров» точек на выходе.

Теперь сделаем подсолнечник на сфере

Изменения, которые нужно сделать, чтобы усечь сферу точками, include в себя только выключение полярных координат для сферических координат. Радиальная координата, конечно, не входит в это, потому что мы находимся на единичной сфере. Чтобы здесь было немного более последовательным, хотя я был обучен физике, я буду использовать математические координаты, где 0 ≤ φ ≤ π – широта, сходящаяся с полюса, и 0 ≤ θ ≤ 2π – долгота. Таким образом, отличие сверху заключается в том, что мы в основном заменяем переменную r на φ .

Наш элемент области, который был r d r d θ , теперь становится не намного сложнее sin ( φ ) d φ d θ . Таким образом, плотность соединения для равномерного расстояния равна sin ( φ ) / 4π. Интегрируя из θ , находим f ( φ ) = sin ( φ ) / 2, поэтому F ( φ ) = (1 – cos ( φ )) / 2. Инвертируя это, мы видим, что однородная случайная величина будет выглядеть как acos (1 – 2 u ), но мы произвольно выбираем случайным образом, поэтому вместо этого будем использовать φ k = acos (1 – 2 ( k + 0,5) / N ). Остальная часть алгоритма просто проецирует это на координаты x, y и z:

 from numpy import pi, cos, sin, arccos, arange import mpl_toolkits.mplot3d import matplotlib.pyplot as pp num_pts = 1000 indices = arange(0, num_pts, dtype=float) + 0.5 phi = arccos(1 - 2*indices/num_pts) theta = pi * (1 + 5**0.5) * indices x, y, z = cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi); pp.figure().add_subplot(111, projection='3d').scatter(x, y, z); pp.show() 

Снова при n = 100 и n = 1000 результаты выглядят так: введите описание изображения здесь введите описание изображения здесь

Заметки

  1. Эти «стержни» формируются рациональными приближениями к числу, а наилучшие рациональные приближения к числу исходят из его продолженного выражения, z + 1/(n_1 + 1/(n_2 + 1/(n_3 + ...))) где z – целое число, а n_1, n_2, n_3, ... либо конечная, либо бесконечная последовательность натуральных чисел:

     def continued_fraction(r): while r != 0: n = floor(r) yield n r = 1/(r - n) 

    Поскольку часть дроби 1/(...) всегда находится между нулем и единицей, большое целое в цепной дроби позволяет особенно хорошее рациональное приближение: «один, разделенный на что-то между 100 и 101», лучше, чем «один, деленный на что-то между 1 и 2. ” Поэтому самое иррациональное число равно 1 + 1/(1 + 1/(1 + ...)) и не имеет особо хороших рациональных аппроксимаций; можно решить φ = 1 + 1 / φ , умножив на φ, чтобы получить формулу для золотого отношения.

    1. Для людей, которые не знакомы с NumPy – все функции «векторизованы», так что sqrt(array) совпадает с тем, что другие языки могут писать map(sqrt, array) . Таким образом, это компонентное приложение sqrt . То же самое справедливо и для деления на скаляр или дополнение со скалярами – они применяются ко всем компонентам параллельно.

    2. Доказательство просто, если вы знаете, что это результат. Если вы спросите, какова вероятность того, что z < Z < z + d z , это то же самое, что задать вопрос о вероятности того, что z < F -1 ( U ) < z + d z , применить F ко всем трем выражениям, отметив, что это monoтонно возрастающую функцию, поэтому F ( z ) < U < F ( z + d z ) разложим правую часть, чтобы найти F ( z ) + f ( z ) d z , а так как U равномерно, эта вероятность справедлива f ( z ) d z, как и было обещано.

Этот ответ основан на той же «теории», которая хорошо описана в этом ответе

Я добавляю этот ответ как:
– Ни один из других вариантов не соответствует «однородности» необходимости «пятно» (или явно не ясно). (Принимая во внимание, что планету нравится поведение, связанное с распределением, в частности, в первоначальном запросе, вы просто отклоняетесь от конечного списка k равномерно созданных точек в случайном порядке (произвольно по счету индекса в элементах k назад).)
– Ближайший другой импотент заставил вас выбрать «угловую ось» N по сравнению с «одним значением N» по обеим значениям угловой оси (что при низких значениях N очень сложно узнать, что может, или может не иметь значения (например, вы хотите «5 очков» – получайте удовольствие))
– Кроме того, очень сложно «заглянуть», как различать другие параметры без каких-либо образов, поэтому вот что выглядит эта опция (ниже) и готовая к исполнению реализация, которая идет с ней.

с N в 20:

введите описание изображения здесь
а затем N при 80: введите описание изображения здесь

вот готовый к запуску код python3, где эмуляция – это тот же источник: « http://web.archive.org/web/20120421191837/http://www.cgafaq.info/wiki/Evenly_distributed_points_on_sphere », найденный другими пользователями , (Сюжет, который я включил, который срабатывает при запуске как «основной», берется из: http://www.scipy.org/Cookbook/Matplotlib/mplot3D )

 from math import cos, sin, pi, sqrt def GetPointsEquiAngularlyDistancedOnSphere(numberOfPoints=45): """ each point you get will be of form 'x, y, z'; in cartesian coordinates eg. the 'l2 distance' from the origion [0., 0., 0.] for each point will be 1.0 ------------ converted from: http://web.archive.org/web/20120421191837/http://www.cgafaq.info/wiki/Evenly_distributed_points_on_sphere ) """ dlong = pi*(3.0-sqrt(5.0)) # ~2.39996323 dz = 2.0/numberOfPoints long = 0.0 z = 1.0 - dz/2.0 ptsOnSphere =[] for k in range( 0, numberOfPoints): r = sqrt(1.0-z*z) ptNew = (cos(long)*r, sin(long)*r, z) ptsOnSphere.append( ptNew ) z = z - dz long = long + dlong return ptsOnSphere if __name__ == '__main__': ptsOnSphere = GetPointsEquiAngularlyDistancedOnSphere( 80) #toggle True/False to print them if( True ): for pt in ptsOnSphere: print( pt) #toggle True/False to plot them if(True): from numpy import * import pylab as p import mpl_toolkits.mplot3d.axes3d as p3 fig=p.figure() ax = p3.Axes3D(fig) x_s=[];y_s=[]; z_s=[] for pt in ptsOnSphere: x_s.append( pt[0]); y_s.append( pt[1]); z_s.append( pt[2]) ax.scatter3D( array( x_s), array( y_s), array( z_s) ) ax.set_xlabel('X'); ax.set_ylabel('Y'); ax.set_zlabel('Z') p.show() #end 

(N в 2, 5, 7, 13 и т. д.) и, похоже, работает «хорошо»,

То, что вы ищете, называется сферическим покрытием . Задача о сферическом покрытии очень сложна, и решения неизвестны, за исключением небольшого числа точек. Единственное, что точно известно, это то, что для n точек на сфере всегда существуют две точки расстояния d = (4-csc^2(\pi n/6(n-2)))^(1/2) или ближе.

Если вам нужен вероятностный метод для генерирования точек, равномерно распределенных по сфере, легко: генерировать точки в пространстве равномерно по гауссовскому распределению (он встроен в Java, не сложно найти код для других языков). Поэтому в трехмерном пространстве вам нужно что-то вроде

 Random r = new Random(); double[] p = { r.nextGaussian(), r.nextGaussian(), r.nextGaussian() }; 

Затем проецируем точку на сферу, нормализуя ее расстояние от начала координат

 double norm = Math.sqrt( (p[0])^2 + (p[1])^2 + (p[2])^2 ); double[] sphereRandomPoint = { p[0]/norm, p[1]/norm, p[2]/norm }; 

Гауссовское распределение в n измерениях сферически симметрично, поэтому проекция на сферу является однородной.

Разумеется, нет никакой гарантии, что расстояние между любыми двумя точками в коллекции равномерно сгенерированных точек будет ограничено ниже, поэтому вы можете использовать отклонение для принудительного применения любых таких условий, которые у вас могут быть: возможно, лучше всего создать всю коллекцию, а затем при необходимости отклоните всю коллекцию. (Или используйте «раннее отклонение», чтобы отклонить всю созданную вами коллекцию, просто не оставляйте некоторые точки и бросайте других.) Вы можете использовать формулу для d приведенную выше, минус некоторое ослабление, чтобы определить минимальное расстояние между точками, ниже которых вы отклоните набор очков. Вам нужно будет вычислить n, выбрать 2 расстояния, и вероятность отклонения будет зависеть от слабины; трудно сказать, как это сделать, поэтому запустите симуляцию, чтобы почувствовать соответствующую статистику.

Пытаться:

 function sphere ( N:float,k:int):Vector3 { var inc = Mathf.PI * (3 - Mathf.Sqrt(5)); var off = 2 / N; var y = k * off - 1 + (off / 2); var r = Mathf.Sqrt(1 - y*y); var phi = k * inc; return Vector3((Mathf.Cos(phi)*r), y, Mathf.Sin(phi)*r); }; 

Вышеупомянутая функция должна работать в цикле с общей петлей N и текущей итерацией цикла k.

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

Вот картина, за исключением того, что я помещал камеру на полпути внутри сферы, поэтому она выглядит 2d вместо 3d, потому что камера находится на таком же расстоянии от всех точек. http://3.bp.blogspot.com/-9lbPHLccQHA/USXf88_bvVI/AAAAAAAAADY/j7qhQsSZsA8/s640/sphere.jpg

с небольшим количеством точек вы могли бы запустить симуляцию:

 from random import random,randint r = 10 n = 20 best_closest_d = 0 best_points = [] points = [(r,0,0) for i in range(n)] for simulation in range(10000): x = random()*r y = random()*r z = r-(x**2+y**2)**0.5 if randint(0,1): x = -x if randint(0,1): y = -y if randint(0,1): z = -z closest_dist = (2*r)**2 closest_index = None for i in range(n): for j in range(n): if i==j: continue p1,p2 = points[i],points[j] x1,y1,z1 = p1 x2,y2,z2 = p2 d = (x1-x2)**2+(y1-y2)**2+(z1-z2)**2 if d < closest_dist: closest_dist = d closest_index = i if simulation % 100 == 0: print simulation,closest_dist if closest_dist > best_closest_d: best_closest_d = closest_dist best_points = points[:] points[closest_index]=(x,y,z) print best_points >>> best_points [(9.921692138442777, -9.930808529773849, 4.037839326088124), (5.141893371460546, 1.7274947332807744, -4.575674650522637), (-4.917695758662436, -1.090127967097737, -4.9629263893193745), (3.6164803265540666, 7.004158551438312, -2.1172868271109184), (-9.550655088997003, -9.580386054762917, 3.5277052594769422), (-0.062238110294250415, 6.803105171979587, 3.1966101417463655), (-9.600996012203195, 9.488067284474834, -3.498242301168819), (-8.601522086624803, 4.519484132245867, -0.2834204048792728), (-1.1198210500791472, -2.2916581379035694, 7.44937337008726), (7.981831370440529, 8.539378431788634, 1.6889099589074377), (0.513546008372332, -2.974333486904779, -6.981657873262494), (-4.13615438946178, -6.707488383678717, 2.1197605651446807), (2.2859494919024326, -8.14336582650039, 1.5418694699275672), (-7.241410895247996, 9.907335206038226, 2.271647103735541), (-9.433349952523232, -7.999106443463781, -2.3682575660694347), (3.704772125650199, 1.0526567864085812, 6.148581714099761), (-3.5710511242327048, 5.512552040316693, -3.4318468250897647), (-7.483466337225052, -1.506434920354559, 2.36641535124918), (7.73363824231576, -8.460241422163824, -1.4623228616326003), (10, 0, 0)] 

Возьмите два самых больших фактора вашего N , если N==20 то два самых больших фактора: {5,4} , или, в более общем смысле, {a,b} . подсчитывать

 dlat = 180/(a+1) dlong = 360/(b+1}) 

Поместите свой первый пункт в {90-dlat/2,(dlong/2)-180} , ваш второй в {90-dlat/2,(3*dlong/2)-180} , ваш третий в {90-dlat/2,(5*dlong/2)-180} , пока вы не споткнулись по всему миру один раз, к тому времени вы получите около {75,150} когда вы идете рядом с {90-3*dlat/2,(dlong/2)-180} .

Очевидно, я работаю в gradleусах по поверхности сферической земли, с обычными соглашениями для перевода +/- в N / S или E / W. И, очевидно, это дает вам совершенно неслучайное распределение, но оно однородно и точки не сгруппированы вместе.

Чтобы добавить некоторую степень случайности, вы могли бы генерировать 2 нормально распределенных (со средним 0 и std dev of {dlat / 3, dlong / 3} по мере необходимости) и добавлять их в равномерно распределенные точки.

edit: Это не отвечает на вопрос, который должен был спросить OP, оставляя его здесь, если люди находят его полезным как-то.

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

 longitude: φ = uniform([0,2pi)) azimuth: θ = -arcsin(1 - 2*uniform([0,1])) 

(определяется в следующей системе координат 🙂

введите описание изображения здесь

Обычно ваш язык имеет унифицированный случайный номер. Например, в python вы можете использовать random.random() для возврата числа в диапазоне [0,1) . Вы можете умножить это число на k, чтобы получить случайное число в диапазоне [0,k) . Таким образом, в python, uniform([0,2pi)) будет означать random.random()*2*math.pi


доказательство

Теперь мы не можем равномерно распределить θ, иначе мы получим скопление на полюсах. Мы хотим присвоить вероятности, пропорциональные площади поверхности сферического клина (θ на этой диаграмме фактически φ):

введите описание изображения здесь

Угловое смещение dφ на экваторе приведет к смещению dφ * r. Какое это смещение будет иметь произвольный азимут θ? Ну, радиус от оси z равен r*sin(θ) , поэтому длина дуги этой «широты», пересекающей клин, равна dφ * r*sin(θ) . Таким образом, мы вычисляем кумулятивное распределение площади с образцом из нее, интегрируя площадь среза с южного полюса на северный полюс.

введите описание изображения здесь (где stuff = dφ*r )

Теперь мы попытаемся получить обратную сторону CDF к выборке из нее: http://en.wikipedia.org/wiki/Inverse_transform_sampling

Сначала мы нормализуем делением нашего почти-CDF на его максимальное значение. Это имеет побочный эффект для отмены dφ и r.

 azimuthalCDF: cumProb = (sin(θ)+1)/2 from -pi/2 to pi/2 inverseCDF: θ = -sin^(-1)(1 - 2*cumProb) 

Таким образом:

 let x by a random float in range [0,1] θ = -arcsin(1-2*x) 

ИЛИ … чтобы разместить 20 точек, вычислить центры икосаэдронных граней. На 12 точек найдите вершины икосаэдра. Для 30 пунктов – средняя точка краев икосаэдра. вы можете сделать то же самое с тетраэдром, кубом, додекаэдром и октаэдрами: один набор точек находится на вершинах, другой – на центре лица, другой – на центре краев. Однако их нельзя смешивать.

Healpix решает тесно связанную проблему (пикселирование сферы с равными пикселями области):

http://healpix.sourceforge.net/

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

Я приземлился здесь, пытаясь найти его снова; название «healpix» точно не вызывает сферы …

 # create uniform spiral grid numOfPoints = varargin[0] vxyz = zeros((numOfPoints,3),dtype=float) sq0 = 0.00033333333**2 sq2 = 0.9999998**2 sumsq = 2*sq0 + sq2 vxyz[numOfPoints -1] = array([(sqrt(sq0/sumsq)), (sqrt(sq0/sumsq)), (-sqrt(sq2/sumsq))]) vxyz[0] = -vxyz[numOfPoints -1] phi2 = sqrt(5)*0.5 + 2.5 rootCnt = sqrt(numOfPoints) prevLongitude = 0 for index in arange(1, (numOfPoints -1), 1, dtype=float): zInc = (2*index)/(numOfPoints) -1 radius = sqrt(1-zInc**2) longitude = phi2/(rootCnt*radius) longitude = longitude + prevLongitude while (longitude > 2*pi): longitude = longitude - 2*pi prevLongitude = longitude if (longitude > pi): longitude = longitude - 2*pi latitude = arccos(zInc) - pi/2 vxyz[index] = array([ (cos(latitude) * cos(longitude)) , (cos(latitude) * sin(longitude)), sin(latitude)]) 

Это работает, и это смертельно просто. Сколько вы хотите:

  private function moveTweets():void { var newScale:Number=Scale(meshes.length,50,500,6,2); trace("new scale:"+newScale); var l:Number=this.meshes.length; var tweetMeshInstance:TweetMesh; var destx:Number; var desty:Number; var destz:Number; for (var i:Number=0;i 
Interesting Posts

Реализация NotificationListenerService

Как мы можем создавать графики стиля xkcd?

Прокрутка JTable до указанного указателя строки

Панель навигации Outlook 2010 – отображение непрочитанного числа в почтовом ящике

Загрузите файл через HTTP-форму через MultipartEntityBuilder с индикатором выполнения

Android TextView Обоснование текста

Наиболее эффективный способ реализации целочисленной силовой функции pow (int, int)

Java: как преобразовать HashMap в массив

android-sdks / build-tools / 17.0.0 / aapt: ошибка при загрузке разделяемых библиотек: libz.so.1: невозможно открыть файл общих объектов: нет такого файла или каталога

Html.ActionLink как кнопка или изображение, а не ссылка

В чем разница между интерфейсом и абстрактным classом?

Обнаружение скрытых веб-сканеров

Как получить байты из UnsafeMutableRawPointer?

постоянный указатель vs указатель на постоянное значение

Log4Net: программно указать несколько регистраторов (с несколькими файловыми приложениями)

Давайте будем гением компьютера.