在Python中生成一个圆环内的随机x,y坐标。

3

我正在尝试在一个环形区域内生成随机的x和y坐标,该环形区域具有外半径为3.5和内半径为2。因此,对于x和y,必须满足以下条件:

x**2 + y**2 < 12.25 and x**2 + y**2 > 4

我编写了以下函数:

def meteorites():
    circle = False
    while circle == False:        
        r = np.array([uniform(-6., 6.), uniform(-6., 6.)])
        # we will regenerate random numbers untill the coordinates
        # are within the ring x^2+y^2 < 3,5^2 and x^2+y^2 > 2^2
        if (r[0]**2+r[1]**2 < 12.25) and (r[0]**2+r[1]**2 > 4.):
            circle = True

       else :
            circle = False

    return r[0], r[1]

x = np.zeros(1000)
y = np.zeros(1000)
for i in range(1000):
    x[i] = meteorites()[0]
    y[i] = meteorites()[1]
plt.scatter(x,y)
plt.show()  

当我画出结果坐标后,我得到了从-3.5到3.5的正方形区域。我似乎找不到问题所在。我也不确定是编码错误还是数学问题。既然你们通常擅长于这两者,你能看出我在这里做错了什么吗?


3
为什么不生成一个随机角度和距离,然后将其转换为x、y坐标对呢? - Martijn Pieters
@MartijnPieters 如果您均匀生成距离,则内环中的点将更密集。 - kennytm
7个回答

8
为了在环中获得均匀分布的随机点,应考虑薄圆形区域的相对面积。关于圆形如何工作,请参见此处enter image description here 对于您的情况,在内部和外部半径的平方范围内生成SquaredR的均匀分布。伪代码:
 Fi  = RandomUniform(0, 2 * Pi)
 SquaredR  = RandomUniform(inner*inner, outer*outer)
 R = Sqrt(SquaredR)
 x,y = R * Cos(Fi), R * Sin(Fi)

6

随机选择一个角度和两个约束之间的距离;您需要在圆形中产生一个均匀分布

from math import sin, cos, radians, pi, sqrt

def meteorites():
    angle = uniform(0, 2 * pi)  # in radians
    distance = sqrt(uniform(4, 12.25))
    return distance * cos(angle), distance * sin(angle)

完美的。非常感谢! - user90465
是的,当我看到时间时我意识到了。因为我忙于研究如何在圆周上进行适当的分布,所以没有看到你的评论;-) - Martijn Pieters

5

您的随机点不在圆环上,是因为这两行代码没有达到您的预期:

x[i] = meteorites()[0]
y[i] = meteorites()[1]

这些将环上一个点的x值分配给x[i],并将来自环上不同点的y值分配给y[i]。你从不同的点获取坐标是因为你调用了两次meteorites()
相反,你可能想要只调用一次函数,然后为每个坐标赋值,或者使用可迭代解包的赋值,在等号左侧同时指定两个目标。
x[i], y[i] = meteorites()

3
您的实现也可以正常工作,只需更正一行代码:将调用meteorites()两次更改为仅调用一次即可。
x = np.zeros(1000)
y = np.zeros(1000)
for i in range(1000):
    x[i], y[i] = meteorites()
plt.scatter(x,y)
plt.show()  

enter image description here


2
正如@Martijn Pieters所建议的那样,只需在所需范围内均匀地绘制极坐标即可。
theta = uniform(0,2*np.pi)
r = uniform(2.,3.5)
x = r*np.cos(theta)
y = r*np.sin(theta)

编辑:每个点在环中出现的概率相等。

但是实际上,对于给定的theta,距离下限越近的r会有更少的像素。因此,具有较小r的“陨石”将以更大的概率发生。

我认为这种影响可以忽略不计。

编辑2:MBo的回答更好。代码:

theta = uniform(0, 2 * np.pi)
r = np.sqrt(uniform(2.0 ** 2, 3.5 ** 2)) # draw from sqrt distribution
x = r * np.cos(theta)
y = r * np.sin(theta)

一个圆有2π弧度;你正在布置半个环的位置。 - Martijn Pieters

2
我更倾向于通过循环来选择一个在你的环形范围内的随机角度和随机距离,然后从中计算出坐标。
但在你的代码中,我看到的第一个问题是应该写:
x[i],y[i] = meteorites()

代替
x[i] = meteorites()[0] 
y[i] = meteorites()[1]

在你的示例中,你调用了meteorites()两次,导致x和y是两个不同的陨石。

1

您可以尝试使用numpy生成1000个样本,具体操作如下:

import numpy 
n = 1000
phi = numpy.random.uniform(0, 2*numpy.pi, n)
r = numpy.random.uniform(2, 3.5, n)

然后,可以使用从极坐标到笛卡尔坐标的转换构建以下x、y坐标:

x = r * numpy.cos(phi)
y = r * numpy.sin(phi)

这展示了numpy的强大之处,因为x和y现在是数组,而不需要迭代n。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接