How to plot a cube in 3D in Plots.jl

I would like to plot a 3D cube in Plots.jl and I have not been able to.
I know that there are solutions in Makie but I would like to use the Plots.jl interface because I want to combine this with other things plotted with Plots.jl.

So far I can get wireframe working with:

Plots_jl.plot!(ax, [x, x + w1, x+w1, x, x], [y, y, y+w2, y+w2, y], [z, z, z, z, z], aspect_ratio=1.0) # bottom
    Plots_jl.plot!(ax, [x, x + w1, x+w1, x, x], [y, y, y+w2, y+w2, y], [z+w3, z+w3, z+w3, z+w3, z+w3],) # top
    Plots_jl.plot!(ax, [x, x, x, x, x], [y, y+w2, y+w2, y, y], [z, z, z+w3, z+w3, z]) # back left 
    Plots_jl.plot!(ax, [x, x+w1, x+w1, x, x], [y+w2, y+w2, y+w2, y+w2, y+w2], [z, z, z+w3, z+w3, z]) # back right 
    Plots_jl.plot!(ax, [x, x+w1, x+w1, x, x], [y, y, y, y, y], [z, z, z+w3, z+w3, z]) # front left 
    Plots_jl.plot!(ax, [x+w1, x+w1, x+w1, x+w1, x+w1], [y, y+w2, y+w2, y, y], [z, z, z+w3, z+w3, z])

But I have tried to create solid surfaces with:

# Plots_jl.plotly()
x,y,z = 0.,0.,0.
w1,w2,w3 = 1.0,1.0,1.0
xrange = range(x, stop=x+w1, length=10)
yrange = range(y, stop=y+w2, length=10)
zrange = range(z, stop=z+w3, length=10)
Plots_jl.surface(xrange, yrange, (a1,a2)-> z, xlabel="x", ylabel="y", zlabel="z") # bottom
Plots_jl.surface!(repeat([x], length(xrange)), yrange, (a1,a2)->zrange[findfirst(a -> a == a2, yrange)]) # back left 
# back right 
# front left 
# front right 
Plots_jl.surface!(x:.1:x+w1, y:.1:y+w2, (a1,a2)-> z+w3) # top

and it does not work.

You can not plot vertical surfaces using surface, you’d need mesh3d for this:

using Plots
xp = [0, 0, 0, 0, 1, 1, 1, 1];
yp = [0, 1, 0, 1, 0, 0, 1, 1];
zp = [0, 0, 1, 1, 1, 0, 0, 1];
connections = [(1,2,3), (4,2,3), (4,7,8), (7,5,6), (2,4,7), (1,6,2), (2,7,6), (7,8,5), (4,8,5), (4,5,3), (1,6,3), (6,3,5)];

mesh3d(xp,yp,zp; connections, xlabel="x", proj_type = :persp, linecolor=:black)
3 Likes

Using your solution, there must be a way to remove these triangulation lines right?

image

Ideally I want to keep the “outer edges”, but I cannot figure out how to do this. The documentation confuses me.

Kind regards

Dear @Ahmed_Salih,
Have you found a solution to remove those triangular lines? If yes, could you let me know how to do it?

Hi!

Unfortunately, I don’t recall being able too :slight_smile:

1 Like

FWIW, one possible workaround in Plots.jl’s gr() backend, is to define linewidth=0 in the mesh3d() code above and to draw the cube edges:

PS: one red marker was placed in the center of the cube

2 Likes

Oh, I would have loved to have known this February 12th 2023, but atleast I know it now :smiley:

Thanks @rafael.guerra !

1 Like

Thank you @rafael.guerra. After using linewidth=0 in the mesh3d() code above, diagonal lines are removed but cube edges are also removed. I want to keep cube edges.

@Ashu, the workaround suggested requires drawing the edges.

Dear @rafael.guerra,

Can you please provide the code for this plot? I am getting a cube but with no color fill.

Thank you

@Ashu, as requested here is the code snippet used.

Note that, as usual with lw=0, what you see on the screen is not what you get on disk. The latter is better.

Plots.jl gr(): plot a cube
using Plots; gr()

xp = [0, 0, 0, 0, 1, 1, 1, 1]
yp = [0, 1, 0, 1, 0, 0, 1, 1]
zp = [0, 0, 1, 1, 1, 0, 0, 1]
connections = [(1,2,3), (4,2,3), (4,7,8), (7,5,6), (2,4,7), (1,6,2), (2,7,6), (7,8,5), (4,8,5), (4,5,3), (1,6,3), (6,3,5)]

xe = [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0]
ye = [0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1]
ze = [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1]

plot(xe,ye,ze; lc=:black, lw=0.5, lims=(-0.25,1.25))
scatter!((0.5,0.5,0.5); c=:red, ms=6, msw=0.1)
mesh3d!(xp,yp,zp; connections, proj_type=:persp, fc=:lime, lc=:lime, fa=0.3, lw=0)

savefig("Plots_gr_colored_cube_with_all_edges.png")