Skip to content
Advertisement

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

Given the following image, where plt.Polygon was used to create the triangle and plt.contourf the contour, i would like to ‘cut’ off the regions marked in X so that i only get the contour inside the triangle. How would i do this?

I’ve tried placing NaN values in the mentioned regions but the edges are square and therefore requires a large meshgrid to generate a ‘clean’ cut between the unwanted and wanted regions. Rather is it more appropiate to use plt.tricontourf? If so how should one approach it?

enter image description here

Advertisement

Answer

Thanks @Zephyr for the tricontourf solution, Heres how i solved it without the use of tricontourf and simply a 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')

Contour Plot

Surface Plot

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement