Như @ImportanceOfBeingErnest noted in a comment, mã của bạn là tốt nhưng matplotlib có một động cơ 2d, 3d lô để dễ dàng hiển thị hiện vật kỳ lạ. Đặc biệt, các đối tượng được hiển thị một lần, vì vậy hai đối tượng 3D thường hoàn toàn ở phía trước hoặc hoàn toàn phía sau nhau, làm cho hình ảnh của các đối tượng 3D lồng vào nhau gần như không thể sử dụng matplotlib.
Đề xuất thay thế cá nhân của tôi sẽ là mayavi (tính linh hoạt và trực quan đáng kinh ngạc, đường cong học tập khá dốc), tuy nhiên tôi muốn hiển thị một mẹo mà vấn đề thường có thể bị xóa hoàn toàn. Ý tưởng là để biến hai đối tượng độc lập của bạn thành một vật duy nhất bằng cách sử dụng cầu nối vô hình giữa các bề mặt của bạn. nhược điểm có thể có của phương pháp này là rằng
- bạn cần phải vẽ cả các bề mặt như các bề mặt chứ không phải là một
contour3D
, và
- đầu ra chủ yếu dựa vào sự minh bạch, vì vậy bạn cần một phụ trợ có thể xử lý đó.
Tuyên bố từ chối trách nhiệm: Tôi đã học được mẹo này từ người đóng góp cho chủ đề matplotlib của now-defunct Stack Overflow Documentation project, nhưng rất tiếc là tôi không nhớ người dùng đó là ai.
Để sử dụng thủ thuật này cho trường hợp sử dụng của bạn, về cơ bản, chúng tôi phải chuyển cuộc gọi đó contour3D
sang một số khác plot_surface
. Tôi không nghĩ rằng đây là tổng thể xấu; bạn có lẽ cần phải xem xét lại mật độ của mặt phẳng cắt của bạn nếu bạn thấy rằng con số kết quả có quá nhiều khuôn mặt để sử dụng tương tác. Chúng tôi cũng phải xác định rõ ràng một bản đồ theo từng điểm, kênh alpha trong đó đóng góp cầu trong suốt giữa hai bề mặt của bạn. Vì chúng ta cần phải ghép hai mặt với nhau, ít nhất một kích thước "trong mặt phẳng" của các bề mặt phải khớp; trong trường hợp này, tôi đảm bảo rằng các điểm dọc theo "y" giống nhau trong hai trường hợp.
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def f(theta1, theta2):
return theta1**2 + theta2**2
fig, ax = plt.subplots(figsize=(6, 6),
subplot_kw={'projection': '3d'})
# plane data: X, Y, Z, C (first three shaped (nx,ny), last one shaped (nx,ny,4))
x,z = np.meshgrid(np.linspace(-1,1,100), np.linspace(0,2,100)) # <-- you can probably reduce these sizes
X = x.T
Z = z.T
Y = 0 * np.ones((100, 100))
# colormap for the plane: need shape (nx,ny,4) for RGBA values
C = np.full(X.shape + (4,), [0,0,0.5,1]) # dark blue plane, fully opaque
# surface data: theta1_grid, theta2_grid, J_grid, CJ (shaped (nx',ny) or (nx',ny,4))
r = np.linspace(-1,1,X.shape[1]) # <-- we are going to stitch the surface along the y dimension, sizes have to match
theta1_grid, theta2_grid = np.meshgrid(r,r)
J_grid = f(theta1_grid, theta2_grid)
# colormap for the surface; scale data to between 0 and 1 for scaling
CJ = plt.get_cmap('binary')((J_grid - J_grid.min())/J_grid.ptp())
# construct a common dataset with an invisible bridge, shape (2,ny) or (2,ny,4)
X_bridge = np.vstack([X[-1,:],theta1_grid[0,:]])
Y_bridge = np.vstack([Y[-1,:],theta2_grid[0,:]])
Z_bridge = np.vstack([Z[-1,:],J_grid[0,:]])
C_bridge = np.full(Z_bridge.shape + (4,), [1,1,1,0]) # 0 opacity == transparent; probably needs a backend that supports transparency!
# join the datasets
X_surf = np.vstack([X,X_bridge,theta1_grid])
Y_surf = np.vstack([Y,Y_bridge,theta2_grid])
Z_surf = np.vstack([Z,Z_bridge,J_grid])
C_surf = np.vstack([C,C_bridge,CJ])
# plot the joint datasets as a single surface, pass colors explicitly, set strides to 1
ax.plot_surface(X_surf, Y_surf, Z_surf, facecolors=C_surf, rstride=1, cstride=1)
ax.set_xlabel(r'$\theta_1$',fontsize='large')
ax.set_ylabel(r'$\theta_2$',fontsize='large')
ax.set_zlabel(r'$J(\theta_1,\theta_2)$',fontsize='large')
ax.set_title(r'Fig.2 $J(\theta_1,\theta_2)=(\theta_1^2+\theta_2^2)$',fontsize='x-large')
plt.tight_layout()
plt.show()
Kết quả từ hai góc độ:
Như bạn có thể thấy, kết quả là khá tốt. Bạn có thể bắt đầu chơi xung quanh với các vật trong suốt của các bề mặt của bạn để xem bạn có thể làm cho mặt cắt đó hiển thị rõ hơn không. Bạn cũng có thể chuyển đổi độ mờ của cây cầu thành 1 để xem các bề mặt của bạn thực sự được khâu lại như thế nào.Tất cả trong tất cả những gì chúng tôi phải làm là lấy dữ liệu hiện có của bạn, đảm bảo kích thước của chúng phù hợp và xác định các hình lục giác rõ ràng và cầu nối phụ giữa các bề mặt.
Đối với mặt phẳng 2D bị tắt: Điều này chỉ trông giống như vậy. Nó được sở hữu một cách chính xác. Đối với cốt truyện 3D: Đây sẽ là một trong những trường hợp thông thường của [cốt truyện 3D của tôi không nhìn đúng ở các góc nhìn nhất định] (https://matplotlib.org/mpl_toolkits/mplot3d/faq.html#my-3d-plot -doesn-t-look-right-at-nhất định-xem-góc). – ImportanceOfBeingErnest
Tôi thấy, thực sự tôi đã đi qua các ý kiến trên Matplotlib không thực sự là một sự lựa chọn tối ưu cho âm mưu 3D. Tôi sẽ khám phá một số tùy chọn khác như Plotly. Cảm ơn bạn :) –