如何基于2D输入间距绘制带颜色的3D函数及排障
问题与解决方案
需求描述
定义三个数组:
v1=np.linspace(1,100) v2=np.linspace(1,100) v3=np.linspace(1,100)
有函数 f = (v1 + v2*10)/v3,需要实现两个目标:
- 在以v1、v2、v3为坐标轴的3D图中绘制该函数,根据函数值为曲面/点集着色;
- 用嵌套循环遍历输入向量的所有值,逐点构建函数(之前尝试循环时报错)。
此外,尝试了一段代码绘制3D曲面,但最终只显示线条,代码如下:
import mpl_toolkits.mplot3d.axes3d as axes3d import sympy from sympy import symbols, Function # Parameters I use in the function L = 132 alpha = 45*math.pi/180 beta = 0 s,t = symbols('s,t') z = Function('z')(s,t) figure = plt.figure(figsize=(8,8)) ax = figure.add_subplot(1, 1, 1, projection='3d') # experiment with various range of data in x and y x1 = np.linspace(-40,-40,100) y1 = np.linspace(-40,40,100) x,y = np.meshgrid(x1,y1) # My function Z c1=math.cos(beta)**2 c2=math.cos(alpha)**2 s1=math.sin(alpha)**2 den = math.sqrt((c1*c2)+s1) z=L*((math.cos(beta)/den)-1)+(s*(math.sin(alpha)))+(t*(1-math.cos(alpha))) ax.plot_surface(x,y,z,cmap='rainbow') ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z') plt.show()
问题代码分析
这段代码存在两个核心问题:
x1 = np.linspace(-40,-40,100)生成的是全为-40的数组,meshgrid后x是无变化的100x100矩阵,x轴没有跨度,自然只能画出线条;- 错误混用SymPy符号变量与NumPy数值数组:s、t是SymPy符号,未替换为x、y的数值,导致z是符号表达式而非数值矩阵,
plot_surface无法识别。
正确实现方法
1. 3D曲面绘图的最佳方式
无需使用SymPy,直接用NumPy数值计算结合Matplotlib的3D绘图即可,核心是生成有跨度的网格矩阵,确保所有运算为数值运算。
修正你尝试的代码(实现曲面绘制)
import numpy as np import matplotlib.pyplot as plt import math # 参数定义 L = 132 alpha = 45 * math.pi / 180 beta = 0 # 生成有跨度的x、y轴线性空间 x1 = np.linspace(-40, 40, 100) y1 = np.linspace(-40, 40, 100) x, y = np.meshgrid(x1, y1) # 计算z的数值矩阵(直接用x、y替代符号变量) c1 = math.cos(beta)**2 c2 = math.cos(alpha)**2 s1 = math.sin(alpha)**2 den = math.sqrt((c1 * c2) + s1) z = L * ((math.cos(beta)/den) - 1) + (x * math.sin(alpha)) + (y * (1 - math.cos(alpha))) # 绘制3D曲面 figure = plt.figure(figsize=(8,8)) ax = figure.add_subplot(1, 1, 1, projection='3d') ax.plot_surface(x, y, z, cmap='rainbow') ax.set_xlabel('x') ax.set_ylabel('y') ax.set_zlabel('z') plt.show()
针对初始函数 f=(v1+v2*10)/v3 的3D可视化
如果要以v1、v2、v3为坐标轴,用f值着色,可以绘制三维散点图:
import numpy as np import matplotlib.pyplot as plt # 生成三个轴的取值数组 v1 = np.linspace(1, 100, 20) v2 = np.linspace(1, 100, 20) v3 = np.linspace(1, 100, 20) # 构建三维网格 x, y, z = np.meshgrid(v1, v2, v3) # 计算函数值 f = (x + y*10)/z # 绘制带颜色映射的三维散点图 fig = plt.figure(figsize=(10,8)) ax = fig.add_subplot(111, projection='3d') scatter = ax.scatter(x, y, z, c=f, cmap='rainbow') ax.set_xlabel('v1') ax.set_ylabel('v2') ax.set_zlabel('v3') plt.colorbar(scatter, label='f=(v1+v2*10)/v3') plt.show()
2. 嵌套循环逐点构建函数
如果不想用NumPy的向量化运算,可用嵌套循环逐点计算函数值,核心是初始化对应维度的结果数组,再遍历索引计算。
三维网格逐点计算
import numpy as np import matplotlib.pyplot as plt v1 = np.linspace(1, 100, 20) v2 = np.linspace(1, 100, 20) v3 = np.linspace(1, 100, 20) # 初始化与三维网格同维度的结果数组 f_values = np.zeros((len(v1), len(v2), len(v3))) # 三层嵌套循环遍历所有组合 for i in range(len(v1)): for j in range(len(v2)): for k in range(len(v3)): f_values[i,j,k] = (v1[i] + v2[j]*10)/v3[k] # 可视化结果 fig = plt.figure(figsize=(10,8)) ax = fig.add_subplot(111, projection='3d') x, y, z = np.meshgrid(v1, v2, v3) scatter = ax.scatter(x, y, z, c=f_values.flatten(), cmap='rainbow') ax.set_xlabel('v1') ax.set_ylabel('v2') ax.set_zlabel('v3') plt.colorbar(scatter, label='f=(v1+v2*10)/v3') plt.show()
二维曲面逐点计算(固定v3值)
import numpy as np import matplotlib.pyplot as plt v1 = np.linspace(1, 100, 100) v2 = np.linspace(1, 100, 100) v3 = 50 # 固定v3的取值 # 初始化二维结果数组 z_values = np.zeros((len(v1), len(v2))) # 两层嵌套循环计算每个点的函数值 for i in range(len(v1)): for j in range(len(v2)): z_values[i,j] = (v1[i] + v2[j]*10)/v3 # 绘制3D曲面 fig = plt.figure(figsize=(8,8)) ax = fig.add_subplot(111, projection='3d') x, y = np.meshgrid(v1, v2) ax.plot_surface(x, y, z_values, cmap='rainbow') ax.set_xlabel('v1') ax.set_ylabel('v2') ax.set_zlabel('f=(v1+v2*10)/v3') plt.show()
内容的提问来源于stack exchange,提问作者stefano massardi
相关产品推荐
相关产品推荐

