You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

斐波那契球面Delaunay三角化结果异常原因排查

问题描述

用Fibonacci sphere算法生成单位球面上的(x,y,z)坐标,3D散点图显示正常。尝试通过stripy库的Delaunay三角化将点连接成边,结果出现异常:两个半球区域三角化正常,但中间区域沿某一平面皱缩,呈现类似核桃/大脑的形状。

坐标转换(笛卡尔转球面)代码:

r = float(sqrt(x * x + y * y + z * z))
theta = float(acos(z / r))  # 注释标注转角度,但实际计算结果为弧度
phi = float(atan2(y, x))
return r, theta, phi

得到(n,3)的球面坐标数组后,丢弃半径得到(n,2)数组,再转弧度构建三角化:

vertices_lon = np.radians(vertices_spherical.T[0])
vertices_lat = np.radians(vertices_spherical.T[1])

spherical_triangulation = stripy.sTriangulation(lons=vertices_lon, lats=vertices_lat, permute=True)

# 构建图结构
graph: List[Node] = []
for i in range(spherical_triangulation.npoints):
    node = Node(name=f'{vertices_spherical.T[0][i]}, {vertices_spherical.T[1][i]}',
                lon=spherical_triangulation.lons[i],
                lat=spherical_triangulation.lats[i])
    graph.append(node)

segs = spherical_triangulation.identify_segments()

for s1, s2 in segs:
    graph[s1].add_neighbor(graph[s2])

return graph

(Node是包含名称、lon、lat和邻居属性的简单类)


问题原因及解决办法

核心问题:球面坐标定义与stripy库要求不匹配

stripy的sTriangulation对输入坐标有明确要求:

  • lons对应方位角φ(绕z轴的角度,范围[-π, π])
  • lats对应纬度(极角的补角,即90°-θ,范围[-π/2, π/2])

你的代码存在两处关键错误:

  1. 坐标映射完全颠倒:把极角theta当成经度传给vertices_lon,却未将方位角phi对应到正确参数;
  2. 多余的弧度转换:acos和atan2返回的本身就是弧度值,再次调用np.radians()会将数值极小化,直接导致球面坐标错乱,引发中间区域皱缩。

修正步骤

1. 纠正坐标转换逻辑

调整笛卡尔坐标到stripy适配的球面坐标的映射关系:

def cartesian_to_stripy_spherical(x, y, z):
    theta = np.arccos(z / np.sqrt(x**2 + y**2 + z**2))  # 极角(弧度)
    phi = np.arctan2(y, x)                              # 方位角(弧度)
    # 转换为stripy要求的lon(方位角phi)和lat(π/2 - 极角theta)
    lon = phi
    lat = np.pi/2 - theta
    return lon, lat

2. 重构三角化代码

去掉多余的弧度转换,用正确的坐标构建三角化:

# 生成适配stripy的坐标数组
lons = []
lats = []
for x, y, z in fibonacci_points:
    lon, lat = cartesian_to_stripy_spherical(x, y, z)
    lons.append(lon)
    lats.append(lat)
lons = np.array(lons)
lats = np.array(lats)

# 构建球面三角化
spherical_triangulation = stripy.sTriangulation(lons=lons, lats=lats, permute=True)

# 后续图结构构建代码保持不变

3. 修正笛卡尔坐标转回逻辑

确保绘图时用正确的球面坐标逆向转换:

def stripy_spherical_to_cartesian(lon, lat):
    theta = np.pi/2 - lat  # 从纬度转回极角
    phi = lon
    x = np.sin(theta) * np.cos(phi)
    y = np.sin(theta) * np.sin(phi)
    z = np.cos(theta)
    return x, y, z

其他可能性排除

  • Fibonacci sphere点集是均匀分布的,不存在非周期性导致的三角化异常;
  • stripy的球面Delaunay三角化对均匀点集支持良好,只要坐标定义正确就不会有固有局限。

内容的提问来源于stack exchange,提问作者Andrei Miculiță

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 15:27:37