40

球状ボリューム内にある粒子位置のランダムで均一なサンプルを生成できるようにしたいと考えています。

下の画像 ( http://nojhan.free.fr/metah/提供) は、私が探しているものを示しています。これは球をスライスしたもので、点が均一に分布していることを示しています。

一様分布円

これは私が現在得ているものです:

一様に分布しているが点のクラスター

球座標とデカルト座標の間の変換により、中心に点のクラスターがあることがわかります。

私が使用しているコードは次のとおりです。

def new_positions_spherical_coordinates(self):
   radius = numpy.random.uniform(0.0,1.0, (self.number_of_particles,1)) 
   theta = numpy.random.uniform(0.,1.,(self.number_of_particles,1))*pi
   phi = numpy.arccos(1-2*numpy.random.uniform(0.0,1.,(self.number_of_particles,1)))
   x = radius * numpy.sin( theta ) * numpy.cos( phi )
   y = radius * numpy.sin( theta ) * numpy.sin( phi )
   z = radius * numpy.cos( theta )
   return (x,y,z)

以下は、 http://nojhan.free.fr/metahで与えられた方程式に似た、均一な球形のサンプルを作成すると思われる MATLAB コードです。私はそれを解読することも、彼らが何をしたかを理解することもできないようです.

function X = randsphere(m,n,r)

% This function returns an m by n array, X, in which 
% each of the m rows has the n Cartesian coordinates 
% of a random point uniformly-distributed over the 
% interior of an n-dimensional hypersphere with 
% radius r and center at the origin.  The function 
% 'randn' is initially used to generate m sets of n 
% random variables with independent multivariate 
% normal distribution, with mean 0 and variance 1.
% Then the incomplete gamma function, 'gammainc', 
% is used to map these points radially to fit in the 
% hypersphere of finite radius r with a uniform % spatial distribution.
% Roger Stafford - 12/23/05

X = randn(m,n);
s2 = sum(X.^2,2);
X = X.*repmat(r*(gammainc(s2/2,n/2).^(1/n))./sqrt(s2),1,n);

Python で球体ボリュームから真に均一なサンプルを生成するための提案をいただければ幸いです。

均一な球殻からサンプリングする方法を示す例はたくさんあるようですが、それはより簡単な問題のようです。この問題はスケーリングに関係しています。球体のボリュームから均一なサンプルを生成するには、半径 1.0 よりも半径 0.1 の方がパーティクルの数が少ない必要があります。

編集:私が普通に頼んだという事実を修正して削除し、私は制服を意味しました.

4

9 に答える 9

46

私は球体の破棄方法を好みますが、完全を期すために正確な解決策を提供します

球面座標では、サンプリング ルールを利用します。

phi = random(0,2pi)
costheta = random(-1,1)
u = random(0,1)

theta = arccos( costheta )
r = R * cuberoot( u )

これで、通常の方法で(r, theta, phi)変換できるグループができました(x, y, z)

x = r * sin( theta) * cos( phi )
y = r * sin( theta) * sin( phi )
z = r * cos( theta )
于 2011-03-23T16:55:02.577 に答える
18

n 次元空間で球面上に均一な点を生成する素晴らしい方法があり、これを質問で指摘しました (MATLAB コードを意味します)。

なぜそれが機能するのですか?答えは、n 次元正規分布の確率密度を見てみましょう。等しい(定数まで)

exp(-x_1*x_1/2) *exp(-x_2*x_2/2)... = exp(-r*r/2) なので、方向には依存せず、距離のみに依存します! これは、ベクトルを正規化した後、結果の分布の密度が球全体で一定になることを意味します。

この方法は、その単純さ、汎用性、効率性 (および美しさ) から、間違いなく好まれます。3 次元の球体で1000 個のイベントを生成するコード:

size = 1000
n = 3 # or any positive integer
x = numpy.random.normal(size=(size, n)) 
x /= numpy.linalg.norm(x, axis=1)[:, numpy.newaxis]

ところで、見るべき良いリンク: http://www-alg.ist.hokudai.ac.jp/~jan/randsphere.pdf

球内で均一に分布する場合、ベクトルを正規化する代わりに、vercor に f(r) を掛ける必要があります。f(r)*r は [0,1] 上の r^n に比例する密度で分布します。あなたが投稿したコードで行われます

于 2014-05-21T13:54:22.057 に答える
15

立方体内に均一に分布する点のセットを生成し、中心からの距離が目的の球の半径を超える点を破棄します。

于 2011-03-23T16:16:46.460 に答える
2

ノルム ガウス 3D ベクトルは、球面上に均一に分布しています。http://mathworld.wolfram.com/SpherePointPicking.html を参照してください。

例えば:

N = 1000
v = numpy.random.uniform(size=(3,N)) 
vn = v / numpy.sqrt(numpy.sum(v**2, 0))
于 2014-05-24T12:13:11.387 に答える
2

これはあなたの目的のために十分に均一でしょうか?

In []: p= 2* rand(3, 1e4)- 1
In []: p= p[:, sum(p* p, 0)** .5<= 1]
In []: p.shape
Out[]: (3, 5216)

それのスライス

In []: plot(p[0], p[2], '.')

次のようになります。 ここに画像の説明を入力

于 2011-03-23T16:20:23.147 に答える
-1

球面座標でランダムな点を生成することができます(3Dで作業していると仮定):S(r、θ、φ)、ここでr∈[0、R)、θ∈[0、π]、φ∈[0、 2π)、ここでRは球の半径です。これにより、生成されるポイントの数を直接制御することもできます(つまり、ポイントを破棄する必要はありません)。

半径による密度の損失を補正するには、べき乗則の分布に従って半径座標を生成します(これを行う方法の説明については、dmckeeの回答を参照してください)。

コードに(x、y、z)(つまりデカルト)座標が必要な場合は、ここで説明するように、球形でランダムに生成されたポイントをデカルト座標に変換します。

于 2011-03-23T16:37:13.460 に答える