斐波那契球面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])
你的代码存在两处关键错误:
- 坐标映射完全颠倒:把极角
theta当成经度传给vertices_lon,却未将方位角phi对应到正确参数; - 多余的弧度转换:
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ță
相关产品推荐
相关产品推荐

