Zoom in GLMakie 3d plot then save

Hello, I need some help to perform some simple operations on GLMakie.
I want, say, to draw a simple torus juste like this example, zoom in, and save the plot, but I could find no example on how to use Makie’s zoom! function.

Here is the code for plotting a torus :

using GLMakie
let
    U = LinRange(-pi, pi, 100) # 50
    V = LinRange(-pi, pi, 20)
    x1 = [cos(u) + .5 * cos(u) * cos(v)      for u in U, v in V]
    y1 = [sin(u) + .5 * sin(u) * cos(v)      for u in U, v in V]
    z1 = [.5 * sin(v)                        for u in U, v in V]
    x2 = [1 + cos(u) + .5 * cos(u) * cos(v)  for u in U, v in V]
    y2 = [.5 * sin(v)                        for u in U, v in V]
    z2 = [sin(u) + .5 * sin(u) * cos(v)      for u in U, v in V]
    fig = Figure(resolution =(900,600))
    ax = LScene(fig, scenekw = (camera = cam3d!, show_axis = true))
    wireframe!(ax.scene, x1,y1,z1, shading = false)
    fig[1,1] = ax
    save("zoom.png", fig)
end

and saving as a .png picture. I tried to zoom by adding

zoom!(ax.scene, 3)

to zoom by a factor 3 and it didnt work. How could I do ?
Same question applies for translations and rotations.

PS: this issue seems related, but does not provide a solution on how to zoom.

In fact, any tutorial on using Makie’s camera would be useful, but there are not so many examples for learning…
Anyone has something on how to zoom on a picture ? It should be simple enough, but I can’t find it on the doc and the zoom! method does not seem to have any effect.

Have you tried using scale!:
scale!(ax.scene, 3, 3, 3)

zoom!(ax.scene, cameracontrols(ax.scene), 3) followed by update_cam!(ax.scene, cameracontrols(ax.scene)) works for me, but I believe that your version should in principle also be correct if everything was working as intended (see also https://github.com/JuliaPlots/Makie.jl/issues/1236#issuecomment-902094122).

The scale!(ax.scene, 3,3,3) makes no difference. When I play with the arguments. See for instance the output of the above code in the first post:

and the output with scale!(ax.scene, 3,3,3) :

and the output with scale!(ax.scene, 100,100,100) :

It just removed the ticks, I don’t know why.

The solution proposed by bvrb does not work either, ie

using GLMakie
let
    U = LinRange(-pi, pi, 100) # 50
    V = LinRange(-pi, pi, 20)
    x1 = [cos(u) + .5 * cos(u) * cos(v)      for u in U, v in V]
    y1 = [sin(u) + .5 * sin(u) * cos(v)      for u in U, v in V]
    z1 = [.5 * sin(v)                        for u in U, v in V]
    x2 = [1 + cos(u) + .5 * cos(u) * cos(v)  for u in U, v in V]
    y2 = [.5 * sin(v)                        for u in U, v in V]
    z2 = [sin(u) + .5 * sin(u) * cos(v)      for u in U, v in V]
    fig = Figure(resolution =(900,600))
    ax = LScene(fig, scenekw = (camera = cam3d!, show_axis = true))
    wireframe!(ax.scene, x1,y1,z1, shading = false)
    zoom!(ax.scene, cameracontrols(ax.scene), 3)
    update_cam!(ax.scene, cameracontrols(ax.scene))
    fig[1,1] = ax
    save("zoom_alt.png", fig)
end

ends with the same picture.

Please check solution in this other post, it works (GLMakie v0.4.4):

Indeed, there are two separate issues here - the zooming itself, and then saving the picture. I had only tried it directly in the REPL.

Just for completeness sake, combining the code you quoted and what is proposed in rafael.guerra’s link:

using GLMakie

U = LinRange(-pi, pi, 100) # 50
V = LinRange(-pi, pi, 20)
x1 = [cos(u) + .5 * cos(u) * cos(v)      for u in U, v in V]
y1 = [sin(u) + .5 * sin(u) * cos(v)      for u in U, v in V]
z1 = [.5 * sin(v)                        for u in U, v in V]
x2 = [1 + cos(u) + .5 * cos(u) * cos(v)  for u in U, v in V]
y2 = [.5 * sin(v)                        for u in U, v in V]
z2 = [sin(u) + .5 * sin(u) * cos(v)      for u in U, v in V]
fig = Figure(resolution =(900,600))
ax = LScene(fig, scenekw = (camera = cam3d!, show_axis = true))
wireframe!(ax.scene, x1,y1,z1, shading = false)
zoom!(ax.scene, cameracontrols(ax.scene), 3)
update_cam!(ax.scene, cameracontrols(ax.scene))
fig[1,1] = ax
ax.scene.center = false
save("zoom_alt.png", fig)

This, for me (with GLMakie v0.4.4), results in a zoomed out picture:

Alternatively, zoom!(ax.scene, cameracontrols(ax.scene), 1/3) will zoom in instead:

2 Likes

@bvrb It works perfectly. Thank you !

current version is
v0.3.4Latest
on Jun 8

mine shows an error in zoom
" MethodError: no method matching zoom!(::Scene, ::Camera3D, ::Int64)
something wrong with me

That repository you linked is outdated, citing from the README.md:

INFO: This repository is deprecated

GLMakie has been moved into the monorepo at Makie.jl. The latest version can be determined by checking the Project.toml in the GLMakie subdirectory. add GLMakie will now install from the monorepo for GLMakie versions above 0.3.4.

If we check the Project.toml file in the GLMakie subdirectory, the newest version now is actually 0.4.6.

What is the output of pkg> st GLMakie? Have you tried updating it via pkg> up GLMakie? If that doesn’t work, you could also try removing it, and then adding it again, I am not sure if it gets picked up automatically if the repository moves and you still have the old version installed. Alternatively, if you add GLMakie in a fresh environment it should definitely work.

(By the way, the bug mentioned in in the OP has already been fixed in the newest release, so you should now be able to just do zoom!(ax.scene, 3), no workaround necessary anymore.)

Sorry to re-open this discussion, but GLMakie resets my zoom when saving too. I’m on GLMakie v0.9.8, and there is no field center in the scene anymore (ax.scene.center). How should I do?

save(...; update=false)

2 Likes

Thank-you. I just wasted an hour trying to get the zoom to stick when saving. Finally found this. It is still a bug that the zoom is undone at the save stage (I’m on CairoMakie v0.11.8). I hope this workaround can be added on the Makie Troubleshooting page. Great package!

Somehow I can still not figure out how to make this work.

Looking at this example

using GLMakie
begin
    fig = Figure() 
    ax = LScene(fig[1,1])

    surface!([-8,-8,8,8],[-8,8,-8,8],[0,0,0,0])
    meshscatter!([1],[1],[1], markersize = 1)

    zoom!(ax.scene, cameracontrols(ax.scene), 0.1)
    #zoom!(ax.scene, cameracontrols(ax.scene), 2.0)
    update_cam!(ax.scene, cameracontrols(ax.scene))
    
    fig
end

No matter which of the zoom! lines I call, it makes no difference in the displayed plot.

It seems that at disp(fig) it adjusts the camera to fit the scene. Is there a way to deactivate that?

(Sorry if the question is already answered, I tried to look for it for quite a while but wasn’t successful.)

Packages in my env:

  [a9b6321e] Atomix v0.1.0
  [052768ef] CUDA v5.3.3
  [e9467ef8] GLMakie v0.9.10
  [5c1252a2] GeometryBasics v0.4.11
  [63c18a36] KernelAbstractions v0.9.18
  [90137ffa] StaticArrays v1.9.3

display(fig, update=false) and save(fig, update=false) should work.

1 Like

Thanks! Also record(..., update=false) works, which is what I needed in my setup.