nul*_*tto 3 python visualization plotly plotly-python
我有兴趣绘制一个实值函数f(x,y,z)=a,其中(x,y,z)是球体上的 3D 点,并且a是实数。我计算球体点的笛卡尔坐标如下,但我不知道如何可视化f每个点的值。
import plotly.graph_objects as go
import numpy as np
fig = go.Figure(layout=go.Layout(title=go.layout.Title(text=title), hovermode=False))
# Create mesh grid for spherical coordinates
phi, theta = np.mgrid[0.0:np.pi:100j, 0.0:2.0 * np.pi:100j]
# Get Cartesian mesh grid
x = np.sin(phi) * np.cos(theta)
y = np.sin(phi) * np.sin(theta)
z = np.cos(phi)
# Plot sphere surface
self.fig.add_surface(x=x, y=y, z=z, opacity=0.35)
fig.show()
Run Code Online (Sandbox Code Playgroud)
我会想象/期望/喜欢这样的可视化
f此外,我还以封闭形式计算了的梯度(即,对于每个(x,y,z)我计算 的 3D 维梯度f)。有没有一种方法可以绘制这个矢量场,类似于上图所示?
小智 5
这是一个远非完美的答案,但希望这足以让您继续前进。
对于球体本身,我不知道有什么“捷径”可以在绘图中执行类似的操作,所以我的方法只是手动创建球体网格。生成顶点很简单,例如像您一样 - 稍微棘手的部分是计算三角形的顶点索引(这取决于顶点生成方案)。有多种算法可以顺利地做到这一点(即生成一个没有“尖端”的球体),我只是为了演示而破解了一些粗糙的东西。然后我们可以使用该Mesh3d对象来显示球体以及强度和您选择的颜色图:
N = 100 # Sphere resolution (both rings and segments, can be separated to different constants)
theta, z = np.meshgrid(np.linspace(-np.pi, np.pi, N), np.linspace(-1, 1, N))
r = np.sqrt(1 - z ** 2)
x = r * np.cos(theta)
y = r * np.sin(theta)
x = x.ravel()
y = y.ravel()
z = z.ravel()
# Triangle indices
indices = np.arange(N * (N - 1) - 1)
i1 = np.concatenate([indices, (indices // N + 1) * N + (indices + 1) % N])
i2 = np.concatenate([indices + N, indices // N * N + (indices + 1) % N])
i3 = np.concatenate([(indices // N + 1) * N + (indices + 1) % N, indices])
# Point intensity function
def f(x, y, z):
return (np.cos(x * 2) + np.sin(y ** 2) + np.sin(z) + 3) / 6
fig = go.Figure(data=[
go.Mesh3d(
x=x,
y=y,
z=z,
colorbar_title='f(x, y, z)',
colorscale=[[0, 'gold'],
[0.5, 'mediumturquoise'],
[1, 'magenta']],
intensity = f(x, y, z),
i = i1,
j = i2,
k = i3,
name='y',
showscale=True
)
])
fig.show()
Run Code Online (Sandbox Code Playgroud)
要添加矢量场,您可以使用Cone plot; 这需要一些修补,因为当我简单地将圆锥体绘制在x, y, z与球体相同的位置时,一些圆锥体部分或完全被球体遮挡。因此,我生成了另一个半径稍大的球体,并将圆锥体放置在那里。我还使用了一些照明参数,使其像您的示例中那样变黑。完整的代码如下所示:
N = 100 # Sphere resolution (both rings and segments, can be separated to different constants)
theta, z = np.meshgrid(np.linspace(-np.pi, np.pi, N), np.linspace(-1, 1, N))
r = np.sqrt(1 - z ** 2)
x = r * np.cos(theta)
y = r * np.sin(theta)
x = x.ravel()
y = y.ravel()
z = z.ravel()
# Triangle indices
indices = np.arange(N * (N - 1) - 1)
i1 = np.concatenate([indices, (indices // N + 1) * N + (indices + 1) % N])
i2 = np.concatenate([indices + N, indices // N * N + (indices + 1) % N])
i3 = np.concatenate([(indices // N + 1) * N + (indices + 1) % N, indices])
# Point intensity function
def f(x, y, z):
return (np.cos(x * 2) + np.sin(y ** 2) + np.sin(z) + 3) / 6
# Vector field function
def grad_f(x, y, z):
return np.stack([np.cos(3 * y + 5 * x),
np.sin(z * y),
np.cos(4 * x - 3 * y + z * 7)], axis=1)
# Second sphere for placing cones
N2 = 50 # Smaller resolution (again rings and segments combined)
R2 = 1.05 # Slightly larger radius
theta2, z2 = np.meshgrid(np.linspace(-np.pi, np.pi, N2), np.linspace(-R2, R2, N2))
r2 = np.sqrt(R2 ** 2 - z2 ** 2)
x2 = r2 * np.cos(theta2)
y2 = r2 * np.sin(theta2)
x2 = x2.ravel()
y2 = y2.ravel()
z2 = z2.ravel()
uvw = grad_f(x2, y2, z2)
fig = go.Figure(data=[
go.Mesh3d(
x=x,
y=y,
z=z,
colorbar_title='f(x, y, z)',
colorscale=[[0, 'gold'],
[0.5, 'mediumturquoise'],
[1, 'magenta']],
intensity = f(x, y, z),
i = i1,
j = i2,
k = i3,
name='y',
showscale=True
),
go.Cone(
x=x2, y=y2, z=z2, u=uvw[:, 0], v=uvw[:, 1], w=uvw[:, 2], sizemode='absolute', sizeref=2, anchor='tail',
lighting_ambient=0, lighting_diffuse=0, opacity=.2
)
])
fig.show()
Run Code Online (Sandbox Code Playgroud)
并产生这个图:
希望这可以帮助。显示有很多调整,当然还有构建球体网格的更好方法(例如,请参阅这篇文章),因此应该有很大的自由度(尽管以一些工作为代价)。
祝你好运!
| 归档时间: |
|
| 查看次数: |
643 次 |
| 最近记录: |