我在 xy 平面上有一个 3D 曲面图和一个 2D 等值线图。我想创建从曲面图到计算机图的几条垂直线(理想情况下,每个轮廓一条垂直线)。
示例要求(从此处复制):
但是,我无法实现与上面类似的情节。我的虚拟最小工作示例如下,其中我添加了一条带有硬编码代码的红色垂直线,但我希望有类似的垂直线。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
# Create a quadratic surface
x = np.linspace(-3, 3, 100)
y = np.linspace(-3, 3, 100)
X, Y = np.meshgrid(x, y)
Z = X**2 + Y**2 # Quadratic surface
Z = Z + 20
# Mask a circular region (e.g., radius > 2)
mask = (X**2 + Y**2) > 4
Z_masked = np.ma.masked_where(mask, Z)
# Create plot
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# Plot the surface
surf = ax.plot_surface(X, Y, Z_masked, cmap=cm.viridis, edgecolor='none', alpha=0.8)
# Add contours on the XY plane at Z_min level
z_min = Z_masked.min() - 20
contour = ax.contour(X, Y, Z_masked, zdir='z', offset=z_min, colors='black', linewidths=1)
# Calculate the center of the valid region
valid_mask = ~Z_masked.mask
x_valid = X[valid_mask]
y_valid = Y[valid_mask]
z_valid = Z_masked[valid_mask]
# Find the approximate center
x_center = np.mean(x_valid)
y_center = np.mean(y_valid)
z_center = np.mean(z_valid)
# Plot the vertical line in red
ax.plot([x_center, x_center], [y_center, y_center], [z_min, z_center],
color='red', linewidth=2, alpha=0.9)
# Add markers for clarity
ax.scatter(x_center, y_center, z_center, color='red', s=50, label='Surface Center')
ax.scatter(x_center, y_center, z_min, color='red', s=50, label='Contour Center')
# Labels and legend
ax.set_xlabel('X-axis')
ax.set_ylabel('Y-axis')
ax.set_zlabel('Z-axis')
ax.legend()
# Show plot
plt.show()
print
轮廓对象具有属性levels和get_paths,分别列出每个等轮廓的值及其点的坐标(通过路径对象的顶点属性):
contour = ax.contour(X, Y, Z_masked, zdir='z', offset=z_min, colors='black', linewidths=1)
# Get the coordinates of one point per contour
pointsX, pointsY, pointsZ = [], [], []
for i, (level, path) in enumerate(zip(contour.levels, contour.get_paths())):
if len(path):
pointsX.append(path.vertices[5+25*i][0])
pointsY.append(path.vertices[5+25*i][1])
pointsZ = [X**2 + Y**2 + 20 for (X, Y) in zip(pointsX, pointsY)]
# Plot the points
ax.scatter(pointsX, pointsY, z_min, color='red', s=50, label='Contour Center')
ax.scatter(pointsX, pointsY, pointsZ, color='red', s=50, label='Contour Center')
# Plot the vertical line in red
for i in range(len(pointsX)):
ax.plot([pointsX[i], pointsX[i]], [pointsY[i], pointsY[i]], [z_min, pointsZ[i]],
color='red', linewidth=2, alpha=0.9)