Sampling uniformly distributed random points inside a spherical volume

前端 未结 9 613
无人及你
无人及你 2020-11-27 13:10

I am looking to be able to generate a random uniform sample of particle locations that fall within a spherical volume.

The image below (courtesy of http://nojhan.fre

相关标签:
9条回答
  • 2020-11-27 13:26

    Normed gaussian 3d vector is uniformly distributed on sphere, see http://mathworld.wolfram.com/SpherePointPicking.html

    For example:

    N = 1000
    v = numpy.random.uniform(size=(3,N)) 
    vn = v / numpy.sqrt(numpy.sum(v**2, 0))
    
    0 讨论(0)
  • 2020-11-27 13:27

    Generate a set of points uniformly distributed within a cube, then discard the ones whose distance from the center exceeds the radius of the desired sphere.

    0 讨论(0)
  • 2020-11-27 13:33

    Would this be uniform enough for your purposes?

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

    A slice of it

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

    looks like: enter image description here

    0 讨论(0)
  • 2020-11-27 13:36
    import random
    R = 2
    
    def sample_circle(center):
        a = random.random() * 2 * np.pi
        r = R * np.sqrt(random.random())
        x = center[0]+ (r * np.cos(a))
        y = center[1] + (r * np.sin(a))
        return x,y
    
    ps = np.array([sample_circle((0,0)) for i in range(100)])
    
    plt.plot(ps[:,0],ps[:,1],'.')
    plt.xlim(-3,3)
    plt.ylim(-3,3)
    plt.show()
    

    0 讨论(0)
  • 2020-11-27 13:38

    You can just generate random points in spherical coordinates (assuming that you are working in 3D): S(r, θ, φ ), where r ∈ [0, R), θ ∈ [0, π ], φ ∈ [0, 2π ), where R is the radius of your sphere. This would also allow you directly control how many points are generated (i.e. you don't need to discard any points).

    To compensate for the loss of density with the radius, you would generate the radial coordinate following a power law distribution (see dmckee's answer for an explanation on how to do this).

    If your code needs (x,y,z) (i.e. cartesian) coordinates, you would then just convert the randomly generated points in spherical to cartesian coordinates as explained here.

    0 讨论(0)
  • 2020-11-27 13:45

    While I prefer the discarding method for spheres, for completeness I offer the exact solution.

    In spherical coordinates, taking advantage of the sampling rule:

    phi = random(0,2pi)
    costheta = random(-1,1)
    u = random(0,1)
    
    theta = arccos( costheta )
    r = R * cuberoot( u )
    

    now you have a (r, theta, phi) group which can be transformed to (x, y, z) in the usual way

    x = r * sin( theta) * cos( phi )
    y = r * sin( theta) * sin( phi )
    z = r * cos( theta )
    
    0 讨论(0)
提交回复
热议问题