如何用Python Matplotlib闭合半圆柱曲面及顶点弧绘制圆柱?
半圆柱曲面闭合及顶点边绘制方法
问题
- 绘制的半圆柱曲面未闭合,如何实现曲面完全闭合?
- 能否通过顶点和边来绘制圆柱,让两个顶点之间形成一段弧?
一、实现半圆柱曲面闭合
你当前的代码里,theta只取了0到π的区间,且首尾点不重合,同时缺少半圆柱的两个端面,导致曲面呈开放状态。要实现闭合,需要两步操作:
- 让曲面的弧边首尾重合;
- 添加半圆柱的两个半圆端面。
修改后的完整代码:
from matplotlib import pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection import numpy as np def data_for_cylinder_along_z(center_x,center_y,radius,height_z): z = np.linspace(0, height_z, 50) # 重复起点,让弧边首尾闭合 theta = np.linspace(0, np.pi, 50) theta = np.append(theta, theta[0]) theta_grid, z_grid=np.meshgrid(theta, z) x_grid = radius*np.cos(theta_grid) + center_x y_grid = radius*np.sin(theta_grid) + center_y return x_grid,y_grid,z_grid fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # 绘制半圆柱曲面 center_x, center_y = 0.2, 0.2 radius = 0.05 height_z = 0.1 Xc,Yc,Zc = data_for_cylinder_along_z(center_x,center_y,radius,height_z) ax.plot_surface(Xc, Yc, Zc, alpha=0.5) # 生成并添加两个半圆端面 theta_end = np.linspace(0, np.pi, 50) x_end = radius*np.cos(theta_end) + center_x y_end = radius*np.sin(theta_end) + center_y # z=0处的端面 end1 = np.column_stack((x_end, y_end, np.zeros_like(x_end))) # z=height_z处的端面 end2 = np.column_stack((x_end, y_end, np.full_like(x_end, height_z))) ax.add_collection3d(Poly3DCollection([end1], alpha=0.5, facecolor='blue')) ax.add_collection3d(Poly3DCollection([end2], alpha=0.5, facecolor='blue')) ax.set_title("Closed Half Cylinder") plt.show()
二、通过顶点和边绘制带弧段的圆柱
完全可以手动通过顶点和边构建半圆柱。你可以自定义弧的顶点坐标,再用Poly3DCollection绘制曲面,或用Line3DCollection绘制边缘线条,示例代码如下:
from matplotlib import pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection import numpy as np fig = plt.figure() ax = fig.add_subplot(111, projection='3d') center_x, center_y = 0.2, 0.2 radius = 0.05 height_z = 0.1 # 定义半圆弧的顶点 theta = np.linspace(0, np.pi, 50) x_arc = radius*np.cos(theta) + center_x y_arc = radius*np.sin(theta) + center_y # 生成上下两个弧的z坐标 z0 = np.zeros_like(x_arc) z1 = np.full_like(x_arc, height_z) # 构建曲面的小四边形顶点 surface_verts = [] for i in range(len(theta)-1): verts = [ (x_arc[i], y_arc[i], z0[i]), (x_arc[i+1], y_arc[i+1], z0[i+1]), (x_arc[i+1], y_arc[i+1], z1[i+1]), (x_arc[i], y_arc[i], z1[i]) ] surface_verts.append(verts) # 添加半圆柱曲面 ax.add_collection3d(Poly3DCollection(surface_verts, alpha=0.5, facecolor='cyan')) # 添加边缘线条(可选) edges = [] # 上下弧的分段边 for i in range(len(theta)-1): edges.append([(x_arc[i], y_arc[i], z0[i]), (x_arc[i+1], y_arc[i+1], z0[i+1])]) edges.append([(x_arc[i], y_arc[i], z1[i]), (x_arc[i+1], y_arc[i+1], z1[i+1])]) # 两端的竖直边 edges.append([(x_arc[0], y_arc[0], z0[0]), (x_arc[0], y_arc[0], z1[0])]) edges.append([(x_arc[-1], y_arc[-1], z0[-1]), (x_arc[-1], y_arc[-1], z1[-1])]) ax.add_collection3d(Line3DCollection(edges, color='black', linewidths=0.5)) ax.set_title("Half Cylinder via Vertices & Edges") plt.show()
你可以通过调整theta的采样数量,控制弧段的平滑程度。
内容的提问来源于stack exchange,提问作者Freya the Goddess
相关产品推荐
相关产品推荐

