<p>经过一番反复试验,我终于用gammainc方法完成了。它背后的数学是我无法理解的,但我基本上把gammainc中的系数2改为幂z来提高一致性。在</p>
<p>还测试了它在三维和似乎工作良好。在</p>
<p>(这在我的待办事项列表中已经有一段时间了,谢谢你的建议!)在</p>
<pre><code>import numpy as np
from scipy.special import gammainc
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def sample_ring(center,r1,r2,n_points):
nd = center.size
x = np.random.normal(size=(n_points, nd))
sq = np.sum(x**2,axis=1)
z = (r2-r1)/r2
fr = (r2-r1)*gammainc(nd/2**z,sq/2**z)**(1/nd)/np.sqrt(sq) + r1/np.sqrt(sq)
frtiled = np.tile(fr.reshape(n_points,1),(1,nd))
p = center + np.multiply(x,frtiled)
return p
fig1 = plt.figure(1)
ax1 = fig1.gca()
center = np.array([0,0])
r1 = 1.5
R2 = 3
p = sample_ring(center,r1,R2,5000)
ax1.scatter(p[:,0],p[:,1],s=0.5)
ax1.add_artist(plt.Circle(center,r1,fill=False,color='0.5'))
ax1.add_artist(plt.Circle(center,R2,fill=False,color='0.5'))
ax1.set_xlim(-4,4)
ax1.set_ylim(-4,4)
ax1.set_aspect('equal')
fig3 = plt.figure(3)
ax3 = plt.gca(projection='3d')
ax3.set_aspect("equal")
theta, phi = np.mgrid[0:2*np.pi:10j, 0:np.pi:10j]
c_3d = np.array([0,0,0])
r1_3d = 0.5
x1 = c_3d[0] + r1_3d*np.cos(theta)*np.sin(phi)
y1 = c_3d[1] + r1_3d*np.sin(theta)*np.sin(phi)
z1 = c_3d[2] + r1_3d*np.cos(phi)
r2_3d = 1.4
x2 = c_3d[0] + r2_3d*np.cos(theta)*np.sin(phi)
y2 = c_3d[1] + r2_3d*np.sin(theta)*np.sin(phi)
z2 = c_3d[2] + r2_3d*np.cos(phi)
ax3.plot_wireframe(x1, y1, z1, color="r")
ax3.plot_wireframe(x2, y2, z2, color="r")
p = sample_ring(c_3d,r1_3d,r2_3d,1000)
ax3.scatter(p[:,0],p[:,1],p[:,2], c='b', marker='o')
ax3.set_xlim(-1.5, 1.5)
ax3.set_ylim(-1.5, 1.5)
ax3.set_zlim(-1.5, 1.5)
</code></pre>
<p><a href="https://i.stack.imgur.com/DNemQ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/DNemQ.png" alt="uniform sample in ring"/></a></p>
<p><a href="https://i.stack.imgur.com/Hsze5.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Hsze5.png" alt="uniform sample 3d ring"/></a></p>