使用低于零的“负”Z 轴构建 3D 绘图

问题描述

我们正在开展一个要构建 3D 绘图的项目。 Python 是我们的主要语言,因此自然选择使用 matplotlib 作为我们的绘图库。各种教程(hereherehere)教我们如何使用 matplotlib 的 mplot3d 功能执行 3D 绘图。因此,各种 StackOverflow 答案帮助我们将每个轴的原点移动到不同的位置(herehere)。

然而,在搜索了几个小时之后,我们很难找到下一个问题的答案。我们希望 Z 轴有正负两面(见下图,橙色部分)。这意味着 Z>0 的数据点高于原点,而 Z

Example

在社区的大力帮助下,我们找到了一个展示我想要的东西的最小示例。我使用的代码是:

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

fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')

# Some settings
sn = 2   #limits in x,y,z
n = 50   #number of sample points
x1,x2 = 0,sn
y1,y2 = 0,sn
z1,z2 = -sn,sn

# Data for points
xs = (x2 - x1)*np.random.rand(n) + x1
ys = (y2 - y1)*np.random.rand(n) + y1
zs = (z2 - z1)*np.random.rand(n) + z1

# Points with z >= 0,plotted in green
ax.scatter(xs[zs>=0],ys[zs>=0],zs[zs>=0],color='green')
# Points with z < 0,plotted in red
ax.scatter(xs[zs<0],ys[zs<0],zs[zs<0],color='red')

# Data for plotting plane x|y|z=0 within the domain
tmp = np.linspace(0,sn,8)
x,y = np.meshgrid(tmp,tmp)
z = 0*x

# Plot grid lines
ax.plot([0,sn],[0,0],color='black')
ax.plot([0,[-sn,color='black')

# Maximum tick labels for X,Y,and Z (x3)
ax.plot([sn,[-.05,.02],[sn,color='black')
ax.plot([-.05,-sn],color='black')

# Label texts
ax.text(sn/2,-.2*sn,'xlabel','x',ha='center')
ax.text(0,sn/2,'ylabel','y',ha='center')
ax.text(-.1*sn,'zlabel','z',ha='center')

# Maximum limit text for X,Y and Z (x3)
ax.text(sn,-.1*sn,f'{sn}',ha='center')
ax.text(-.05*sn,-.05*sn,'0',ha='right')
ax.text(-.05*sn,-sn,f'{-sn}',ha='center')

# Set limits of the 3D display
ax.set_xlim3d([-sn,sn])
ax.set_ylim3d([-sn,sn])
ax.set_zlim3d([-sn,sn])

ax.set_axis_off()

plt.show()

结果如下图:

enter image description here

尽管我对结果非常满意,但这仍然是一种手动绘制轴、刻度和标签的“hacky”解决方案。如果有人有一个解决方案,我们可以在其中重新设计 mplot3d API 中的轴,那将非常有帮助。

解决方法

(Swatchai 将此创建为社区维基):

有时,没有一些可运行的代码来播放/实验的讨论并不是获得解决方案的最佳方法。在这里我建议使用此代码以供进一步讨论。

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

fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')

# Quivers for axes x,y,z from (0,0)
quiver1 = ax.quiver([0],[0],[2],colors='r')
quiver2 = ax.quiver([0],colors='g')
quiver3 = ax.quiver([0],colors='b')

# Some settings
sn = 2   #limits in x,z
n = 50   #number of sample points
x1,x2 = -sn,sn
y1,y2 = -sn,sn    
z1,z2 = -sn,sn

# Data for points
xs = (x2 - x1)*np.random.rand(n) + x1
ys = (y2 - y1)*np.random.rand(n) + y1
zs = (z2 - z1)*np.random.rand(n) + z1

# Points with z >= 0,plotted in green
ax.scatter(xs[zs>=0],ys[zs>=0],zs[zs>=0],color='green')
# Points with z < 0,plotted in red
ax.scatter(xs[zs<0],ys[zs<0],zs[zs<0],color='red')

# Data for plotting plane x|y|z=0 within the domain
tmp = np.linspace(0,sn,8)
x,y = np.meshgrid(tmp,tmp)
z = 0*x

ax.plot_surface(z,x,alpha=0.15,color='red')    # plot the plane x=0
ax.plot_surface(x,z,color='green')  # plot the plane y=0
ax.plot_surface(x,color='blue')   # plot the plane z=0

# Set limits of the 3D display
ax.set_xlim3d([-sn,sn])
ax.set_ylim3d([-sn,sn])
ax.set_zlim3d([-sn,sn])

# Set labels at the 3d box/frame
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

输出图:

quiverasaxes

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...