将星星按类别均匀分布在球体上

问题描述 投票:0回答:1

我正在开发一个项目,需要将星星映射到虚拟球体上。星星彼此之间以及与球体中心 (0,0,0) 的间距必须均匀,并且亮度类别在球体表面具有特定的分布。球体的每个部分都应根据亮度按比例混合星星,确保整个球体被均匀覆盖。

方法与问题:

归一化:我首先将每颗恒星的位置归一化,通过将其位置向量缩放到固定半径来形成一个球体。

偶数点分布:我使用斐波那契球体采样在球体上生成了 1000 个均匀分布的点。

初始匹配:将每个点与最近的星星匹配效果很好,无需考虑星星亮度。

类别分布:当我尝试包含所需的恒星亮度分布时,挑战就出现了。这些类别需要球体表面的特定比率,但在按亮度分类时我很难保持均匀分布。

当前方法:我最新的尝试涉及随机打乱生成的点,然后根据星星的亮度类别将它们分配给星星。例如,每 1.9 分就属于亮度类别“8”的一颗星。然而,这种方法未能达到所需的均匀分布,特别是因为“8”类星星很少但数量足以满足分布要求。

import pandas as pd
import numpy as np
from sklearn.neighbors import NearestNeighbors

def classify_stars(vmag):
    if vmag >= 10:
        return '1'
    elif 7 <= vmag < 10:
        return '3'
    elif 6 <= vmag < 7:
        return '5'
    elif 3 <= vmag < 6:
        return '8'
    elif 1 <= vmag < 3:
        return '9'
    else:
        return '10'

def generate_sphere_points(samples=1000, radius=50):
    points = []
    dphi = np.pi * (3. - np.sqrt(5.))  # Approximation of the golden angle in radians.
    for i in range(samples):
        y = 1 - (i / float(samples - 1)) * 2  # y goes from 1 to -1
        radius = np.sqrt(1 - y * y)  # radius at y

        theta = dphi * i  # golden angle increment
        x = np.cos(theta) * radius
        z = np.sin(theta) * radius

        points.append((x * 50, y * 50, z * 50))
    return np.array(points)

df = pd.read_csv('hygdata_v3.csv', usecols=['hip', 'x', 'y', 'z', 'mag'])
df.dropna(subset=['hip', 'x', 'y', 'z', 'mag'], inplace=True)
df['hip'] = df['hip'].astype(int)
df['norm'] = np.sqrt(df['x']**2 + df['y']**2 + df['z']**2)
df['x'] = 50 * df['x'] / df['norm']
df['y'] = 50 * df['y'] / df['norm']
df['z'] = 50 * df['z'] / df['norm']
df.drop(columns='norm', inplace=True)
df['class'] = df['mag'].apply(classify_stars)

points = generate_sphere_points(samples=1000)
desired_distribution = {'1': 0.27, '3': 0.27, '5': 0.27, '8': 0.19, '9': 0, '10': 0}
total_points = len(points)

# Calculate points per category based on desired distribution
category_points = {k: int(v * total_points) for k, v in desired_distribution.items()}

# Randomly shuffle points to avoid spatial clustering in assignment
np.random.shuffle(points)

sampled_df = pd.DataFrame()
offset = 0

for category, count in category_points.items():
    if count > 0:
        category_stars = df[df['class'] == category]
        nbrs = NearestNeighbors(n_neighbors=1).fit(category_stars[['x', 'y', 'z']])
        if offset + count > len(points):
            count = len(points) - offset  # Adjust count if it exceeds the number of points
        _, indices = nbrs.kneighbors(points[offset:offset + count])
        unique_indices = np.unique(indices.flatten())
        assigned_stars = category_stars.iloc[unique_indices[:count]]
        sampled_df = pd.concat([sampled_df, assigned_stars], ignore_index=True)
        offset += count

# Output the hip values of stars with category 8 to see if they are evenly distributed
sampled_df = sampled_df.drop_duplicates(subset='hip')

category_8_stars = sampled_df[sampled_df['class'] == '8']
hip_values_category_8 = category_8_stars['hip'].astype(str).tolist()
print(hip_values_category_8)

数据集可以在这里下载:https://raw.githubusercontent.com/EnguerranVidal/HYG-STAR-MAP/main/hygdatav3.csv

就像我说的,它并没有像我想象的那样工作。 经过整整两天的尝试解决这个谜题后,我来到这里寻求专家的建议。

知道如何解决这个问题吗?

python algorithm math geometry visualization
1个回答
0
投票

泊松盘采样适用于球体并生成良好的点分布。

如果您将星星按照亮度递减/受欢迎程度增加的顺序排列,那么您可以减小光盘大小,以便在每个尺度上获得令人满意的分布。

© www.soinside.com 2019 - 2024. All rights reserved.