matplotlib 如何使用plotly(或其他库)在3d中绘制球体?

xxb16uws  于 2023-11-22  发布在  其他
关注(0)|答案(4)|浏览(184)

我正在努力绘制一些东西,我认为应该是非常简单的。我有一个包含球体坐标x,y,z的框架/表df。此外,在一个单独的列中,它包含这些球体的半径。我如何使用plotly绘制空间中球体的3D图,并使用正确的半径?
我最接近实现这个情节的是下面的代码:

import plotly.express as px
import plotly.graph_objects as go

x =y=z = np.arange(1,4)

fig = go.Figure()
fig.add_trace(go.Scatter3d(
        mode='markers',
        x=x,
        y=y,
        z=z,
        marker=dict(color=px.colors.qualitative.D3,size=[50, 5, 25],sizemode='diameter'
        )
    )
)

字符串
这几乎产生了我想要的结果(见下文),但请注意,球体的大小不正确-球体大小之间的比率是正确的,但我希望size提供图中球体的绝对大小。我如何使此图与plotly一起工作(或与另一个库一起工作的最坏情况)?
x1c 0d1x的数据

qaxu7uf2

qaxu7uf21#

基于azelcer的回答,我设法生成了以下代码,用plotly绘制球体:

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

def ms(x, y, z, radius, resolution=20):
    """Return the coordinates for plotting a sphere centered at (x,y,z)"""
    u, v = np.mgrid[0:2*np.pi:resolution*2j, 0:np.pi:resolution*1j]
    X = radius * np.cos(u)*np.sin(v) + x
    Y = radius * np.sin(u)*np.sin(v) + y
    Z = radius * np.cos(v) + z
    return (X, Y, Z)

df = pd.read_csv('xyzr_sphere_coordinates.txt')

data = []
for index, row in df.iterrows():
    (x_pns_surface, y_pns_surface, z_pns_suraface) = ms(row.x, row.y, row.z, row.r)
    data.append(go.Surface(x=x_pns_surface, y=y_pns_surface, z=z_pns_suraface, opacity=0.5))

fig = go.Figure(data=data)
fig.show()

字符串
它导致了这个3D互动图:


的数据

e0uiprwp

e0uiprwp2#

当你使用标记时,大小通常以像素为单位(面积或直径)。
我从来没有使用过plotly,但我很确定将这个使用matplotlib的脚本转换为使用plotly是很容易的(参见here)。

import numpy as np
import matplotlib.pyplot as plt
from itertools import repeat  # just for the example

def makesphere(x, y, z, radius, resolution=10):
    """Return the coordinates for plotting a sphere centered at (x,y,z)"""
    u, v = np.mgrid[0:2*np.pi:resolution*2j, 0:np.pi:resolution*1j]
    X = radius * np.cos(u)*np.sin(v) + x
    Y = radius * np.sin(u)*np.sin(v) + y
    Z = radius * np.cos(v) + z
    return (X, Y, Z)

fig = plt.figure("Spheres")
ax = fig.add_subplot(projection='3d')

for x, y, z, radius, in zip(*repeat(np.arange(1,4),3), [.1, .5, .75]):
    X, Y, Z = makesphere(x, y, z, radius)
    ax.plot_surface(X, Y, Z, color="r")

字符串
测试结果:


的数据
如果想要更平滑的球体,请增加resolution参数(并将cstriderstride参数检查为plot_surface)。

vktxenjb

vktxenjb3#

我个人使用PyVista将球体的网格作为等值面,并使用go.Mesh3d使用plotly绘制它。

import numpy as np
import pyvista as pv
import plotly.graph_objects as go
import plotly.io as pio # to save the graphics as html

# center 
x0 = 0
y0 = 0
z0 = 0
# radius 
r = 2
# radius + 2% to be sure of the bounds
R = r * 1.02

def f(x, y, z):
    return (
        (x-x0)**2 + (y-y0)**2 + (z-z0)**2
    )

# generate data grid for computing the values
X, Y, Z = np.mgrid[(-R+x0):(R+x0):250j, (-R+y0):(R+y0):250j, (-R+z0):(R+z0):250j]
# create a structured grid
grid = pv.StructuredGrid(X, Y, Z)
# compute and assign the values
values = f(X, Y, Z)
grid.point_data["values"] = values.ravel(order = "F")
# compute the isosurface f(x, y, z) = r²
isosurf = grid.contour(isosurfaces = [r**2])
mesh = isosurf.extract_geometry()
# extract vertices and triangles
vertices = mesh.points
triangles = mesh.faces.reshape(-1, 4)

# plot
fig = go.Figure(data=[
    go.Mesh3d(
        x=vertices[:, 0],
        y=vertices[:, 1],
        z=vertices[:, 2],
        colorscale = [[0, 'gold'],
                     [0.5, 'mediumturquoise'],
                     [1, 'magenta']],
        # Intensity of each vertex, which will be interpolated and color-coded
        intensity = np.linspace(0, 1, len(vertices)),
        # i, j and k give the vertices of the triangles
        i = triangles[:, 1],
        j = triangles[:, 2],
        k = triangles[:, 3],
        showscale = False
    )
])

fig.show()

# save
pio.write_html(fig, "plotlySphere.html")

字符串


的数据

isr3a4wc

isr3a4wc4#

可以使用S3Dlib中的SphericalSurface类直接构造球体的图。例如:
x1c 0d1x的数据
这是从脚本中生成的:

import csv
import numpy as np
import matplotlib.pyplot as plt
import s3dlib.surface as s3d

csv_data = []
with open('testdata.csv') as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=',')
    for row in csv_reader: csv_data.append(row)    
# note: first row contains the column labels
geom = np.array([ c[0:4] for c in csv_data ][1:]).astype(float)  # xyz & radii
colors =        [   c[4] for c in csv_data ][1:]

rez=3
for i,sph in enumerate(geom) :
    s = s3d.SphericalSurface(rez,color=colors[i]).domain(sph[3])
    s.transform(translate=sph[0:3])
    spheres = s if i==0 else spheres+s

fig = plt.figure(figsize=plt.figaspect(1))
ax = plt.axes(projection='3d')
s3d.auto_scale(ax,spheres, rscale=True )
ax.add_collection3d(spheres.shade())

fig.tight_layout()
plt.show()

字符串
使用Excel生成CSV图表,随机xyz坐标为[-25,25]。半径使用正态分布,平均值为10,标准差为5。随机颜色取自Matplotlib,命名为CSS颜色。
使用球面对象创建图形的另一个示例如下所示:



在这种情况下,球体的位置、大小和颜色都是显式定义的。code在S3 Dlib文档中提供。

相关问题