2017-12-15 145 views
7

Tôi đang cố gắng hình dung một mặt phẳng 2D cắt qua biểu đồ 3D với Numpy và Matplotlib để giải thích trực giác của các dẫn xuất từng phần.Vẽ một mặt phẳng 2D qua bề mặt 3D

Cụ thể, hàm tôi đang sử dụng là J (θ1, θ2) = θ1^2 + θ2^2 và tôi muốn vẽ một mặt phẳng θ1-J (θ1, θ2) tại θ2 = 0.

Tôi đã quản lý để vẽ một mặt phẳng 2D với mã bên dưới nhưng chồng chất của mặt phẳng 2D và đồ thị 3D không hoàn toàn đúng và mặt phẳng 2D hơi lệch, vì tôi muốn mặt phẳng trông giống như cắt 3D ở θ2 = 0.

Sẽ thật tuyệt nếu tôi có thể mượn chuyên môn của bạn về điều này, cảm ơn.

def f(theta1, theta2): 
     return theta1**2 + theta2**2 

    fig, ax = plt.subplots(figsize=(6, 6), 
          subplot_kw={'projection': '3d'}) 

    x,z = np.meshgrid(np.linspace(-1,1,100), np.linspace(0,2,100)) 
    X = x.T 
    Z = z.T 
    Y = 0 * np.ones((100, 100)) 
    ax.plot_surface(X, Y, Z) 

    r = np.linspace(-1,1,100) 
    theta1_grid, theta2_grid = np.meshgrid(r,r) 
    J_grid = f(theta1_grid, theta2_grid) 
    ax.contour3D(theta1_grid,theta2_grid,J_grid,500,cmap='binary') 

    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() 

Đây là sản phẩm hình ảnh bằng cách mã:

plot showing a parabolic surface with a vertical plane weirdly superimposed on it

+0

Đố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

+0

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 :) –

Trả lời

7

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

  1. 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à
  2. đầ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 độ:

result 1, default view; all's fine and wellresult 2; still all's fine and well

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.

Các vấn đề liên quan