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

如何绘制两个无曲面衔接断层的正螺旋面?

解决Matplotlib螺旋面合并后的衔接断层问题

使用Matplotlib绘制两个正螺旋面,将它们合并为单个网格后,曲面之间出现了明显的衔接断层,同时表面颜色映射效果不佳。

效果表现:两个螺旋面衔接处存在明显的断裂缝隙,颜色过渡不自然。

原实现代码

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib import cm  # 补充原代码遗漏的颜色模块导入

u = np.linspace(-np.pi, np.pi, 200)
v = np.linspace(np.pi, -np.pi, 200)

theta = np.pi
U, V = np.meshgrid(u, v)

X = np.cos(theta)*np.sinh(V)*np.sin(U) + np.sin(theta)*np.cosh(V)*np.cos(U)
Y = -np.cos(theta)*np.sinh(V)*np.cos(U) + np.sin(theta)*np.cosh(V)*np.sin(U)
Z = U*np.cos(theta)+V*np.sin(theta)

i = -1
for j in np.linspace(0,.8, 2):
    X = np.append(X,  X[::i,:], axis = 0)
    Y = np.append(Y,  Y[::i,:], axis = 0)
    Z = np.append(Z,  Z[::i,:]+j, axis = 0)
    i *=-1
    
r_cols = (X**2 + Y**2)
r_cols /= np.max(r_cols)
r_cols = cm.jet(r_cols)

fig, ax = plt.subplots(figsize=(5,5), subplot_kw={"projection": "3d"})

ax.plot_surface(X, Y, Z, vmin=Z.min() * 2, facecolors = r_cols, rstride = 1  ,  linewidth=0 )

ax.set(xticklabels=[],
       yticklabels=[],
       zticklabels=[])
ax.view_init(elev=5, azim=40, roll=0)

plt.show()
# 补充原代码未定义的变量初始化
num = 0
fig.savefig('file{}.png'.format(num))
num +=1

尝试过的调整方法

  1. 调整u的取值范围以衔接螺旋轴:
u = np.append(np.linspace(0, -np.pi, 200), np.linspace(-np.pi, np.pi, 200))
u = np.append(u,np.linspace(np.pi,0, 200))
  1. 修改堆叠方式与Z轴的添加逻辑:
invert = -1
revert = 1
for j in np.linspace(0,.8, 2):
    X = np.append(X,  X[::invert,::revert], axis = 0)
    Y = np.append(Y,  Y[::invert,::revert], axis = 0)
    Z = np.append(Z,  Z[::invert,::revert]+j, axis = 0)
    invert *=-1
    revert *=-1

问题根源与解决方法

问题原因

  1. 网格参数不连续:原代码直接反转已有曲面的行进行拼接,导致两个曲面的U参数范围是[-pi, pi]和[pi, -pi],边界处U值不连续,plot_surface无法生成连续三角面,从而出现断层。
  2. 颜色映射逻辑冲突:基于合并后的X/Y计算颜色,反转后的曲面颜色方向与原曲面相反,导致衔接处颜色突变。

修正后的代码

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

# 第一个螺旋面参数范围
u1 = np.linspace(-np.pi, np.pi, 200)
v = np.linspace(np.pi, -np.pi, 200)
theta = np.pi

# 生成第一个螺旋面网格
U1, V = np.meshgrid(u1, v)
X1 = np.cos(theta)*np.sinh(V)*np.sin(U1) + np.sin(theta)*np.cosh(V)*np.cos(U1)
Y1 = -np.cos(theta)*np.sinh(V)*np.cos(U1) + np.sin(theta)*np.cosh(V)*np.sin(U1)
Z1 = U1*np.cos(theta) + V*np.sin(theta)

# 第二个螺旋面U参数延续第一个的范围,保证衔接连续
u2 = np.linspace(np.pi, 3*np.pi, 200)
U2, V = np.meshgrid(u2, v)
X2 = np.cos(theta)*np.sinh(V)*np.sin(U2) + np.sin(theta)*np.cosh(V)*np.cos(U2)
Y2 = -np.cos(theta)*np.sinh(V)*np.cos(U2) + np.sin(theta)*np.cosh(V)*np.sin(U2)
Z2 = U2*np.cos(theta) + V*np.sin(theta) + 0.8  # 保持原偏移量

# 合并连续网格
X = np.vstack([X1, X2])
Y = np.vstack([Y1, Y2])
Z = np.vstack([Z1, Z2])

# 计算平滑过渡的颜色映射
r_cols = (X**2 + Y**2)
r_cols /= np.max(r_cols)
r_cols = cm.jet(r_cols)

fig, ax = plt.subplots(figsize=(5,5), subplot_kw={"projection": "3d"})
ax.plot_surface(X, Y, Z, facecolors=r_cols, rstride=1, linewidth=0, antialiased=True)

ax.set(xticklabels=[], yticklabels=[], zticklabels=[])
ax.view_init(elev=5, azim=40, roll=0)

plt.show()
num = 0
fig.savefig('file{}.png'.format(num))

关键调整点

  • 连续参数范围:第二个螺旋面的U参数从pi延续到3pi,与第一个曲面的[-pi, pi]在pi处自然衔接,避免网格断裂。
  • 独立生成曲面:不再复用反转后的原曲面数据,重新计算第二个曲面的所有坐标,保证网格方向一致。
  • 平滑颜色过渡:基于合并后的完整网格计算颜色,确保衔接处颜色连续。

内容的提问来源于stack exchange,提问作者Matthew.MC

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 20:40:52