绘制三角形 contour/surface matplotlib python: tricontourf/meshgrid

Plot a triangle contour/surface matplotlib python: tricontourf/meshgrid

鉴于下图,其中 plt.Polygon 用于创建三角形和 plt.contourf 轮廓,我想 'cut' 关闭 X 中标记的区域,以便我只得到三角形内的轮廓。我该怎么做?

我试过在上述区域放置 NaN 值,但边缘是方形的,因此需要一个大的网格在不需要的区域和想要的区域之间生成 'clean' 切割。而是使用 plt.tricontourf 更合适?如果是这样,应该如何处理它?

您可以使用 matplotlib.pyplot.tricontourf 来完成,但这取决于您存储数据的方式。
你应该有 4 个数组:

  • x 数组 (1, N) x 坐标
  • y 数组 (1, N) y 坐标
  • z 数组 (1, N) 具有 z 值
  • triangles xy 点的索引列表,它们是裁剪三角形的顶点
x = np.asarray([8, 10, 8, 14, 9, 11, 13, 10, 12, 11])
y = np.asarray([2, 2, 2, 2, 2.56666667, 2.56666667, 2.56666667, 3.13333333, 3.13333333, 3.7])
z = np.cos(2.5*x*x)*np.cos(1.5*y*x)
triangles = [[0, 3, 9]]

然后您可以执行三角测量:

triang = mtri.Triangulation(x, y, triangles)

完整代码

import matplotlib.pyplot as plt
import matplotlib.tri as mtri
import numpy as np


x = np.asarray([8, 10, 8, 14, 9, 11, 13, 10, 12, 11])
y = np.asarray([2, 2, 2, 2, 2.56666667, 2.56666667, 2.56666667, 3.13333333, 3.13333333, 3.7])
z = np.cos(2.5*x*x)*np.cos(1.5*y*x)
triangles = [[0, 3, 9]]

triang = mtri.Triangulation(x, y, triangles)


fig, ax = plt.subplots()

t = ax.tricontourf(triang, z)
plt.colorbar(t)

plt.show()

如果您的数据不是这种形状,您应该重新调整数组以获得上述 xyz,并计算 triangles 索引列表。如果您需要帮助,请提供您的数据。

感谢@Zephyr 提供的 tricontourf 解决方案,下面是我如何在不使用 tricontourf 的情况下解决它,只是一个 meshgrid

# =============== Define Points =============== #
left_point = np.array([8, 1])
top_point = np.array([10.75, 3.75])
right_point = np.array([13.5, 1])

# =============== Define Left Line Eq: y = mx+c =============== #
left_m = (top_point[-1] - left_point[-1]) / (top_point[0] - left_point[0])
left_c = left_point[-1] - left_m*left_point[0]
# =============== Define Right Line Eq: y = mx+c =============== #
right_m = (right_point[-1] - top_point[-1]) / (right_point[0] - top_point[0])
right_c = right_point[-1] - right_m*right_point[0]

# =============== Generate Spaced Points on Both Lines =============== #
n_points = 100

# x-coordinates on left line
X_left = np.linspace(left_point[0], top_point[0], n_points)
# y-coordinates on left line
Y_left = left_m * X_left + left_c

# x-coordinates on right line
X_right = np.linspace(right_point[0], top_point[0], n_points)
# y-coordinates on right line
Y_right = right_m * X_right + right_c

# Concatenate Left line X and Right line X: [X_left, X_right]
LR_X = np.hstack([X_left[:, None], X_right[:, None]])


# =============== Generate Spaced Points IN BETWEEN points on both lines =============== #

"""
# We can use lists to generate points between each adjacent points on the left/right line
# Then turn them into arrays
# NOTE: Y_left and Y_right are essentially equal so we could just use one of them

# XX = []
# YY = []
# for ii in range(n_points):
#     XX.append(np.linspace(LR_X[ii, 0], LR_X[ii, 1], n_points).reshape(1, -1))
#     YY.append(Y_left[ii]*np.ones(n_points).reshape(1, -1))
# XX = np.vstack(XX)
# YY = np.vstack(YY)

"""

# Or We could do this (Same thing)
XX = np.meshgrid(np.linspace(LR_X[:, 0], LR_X[:, 1], n_points))[0].reshape(n_points, n_points).T
YY = np.meshgrid([Y_left*np.ones(n_points)]*n_points)[0].reshape(n_points, n_points).T

# Im using a model to predict each point, so i had to flatten it out first
# i.e. XX.shape = (100, 100); YY.shape = (100, 100), WW.shape = (100*100, 2)
WW = np.c_[XX.ravel(), YY.ravel()]
ZZ = model.predict(WW).reshape(XX.shape)

# =============== Contour/Surface Plots =============== #
# Contour plot
fig1 = plt.figure(1, figsize=(8, 6))
ax1 = fig1.add_subplot(111)
levels = np.arange(Y.min(), Y.max())
contour_map = ax1.contourf(XX, YY, ZZ, cmap='viridis')
contour = ax1.contour(XX, YY, ZZ)
cbar = fig1.colorbar(contour_map, )

# Surface Plot
fig2 = plt.figure(2, figsize=(10, 6))
ax2 = fig2.add_subplot(projection='3d')
ax2.plot_surface(XX, YY, ZZ, cmap='viridis')