具有对角轴正交风格的 3D 绘图

问题描述 投票:0回答:1

我想按照我们在学校绘制情节的风格来绘制情节。这是一个例子:

总结:

  • 3D 绘图
  • y-z 平面与屏幕平行(水平 y,垂直 z)
  • x 轴是对角线

Y-Z 轴与屏幕平行(水平 y,垂直 z。通常 X 轴现在指向屏幕。但我想更改它,使其对角向下(就像将其绘制在一张纸上一样)有时是纸张)。不幸的是,我不知道这个投影是如何命名的(倾斜图像),但我很确定它是正交的,并且我需要某种额外的投影。

我已经尝试过使用轴的自定义投影,如下所示:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d', proj_type='ortho')

# Some sample data
x, y, z = np.random.rand(3, 100)
ax.scatter(x, y, z)

# Apply the transformation
ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), transform)

# Set labels and view
ax.view_init(elev=0, azim=0)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

# Manual transformation matrix
c = np.cos(np.deg2rad(30))
s = np.sin(np.deg2rad(30))
transform = np.array([
[1,  0,  0, 0],
[0,  c, -s, 0],
[0,  s,  c, 0],
[0,  0,  0, 1]
])

# Apply the transformation
ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), transform)

plt.show()

这是我的结果(到目前为止还不是很令人印象深刻:)

我怎样才能使它看起来像立方体?

python matplotlib projection diagonal matplotlib-3d
1个回答
0
投票

输出示例

解决方案

您正在寻找的投影是斜骑士投影的修改版本。在典型的骑士投影中,xy 平面平行于屏幕,z 轴是对角线,正方向指向屏幕外。该投影的变换矩阵可以在这个维基百科页面上找到,更多信息可以在这些讲义中找到。

听起来您希望 x 轴对角指向屏幕,yz 平面平行于屏幕。只要更改

transform
矩阵,您的代码就可以实现。当
alpha
为对角线角度时,正确的变换矩阵为:

左上角的 -1 翻转对角线 x 轴。尝试使用

cos()
sin()
项上的负号将向您展示如何操作图表。

代码

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d', proj_type='ortho')

# Some sample data
x = [0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1]
y = [0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1]
z = [0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1]

# display data
ax.scatter(x, y, z)
ax.plot(x, y, z)

# set angle of the diagonal (63.4 = arctan(2))
alpha = 63.4 

# Set labels and view and lims
ax.view_init(elev=alpha, azim=(90-alpha))
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

ax.set_xlim(-0.5,1.5)
ax.set_ylim(-0.5,1.5)
ax.set_zlim(-0.5,1.5)

# Manual transformation matrix
c = np.cos(np.deg2rad(alpha))
s = np.sin(np.deg2rad(alpha))
transform = np.array([
[-1, 0,  0, 0],
[0,  1,  0, 0],
[-c, s,  1, 0],
[0,  0,  0, 1]
])

# Apply the transformation
ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), transform)
ax.set_aspect('equal')
plt.show()
© www.soinside.com 2019 - 2024. All rights reserved.