How to create surface plot in CairoMakie where the sides are 'filled'?

I can make a surface plot with the following codes:

x = range(-1, 1, length=129)
y = range(-1, 1, length=129)
R = x'.^2 .+ y.^2
h2d = cos.(R)

update_theme!(
    lightposition = Vec3f(50, 10, 0),
    Axis3 = (
        elevation = pi/6, azimuth = -pi/4, aspect = (1, 1, 0.5) 
        ),
    Surface = (
        shininess = 32f0, specular = Vec3f(0.2), rasterize = 5,
        ),
)

fig = Figure()

ga = fig[1,1] = GridLayout()
ax1 = Axis3(ga[1,1])
surf1 = surface!(ax1, x, y, h2d, colormap=Reverse(:Spectral_4))
hidedecorations!(ax1)

display(fig)

image

I would like to ‘fill’ the four sides of the above surface plot, like the following figure (ignore the lines on the surface, I just want the ‘sides’). Is that possible in CairoMakie?

image

One idea is to use band, here I’ve done it with the two visible sides. One could also draw a single band around all four sides. Also the shape didn’t match from your code, so I changed it a bit to make it wavy.

x = range(-1, 1, length=129)
y = range(-1, 1, length=129)
R = x'.^2 .+ y.^2
h2d = cos.(3.5R)

th = Theme(
    lightposition = Vec3f(50, 10, 0),
    Axis3 = (
        elevation = pi/6, azimuth = -pi/4, aspect = (1, 1, 0.5) 
        ),
    Surface = (
        shininess = 32f0, specular = Vec3f(0.2), rasterize = 5,
        ),
)

with_theme(th) do
    fig = Figure()

    ga = fig[1,1] = GridLayout()
    ax1 = Axis3(ga[1,1])
    surf1 = surface!(ax1, x, y, h2d, colormap=Reverse(:Spectral_4))

    lower = Point3f.(x, first(y), minimum(h2d))
    upper = Point3f.(x, first(y), h2d[:, 1])
    band!(ax1, lower, upper, color = last(Makie.to_colormap(:Spectral_4)), shading = true)

    lower = Point3f.(last(x), y, minimum(h2d))
    upper = Point3f.(last(x), y, h2d[end, :])
    band!(ax1, lower, upper, color = last(Makie.to_colormap(:Spectral_4)), shading = true)

    hidedecorations!(ax1)

    fig
end

3 Likes

Are there any ways to also color the sides such that the color reflects the height of that point? e.g. Using the colormap Reverse(:Spectral_4) the bottom of the base should appear blue while near the top at the four corners it should appear black. It looks like with band if I pass the height of the surface based on h2d to the color argument, then each vertical stripe gets different color, which is not what I want.

I think so, using mesh. I’d try making quadrilateral faces out of the same points I used for the bands. But without making smaller faces by subdividing it won’t look that good in cairomakie, due to the way meshes work there. In glmakie it would look better.

this works:

band(; color = [color_values_at_bottom..., color_values_at_top...]

this case will be available as an example here in the next hour, CI building now.

3 Likes

Ah nice, I forgot about that option, that’s essentially the mesh I proposed without the manual work.

I tried using CairoMakie (basically just changing the backend while keeping the code the same), and it looks like the color of the side bands is wrong (it varies laterally instead of vertically). Is that just a limitation of the CairoMakie backend or are there tricks to make it work?