简体   繁体   English

使用 plotly 在 3d 散点图中绘制 3d 框

[英]Drawing a 3d box in a 3d scatterplot using plotly

I was trying to plot a 3d box in a 3d scatterplot.我试图在 3d 散点图中绘制一个 3d 框。 Basically, this was the result of an optimization problem (background is here ).基本上,这是优化问题的结果(背景在这里)。 The box is the largest empty box possible given all the points.给定所有点,该框是可能的最大空框。

In the plotly docs I noticed an example of a 3d cube built using 3dmesh.在 plotly 文档中,我注意到一个使用 3dmesh 构建的 3d 立方体的示例。 I copied this:我复制了这个:

import plotly.graph_objects as go
x=[ 0.93855, 0.20203, 0.54967, 0.58658, 0.39931, 0.06736, 0.61786, 0.36016, 0.12761, 0.71581, 0.81998, 0.04528, 0.08231, 0.41814, 0.58679, 0.21181, 0.34489, 0.21812, 0.46830, 0.81898,
 0.57360, 0.18453, 0.99792, 0.37970, 0.51954, 0.84264, 0.22431, 0.31440, 0.23893, 0.28493, 0.76353, 0.45365, 0.44480, 0.94911, 0.98050, 0.28615, 0.02626, 0.85477, 0.60404, 0.47469,
 0.10588, 0.55919, 0.42194, 0.34432, 0.80530, 0.88291, 0.53627, 0.45454, 0.01345, 0.84411, 0.04520, 0.35532, 0.45255, 0.99365, 0.72259, 0.08634, 0.78806, 0.28674, 0.57993, 0.84025,
 0.22766, 0.51236, 0.83945, 0.21910, 0.41881, 0.18910, 0.00183, 0.59310, 0.12687, 0.45273, 0.14348, 0.66694, 0.28690, 0.32822, 0.93954, 0.34411, 0.25276, 0.14377, 0.08142, 0.05422,
 0.51448, 0.48659, 0.66585, 0.25156, 0.69205, 0.21175, 0.72413, 0.92027, 0.79572, 0.13293, 0.81984, 0.25584, 0.42517, 0.41333, 0.75978, 0.60823, 0.83418, 0.37497, 0.10177, 0.01215]
y=[ 0.61424, 0.39918, 0.57526, 0.04537, 0.24058, 0.18701, 0.18450, 0.82907, 0.66274, 0.96315, 0.58458, 0.12807, 0.38695, 0.30646, 0.88417, 0.63859, 0.40404, 0.06445, 0.19149, 0.91259,
 0.99317, 0.67468, 0.12954, 0.11868, 0.79252, 0.98170, 0.74706, 0.28944, 0.55650, 0.91190, 0.26978, 0.94868, 0.82534, 0.37846, 0.38055, 0.42637, 0.26349, 0.09109, 0.10308, 0.63728,
 0.37470, 0.85528, 0.19407, 0.29683, 0.71095, 0.72789, 0.47052, 0.54725, 0.62322, 0.52442, 0.32547, 0.54581, 0.51336, 0.58652, 0.76841, 0.00042, 0.80743, 0.32560, 0.29931, 0.19091,
 0.95850, 0.42236, 0.70728, 0.85435, 0.79661, 0.14909, 0.80658, 0.36827, 0.46344, 0.92196, 0.09802, 0.02856, 0.73966, 0.55969, 0.34595, 0.80634, 0.18350, 0.84283, 0.04560, 0.41515,
 0.50151, 0.52665, 0.44211, 0.48040, 0.39643, 0.99743, 0.18206, 0.09721, 0.33793, 0.69245, 0.97670, 0.70870, 0.75288, 0.51147, 0.22298, 0.84305, 0.62014, 0.41474, 0.82815, 0.42865]
