Matplotlib 3D绘图疑问:曲面、XY平面曲线及曲面投影曲线绘制
3D绘图问题解答
需求说明
需要在同一张3D图中展示以下元素:
- 一个曲面
- XY平面内的一条曲线
- 曲面上位于该XY平面曲线正上方的路径
原始代码
import matplotlib.pyplot as plt from matplotlib import cm from matplotlib.ticker import LinearLocator import numpy as np from mpl_toolkits import mplot3d fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) X = np.linspace(-5,5,100) Y = X X, Y = np.meshgrid(X, Y) Z = 50 - X**2 - Y**2 #Plotting curve on the surface ax = plt.axes(projection='3d') yline = np.linspace(-5,5,100) xline = -np.sqrt(4/(2+yline**2)) #the x-values of the curve in the xy-plane zline = 50 - xline**2 - yline**2 ax.plot3D(xline, yline, zline, "black") surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm) ax.set_zlim(0, 50) #Plotting curve in xy-plane a = 5 g = 1 - 2*X - X*Y**2 plt.contour(X,Y,g, [a], offset=0) plt.show()
遇到的问题
- 坐标轴出现重复编号,是否因为创建meshgrid后又用ax.plot3D,重复创建了3D空间?
- 曲面上的路径显示较淡,有没有方法提升其可见性?
- 鸟瞰视角下,曲面上的路径不在XY平面曲线正上方,是否有Python内置函数可直接投影?
问题解答
1. 坐标轴重复编号问题
原因:代码重复创建了3D坐标轴对象。一开始通过fig, ax = plt.subplots(subplot_kw={"projection": "3d"})已经生成了一个3D坐标轴,后续又执行ax = plt.axes(projection='3d'),会在同一画布中新增一个3D坐标轴,导致编号重叠。
解决方法:删除第二次创建坐标轴的语句,全程使用最初生成的ax对象。
2. 曲面上路径可见性问题
解决方法:
- 加粗线条:在
ax.plot3D()中添加linewidth参数,比如linewidth=3; - 使用高对比度颜色:将线条颜色改为更醒目的色调,比如
color='crimson'; - 调整图层顺序:先绘制曲面,再绘制路径,或设置
zorder=10让路径处于图层上层; - 降低曲面透明度:在
plot_surface()中添加alpha=0.8,弱化曲面对路径的遮挡。
3. 投影路径不对应问题
原因:当前XY平面曲线是基于meshgrid用contour生成的,而曲面上的路径是参数化生成的xline/yline点集,两者的点不一一对应,导致视角错位。
解决方法:直接用曲面上路径的xline和yline生成XY平面投影,确保点完全匹配:
# 替换原contour代码,绘制对应投影 ax.plot3D(xline, yline, np.zeros_like(xline), color='blue', linewidth=2)
优化后的完整代码
import matplotlib.pyplot as plt from matplotlib import cm import numpy as np fig, ax = plt.subplots(subplot_kw={"projection": "3d"}) X = np.linspace(-5,5,100) Y = X X, Y = np.meshgrid(X, Y) Z = 50 - X**2 - Y**2 # 绘制半透明曲面 surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm, alpha=0.8) ax.set_zlim(0, 50) # 生成路径数据 yline = np.linspace(-5,5,100) xline = -np.sqrt(4/(2+yline**2)) zline = 50 - xline**2 - yline**2 # 绘制曲面上的高亮路径 ax.plot3D(xline, yline, zline, color='crimson', linewidth=3, zorder=10) # 绘制对应XY平面投影 ax.plot3D(xline, yline, np.zeros_like(xline), color='blue', linewidth=2) plt.show()
内容的提问来源于stack exchange,提问作者abstract_je
相关产品推荐
相关产品推荐

