在半球上随机分布点,不在中心聚集
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
参数在 0
到 pi
周围均匀分布,但请注意,由于您扫过 'az' 整圈,您实际上可能只有 0
到 pi/2
的 alt
分布,我将在其余的回答中这样做。
您希望在较小的环中有较少的星星,因此您不能使用从 0
到 pi/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))
这是此问题的后续问题:
我想在观察者上方随机分布星星。我在最后一个问题中能够做到这一点。
我现在遇到的问题是星星似乎聚集在中心。
我怎样才能摆脱这个?
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
参数在 0
到 pi
周围均匀分布,但请注意,由于您扫过 'az' 整圈,您实际上可能只有 0
到 pi/2
的 alt
分布,我将在其余的回答中这样做。
您希望在较小的环中有较少的星星,因此您不能使用从 0
到 pi/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))