z=[ 0.13338, 0.81253, 0.46946, 0.76145, 0.83335, 0.96434, 0.79175, 0.20481, 0.60056, 0.26519, 0.89917, 0.16271, 0.02890, 0.49017, 0.18970, 0.16751, 0.47065, 0.85533, 0.73768, 0.14031,
 0.92923, 0.11933, 0.40330, 0.46713, 0.69964, 0.25784, 0.87656, 0.25886, 0.64603, 0.92604, 0.83728, 0.71988, 0.48486, 0.57123, 0.78618, 0.70429, 0.30544, 0.20687, 0.47584, 0.58176,
 0.43336, 0.35453, 0.96509, 0.98293, 0.88605, 0.70571, 0.51733, 0.09292, 0.69618, 0.76415, 0.82743, 0.99876, 0.86101, 0.58373, 0.03917, 0.60540, 0.59567, 0.94481, 0.35552, 0.80555,
 0.97449, 0.31020, 0.61952, 0.48569, 0.50740, 0.69248, 0.01918, 0.04973, 0.21958, 0.98663, 0.09143, 0.24220, 0.96312, 0.66227, 0.91103, 0.26285, 0.28079, 0.10938, 0.07499, 0.34065,
 0.83692, 0.33815, 0.89640, 0.06275, 0.01852, 0.08153, 0.88351, 0.08171, 0.87036, 0.51620, 0.90021, 0.67128, 0.36607, 0.54804, 0.72661, 0.18951, 0.11629, 0.46170, 0.24500, 0.88841]

fig = go.Figure(data=[
     go.Scatter3d(x=x, y=y, z=z,
                  mode='markers',
                  marker=dict(size=2)
                 ),
     go.Mesh3d(
        # 8 vertices of a cube
        x=[0.608, 0.608, 0.998, 0.998, 0.608, 0.608, 0.998, 0.998],
        y=[0.091, 0.963, 0.963, 0.091, 0.091, 0.963, 0.963, 0.091],
        z=[0.140, 0.140, 0.140, 0.140, 0.571, 0.571, 0.571, 0.571],

        i = [7, 0, 0, 0, 4, 4, 6, 6, 4, 0, 3, 2],
        j = [3, 4, 1, 2, 5, 6, 5, 2, 0, 1, 6, 3],
        k = [0, 7, 2, 3, 6, 7, 1, 1, 5, 5, 7, 6],
        opacity=0.6,
        color='#DC143C'
    )                    
    ])
fig.show()

However, the picture shows really the triangles.但是,图片确实显示了三角形。 Any better way to draw a 3d box (in Plotly)?绘制 3d 框的更好方法(在 Plotly 中)?

在此处输入图片说明

For me using the argument flatshading = True did the job.对我来说,使用参数flatshading = True完成了这项工作。

Code代码

fig = go.Figure(data=[
     go.Scatter3d(x=x, y=y, z=z,
                  mode='markers',
                  marker=dict(size=2)
                 ),
     go.Mesh3d(
        # 8 vertices of a cube
        x=[0.608, 0.608, 0.998, 0.998, 0.608, 0.608, 0.998, 0.998],
        y=[0.091, 0.963, 0.963, 0.091, 0.091, 0.963, 0.963, 0.091],
        z=[0.140, 0.140, 0.140, 0.140, 0.571, 0.571, 0.571, 0.571],

        i = [7, 0, 0, 0, 4, 4, 6, 6, 4, 0, 3, 2],
        j = [3, 4, 1, 2, 5, 6, 5, 2, 0, 1, 6, 3],
        k = [0, 7, 2, 3, 6, 7, 1, 1, 5, 5, 7, 6],
        opacity=0.6,
        color='#DC143C',
        flatshading = True
    )                    
    ])

Output输出

在此处输入图片说明

You can use Poly3DCollection to create shape that you need with defining shape corners.您可以使用Poly3DCollection通过定义形状角来创建所需的形状。

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from itertools import product

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

# create list of corners
z = list(product([-1,1], repeat=3))

# set verts connectors
verts = [[z[0],z[1],z[5],z[4]], [z[4],z[6],z[7],z[5]], [z[7], z[6], z[2], z[3]], [z[2], z[0], z[1], z[3]],
         [z[5], z[7], z[3], z[1]], [z[0], z[2], z[6], z[4]]]


ax.set_xlim3d(-2,2)
ax.set_ylim3d(-2,2)
ax.set_zlim3d(-2,2)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

# plot sides
ax.add_collection3d(Poly3DCollection(verts,facecolors='blue', linewidths=1, edgecolors='black', alpha=.1))

plt.show()

Output:输出:

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM