Makie: get 3D axis limits

Hi,

I can’t for the life of me find I way to retrieve the current axis limits for 3D Makie plots.

I can’t even find I nice way to do this for 2D plots, though you can get there with a lot of effort:

julia> scatter(randn(2, 100))

julia> function projview_to_2d_limits(pv)
           xlim = minmax((((-1, 1) .- pv[1, 4]) ./ pv[1, 1])...)
           ylim = minmax((((-1, 1) .- pv[2, 4]) ./ pv[2, 2])...)
           xlim, ylim
       end
projview_to_2d_limits (generic function with 1 method)

julia> projview_to_2d_limits(current_axis().scene.camera.projectionview[])
((-3.1745217f0, 3.1172993f0), (-2.965359f0, 3.0535767f0))

Any ideas? This strikes me as elementary. I expected there to be functions like xlims() to complement xlims!(xmin, xmax) like in Plots.jl.


The reason I’m wanting to do this is to plot some infinite lines of the form ax + by + cz = 0. I’m doing this by finding two points on either side of the view limits and connecting them with a line segment.

For 2D it seems like this works:

julia> using GLMakie

julia> fig,ax = scatter(rand(10))

julia> ax.yaxis.attributes.limits[]
(-0.03870934f0, 0.95527744f0)

julia> ax.xaxis.attributes.limits[]
(0.55f0, 10.45f0)

3D axis are a mystery to me

3 Likes

Another piece of the puzzle: after much digging I’ve found what looks like the current LScene’s limits cuboid:

julia> scatter([(-1, -2, -3), (1, 2, 3)])

julia> current_axis().scene.plots[1].input_args[1][]
GeometryBasics.HyperRectangle{3, Float32}(Float32[-1.0, -2.0, -3.0], Float32[2.0, 4.0, 6.0])

julia> [ans.origin ans.widths]
3×2 StaticArraysCore.SMatrix{3, 2, Float32, 6} with indices SOneTo(3)×SOneTo(2):
 -1.0  2.0
 -2.0  4.0
 -3.0  6.0

I think this only works for LScene axis types, not Axis3, and it assumes that the plot at index 1 is the <:Combined{Makie.axis3d} which carries view limits data. Not sure if this can be relied on.

And another piece!

For Axis3 plots, there’s the finallimits property:

julia> fig = Figure(); Axis3(fig[1,1]);

julia> scatter!([(-1,-2,-3), (1, 2, 3)])

julia> current_axis().finallimits[]
GeometryBasics.HyperRectangle{3, Float32}(Float32[-1.1, -2.2, -3.3], Float32[2.2, 4.4, 6.6])

julia> [ans.origin ans.widths]
3×2 StaticArraysCore.SMatrix{3, 2, Float32, 6} with indices SOneTo(3)×SOneTo(2):
 -1.1  2.2
 -2.2  4.4
 -3.3  6.6

I’ve almost solved it. I just need to consolidate these different pieces together into something reliable…

For Axis and Axis3:

f, a, p = scatter(rand(Point2f, 10))
a.finallimits[]

For LScene (or Scene) limits/bounding boxes aren’t kept around anymore, but you can grab eyeposition, lookat and upvector from the camera:

f, a, p = scatter(rand(Point3f, 10))
Makie.camera_controls(p).eyeposition

Alternatively you can copy this to get the bounding box the camera uses as a base Makie.jl/scenes.jl at 156e651ffd1b20eed3f511f925c1e8ac4eed1474 · MakieOrg/Makie.jl · GitHub. (Use Makie.parent_scene(p) or a.blockscene.children[1] as the scene here.) This is the combined bounding box of plots though, which might be quite different from your current view (due to zooming and translation).