如何在Matplotlib中将渐变/均匀方管的3D线图转为曲面图?
3D方形管道曲面绘制解决方案
原问题与代码
我尝试用Matplotlib绘制两个3D图:一个渐变方形管,一个均匀方形管。从Excel导入X、Y值,生成每个方形截面的X、Y、Z坐标列表,代码如下:
from mpl_toolkits import mplot3d import pandas as pd import matplotlib.pyplot as plt import numpy as np df = pd.read_excel(r'H:\Hrishikesh1\lidar_excel_data.xlsx') # 最下方方形截面的X坐标列表 x1 = list(df["X_square"]) # 最下方方形截面的Y坐标列表 y1 = list(df["Y_square"]) # Z坐标序列 z1 = np.linspace(0, 10, num=22) # 存储渐变管道所有坐标的列表 x_sqt=[] y_sqt=[] z_sqt=[] # 存储均匀管道所有坐标的列表 x_sqs=[] y_sqs=[] z_sqs=[] # 基于第一个方形的XY坐标生成每个渐变截面的XYZ坐标 for i in z1 : for j in x1 : x_sqt.append((((1.5*10-i))/(1.5*10))*j) z_sqt.append(i) for k in y1 : y_sqt.append((((1.5*10-i))/(1.5*10))*k) # 基于第一个方形的XY坐标生成每个均匀截面的XYZ坐标 for i in z1 : for j in x1 : x_sqs.append(j) z_sqs.append(i) for k in y1 : y_sqs.append(k) fig = plt.figure(figsize=plt.figaspect(0.5)) ax = fig.add_subplot(1, 2, 1, projection='3d') x1 = x_sqt y1 = y_sqt z1 = z_sqt # 绘图 ax.plot3D(x1, y1, z1, 'red') ax.set_title('渐变管') ax = fig.add_subplot(1, 2, 2, projection='3d') x2 = x_sqs y2 = y_sqs z2 = z_sqs ax.plot3D(x2, y2, z2, 'green') ax.set_title('均匀管') plt.show()
当前问题
目前生成的图是堆叠的独立方形,且相邻方形的起点相互连接,无法呈现管道侧边的曲面立体感。
解决方案:绘制曲面而非折线
要实现曲面效果,需要将每个截面的对应顶点连接,生成网格数据后使用plot_surface绘制曲面。以下是修改后的代码:
from mpl_toolkits import mplot3d import pandas as pd import matplotlib.pyplot as plt import numpy as np # 读取Excel数据 df = pd.read_excel(r'H:\Hrishikesh1\lidar_excel_data.xlsx') x1 = np.array(df["X_square"]) y1 = np.array(df["Y_square"]) z_values = np.linspace(0, 10, num=22) # ---------------------- 处理渐变管道 ---------------------- # 生成每个Z层的缩放后XY坐标 x_taper = [] y_taper = [] for z in z_values: scale = (15 - z)/15 # 简化1.5*10的计算 x_taper.append(x1 * scale) y_taper.append(y1 * scale) x_taper = np.array(x_taper) y_taper = np.array(y_taper) z_taper = np.tile(z_values[:, np.newaxis], (1, len(x1))) # ---------------------- 处理均匀管道 ---------------------- x_straight = np.tile(x1, (len(z_values), 1)) y_straight = np.tile(y1, (len(z_values), 1)) z_straight = np.tile(z_values[:, np.newaxis], (1, len(x1))) # ---------------------- 绘图 ---------------------- fig = plt.figure(figsize=plt.figaspect(0.5)) # 渐变管子图 ax1 = fig.add_subplot(1, 2, 1, projection='3d') # 绘制每个侧边曲面 for i in range(len(x1)): # 连接当前顶点和下一个顶点(实现方形闭合) next_i = (i + 1) % len(x1) # 构建曲面网格 x_surf = np.array([x_taper[:, i], x_taper[:, next_i]]) y_surf = np.array([y_taper[:, i], y_taper[:, next_i]]) z_surf = np.array([z_taper[:, i], z_taper[:, next_i]]) ax1.plot_surface(x_surf, y_surf, z_surf, color='red', alpha=0.6) ax1.set_title('渐变方形管') ax1.set_xlabel('X') ax1.set_ylabel('Y') ax1.set_zlabel('Z') # 均匀管子图 ax2 = fig.add_subplot(1, 2, 2, projection='3d') for i in range(len(x1)): next_i = (i + 1) % len(x1) x_surf = np.array([x_straight[:, i], x_straight[:, next_i]]) y_surf = np.array([y_straight[:, i], y_straight[:, next_i]]) z_surf = np.array([z_straight[:, i], z_straight[:, next_i]]) ax2.plot_surface(x_surf, y_surf, z_surf, color='green', alpha=0.6) ax2.set_title('均匀方形管') ax2.set_xlabel('X') ax2.set_ylabel('Y') ax2.set_zlabel('Z') plt.tight_layout() plt.show()
关键说明
- 数据结构调整:将原有的一维列表改为二维数组,每行对应一个Z层的截面坐标,方便构建曲面网格。
- 曲面构建:遍历方形的每个顶点,将相邻顶点在不同Z层的坐标连接,形成矩形曲面片,通过
plot_surface绘制。 - 闭合处理:使用
(i + 1) % len(x1)实现方形顶点的循环闭合,确保最后一个顶点和第一个顶点连接成完整侧边。 - 透明度设置:通过
alpha=0.6让曲面半透明,增强立体感,避免遮挡内部结构。
内容的提问来源于stack exchange,提问作者Hrishi Chougule
相关产品推荐
相关产品推荐

