'Plotly 3D plot with right aspect ratio

the relevant post is here: interactive 3D plot with right aspect ratio using plotly

For a further improvment, I am wondering how to plot a container frame according to the bin size, so the graph can display more clearly how much spare space is left, when container is not full? just like what is shown below:

enter image description here

UPADTE: drawing outer container frame

def parallelipipedic_frame(xm, xM, ym, yM, zm, zM):
    # defines the coords of each segment followed by None, if the line is
    # discontinuous
    x = [xm, xM, xM, xm, xm, None, xm, xM, xM, xm, xm, None, xm, xm, None, xM, xM,
         None, xM, xM, None, xm, xm]
    y = [ym, ym, yM, yM, ym, None, ym, ym, yM, yM, ym, None, ym, ym, None, ym, ym,
         None, yM, yM, None, yM, yM]
    z = [zm, zm, zm, zm, zm, None, zM, zM, zM, zM, zM, None, zm, zM, None, zm, zM,
         None, zm, zM, None, zm, zM]
    return x, y, z

x, y, z = parallelipipedic_frame(0, 1202.4, 0, 235, 0, 269.7)
# fig = go.Figure(go.Scatter3d(x=x, y=y, z=z, mode="lines", line_width=4))

fig.add_trace(
    go.Scatter3d(
        x=x,
        y=y,
        z=z,
        mode="lines",
        line_color="blue",
        line_width=2,
        hoverinfo="skip",
    )
)

ar = 4
xr = max(d["x"].max()) - min(d["x"].min())
fig.update_layout(
    title={"text": pbin, "y": 0.9, "x": 0.5, "xanchor": "center", "yanchor": "top"},
    margin={"l": 0, "r": 0, "t": 0, "b": 0},
    # autosize=False,
    scene=dict(
        camera=dict(eye=dict(x=2, y=2, z=2)),
        aspectratio={
            **{"x": ar},
            **{
                c: ((max(d[c].max()) - min(d[c].min())) / xr) * ar
                for c in list("yz")
            },
        },
        aspectmode="manual",
    ),
)

enter image description here



Solution 1:[1]

The frame consists of segments, and a segment is drawn between two points. Hence I cannot give the code for plottin the frame only from your length, width and height. I need the coordinates of the parallelipiped vertices, i.e. x.min(), x.max(), y.min(), y.max(), etc (see above), denoted xm, xM, ym, yM, zm, zM:

import plotly.graph_objects as go

def parallelipipedic_frame(xm, xM, ym, yM, zm, zM):
    #defines the coords of each segment followed by None, if the line is 
    discontinuous
    x = [xm, xM, xM, xm, xm, None, xm, xM, xM, xm, xm, None, xm, xm, None, xM, xM, 
         None, xM, xM, None, xm, xm]
    y = [ym, ym, yM, yM, ym, None, ym, ym, yM, yM, ym, None, ym, ym, None, ym, ym, 
         None, yM, yM,None, yM, yM]
    z= [zm, zm, zm, zm, zm, None, zM, zM, zM, zM, zM, None, zm, zM, None, zm, zM, 
        None, zm, zM, None, zm, zM]
    return x, y, z

x, y, z= parallelipipedic_frame(2.3, 4.5, 0,5, 0, 2)
fig=go.Figure(go.Scatter3d(x=x, y=y, z=z, mode="lines", line_width=4))
fig.update_layout(width=600, height=450, font_size=11,  scene_aspectmode="data", 
                  scene_camera_eye=dict (x=1.45, y=1.45, z=1), template="none")
fig.show()

enter image description here

Solution 2:[2]

To get a realistic 3d plot, you should set in layout, scene_aspectmode='data'.

To plot the container frame, retrieve from data used to plot the voxels, x.min(), x.max(), y.min(), y.max(), z.min(), z.max(), if x, y, z are arrays or min(x) etc if they are lists. Then add to your plotly figure a scatter3d plot, mode="lines" to draw the lines for container frame. I checked it for a partial frame attached to my own voxel plot, and it works: voxels

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 xecafe
Solution 2