在半球上随机分布点,不在中心聚集

Distribute points on a half sphere randomly without clustering in the center

这是此问题的后续问题:

我想在观察者上方随机分布星星。我在最后一个问题中能够做到这一点。

我现在遇到的问题是星星似乎聚集在中心。

我怎样才能摆脱这个?

import matplotlib.pyplot as plt
import numpy as np
import  math
import ephem
from datetime import datetime
import random

home = ephem.Observer()

home.lon = '-70.4'  # +E
home.lat = '-24.62'  # +N
home.elevation = 0  # meters
home.date = datetime.utcnow()

theta_plot = []
r_plot=[]

stars_pre_selected = []

for n in range(4000):
    ra, dec = home.radec_of(az=random.uniform(0, 2 * math.pi),
                            alt=random.uniform(0, math.pi))

    body = ephem.FixedBody()
    body._epoch = ephem.J2000
    body._ra = ephem.degrees(ra)
    body._dec = ephem.degrees(dec)

    body.compute(home)


    if math.degrees(body.alt) > 0:
        stars_pre_selected.append(body)


    else:
        print(math.degrees(body.alt))


for body in stars_pre_selected:
    body.compute(home)
    theta_plot.append(body.az)
    r_plot.append(math.cos(body.alt))
    print(body.alt,body.az)

ax = plt.subplot(111, polar=True)
#
ax.set_theta_direction(-1)
ax.set_theta_offset(np.pi / 2)
ax.grid(True)
ax.scatter(theta_plot, r_plot, c='blue', s=2)
ax.set_rmax(1.0)

plt.pause(0.1)

plt.show()

更新:

    ra, dec = home.radec_of(az=random.uniform(0, 2 * math.pi),
    alt=math.asin(2*random.random()-1))
    

这也可以,但是必须将代码更改为 math.sin 而不是 math.cos :

    ra, dec = home.radec_of(az=random.uniform(0, 2 * math.pi),
    alt=math.acos(2*random.random()-1))

我猜你可以在一个正方形中生成随机位置,但是然后检查这个位置是否在圆圈内 - 放置新点。这将使您避免聚集在中心。

如果我对您的应用理解正确,这是因为靠近半球顶部的 360 度 'ring' 覆盖的面积小于球体底部的 'ring'。因此,如果每个环中的星星数量相同,它们在较小的环(图像的中心)中会显得更密集。

home.radec_of()alt 参数在 0pi 周围均匀分布,但请注意,由于您扫过 'az' 整圈,您实际上可能只有 0pi/2alt 分布,我将在其余的回答中这样做。

您希望在较小的环中有较少的星星,因此您不能使用从 0pi/2 的均匀分布。相反,您希望更接近 0(较大的环)并且减少 pi/2.

我最好的建议是查看如何在指定分布特征的 numpy 中进行随机分布。

至于分布本身,找出每个 alt 值处的环的大小,并使分布中值的数量与该大小成正比。

您回应 Peter O 的建议时说您不读 C 语言,但是虽然问题是 C 语言,但答案 与语言无关。在 Python 中,它将是

    import numpy as np
    #create random three dimension vector
    vector = np.array([np.random.normal() for _ in range(3)])
    #find length
    length = np.dot(vector,vector)
    #normalize vector
    unit_vector = np.divide(vector, length)

这将在单位球体上创建一个向量。然后您可以将其转换为方位角和高度。既然要半球,那么就取高度的绝对值即可。

ra, dec = home.radec_of(az=random.uniform(0, 2 * math.pi),
alt=math.asin(2*random.random()-1))