# (Plots.jl) aspect\_ratio=1.0 for 3d plot

**URL:** <https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607>\
**Category:** Visualization\
**Tags:** plotting, plots\
**Created:** [April 5, 2021, 10:57am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607 "2021-04-05T10:57:08Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [April 5, 2021, 10:57am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/1 "2021-04-05T10:57:08Z")

</div>

# Issue

I don’t know how to set `aspect_ratio=:equal` for 3d plot (like `axis_equal` in `MATLAB`).  
It seems that only `x` and `y` axes’ aspect ratio are equal.

## Example code

```julia
using Plots

function test()
    N = 10
    xs = range(0, stop=10, length=N)
    ys = range(0, stop=20, length=N)
    zs = range(0, stop=50, length=N)
    p = plot(; aspect_ratio=1.0)
    plot!(xs, ys, zs)
end
test()

```

## Result

 ![image](https://global.discourse-cdn.com/julialang/original/3X/7/2/7254ff9a7d30d6a81decd9b997dc1ee985a55733.jpeg)

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [April 5, 2021, 1:35pm UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/2 "2021-04-05T13:35:48Z")

</div>

@iHany, see revised improved solution using `gr()` backend below.

```julia
using Plots; gr(size=(600,600))

function plot_iso3d(xs, ys, zs; lw=3, lc=:red, title="Isometric 3D plot",label=false, camera=(45,30))
    # condition data for nearly isometric 3D plot 
    x12, y12, z12 = extrema(xs), extrema(ys), extrema(zs)
    d = maximum([diff([x12...]),diff([y12...]),diff([z12...])])[1] / 2
    xm, ym, zm = mean(x12), mean(y12), mean(z12) 

    # plot data
    p = Plots.plot(; xlabel="x",ylabel="y",zlabel="z", aspect_ratio=:equal, grid=:true)
    Plots.plot!(xlims=(xm-d,xm+d), ylims=(ym-d,ym+d), zlims=(zm-d,zm+d))
    Plots.plot!(;camera=camera) #(azimuth,elevation) ???
    Plots.plot!(xs, ys, zs, title=title,lw=lw,lc=lc,label=label)
    Plots.plot!(xs, ys, zlims(p)[1] .+ 0*zs, lw=1, lc=:lightgray, label=false)
    Plots.plot!(xs, ylims(p)[2] .+ 0*ys, zs, lw=1, lc=:lightgray, label=false)
    Plots.plot!(xlims(p)[1] .+ 0*xs, ys, zs, lw=1, lc=:lightgray, label=false)
end

#input data
N = 100
xs = LinRange(0,40,N)
ys = LinRange(0,20,N) .+ 10*sin.(xs)
zs = LinRange(-10,50,N) .+ 15*sin.(xs)
plot_iso3d(xs, ys, zs)

```

 ![Isometric_3d_plot_with_shadow](https://global.discourse-cdn.com/julialang/original/3X/5/b/5b90973c45b2767608ee398bc44e2d61f0c8dce1.png)

---

<div class="post-metadata">

**Author:** ![gustaphe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gustaphe/32/18174_2.png) [@gustaphe](https://discourse.julialang.org/u/gustaphe)\
**Post date:** [April 6, 2021, 7:13am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/3 "2021-04-06T07:13:02Z")

</div>

Minor addition: one thing that always bothered me about doing this sort of thing in Matlab was that it wouldn’t actually do the exact same thing as automatic axis limits, because it didn’t expose the limit widening algorithm.

In Julia,

```julia
plot(x, y; xlims=Plots.widen(xmin, xmax))

```

gets rid of that problem. Just a bit of added sugar.

---

<div class="post-metadata">

**Author:** ![iHany](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ihany/32/18151_2.png) [@iHany](https://discourse.julialang.org/u/iHany)\
**Post date:** [April 6, 2021, 8:08am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/4 "2021-04-06T08:08:24Z")

</div>

Oh no, it’s the best? Seriously?

It works well but is quite uncomfortable ☹

Anyhow, thanks 🙂

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [April 6, 2021, 8:24am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/5 "2021-04-06T08:24:04Z")

</div>

“improved” != best  
🙂

There were related questions and PRs in github, etc…, the best solution is in the hands of Plots.jl code developers.

_NB: The road ahead is straight but the slope is steep…_

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [April 6, 2021, 11:46am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/6 "2021-04-06T11:46:15Z")

</div>

@iHany, updated iso plot 3d above, with shadow projections added.

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [April 19, 2021, 9:38am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/7 "2021-04-19T09:38:53Z")

</div>

Hi, I think that the key line of @rafael.guerra’s solution is:

```julia
using Plots; gr(size=(600,600))

```

At least at first sight, it seems that the attribute `aspect_ratio=1.0` (or `aspect_ratio=:equal`) does work for 3d, but assumes that the figure canvas has square proportions – which is not true by default.

If you don’t want to reset the default figure size, you can also set it for a particular plot:

```julia
plot(x,y,z, aspect_ratio=1.0, size=(600,600))

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [April 19, 2021, 10:02am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/8 "2021-04-19T10:02:54Z")

</div>

@heliosdrm, the key lines in the solution posted above lie immediately below the comment:

```julia
# condition data for nearly isometric 3D plot 
...

```

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [April 19, 2021, 11:20am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/9 "2021-04-19T11:20:58Z")

</div>

Maybe I’m understanding a different point from @iHany 's original question? I interpreted that the problem was that the Z axis in his example looked squashed with respect to the X and Y axes, in spite of having set the attribute `aspect_ratio=1.0`. My point was that the only that has to be done to see the Z axis with the desired proportion is adding `size=(600,600)` in the call to either `gr` or `plot`.

(Edit: or `size=(n,n)`, for whatever `n` is wanted).

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [April 19, 2021, 11:25am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/10 "2021-04-19T11:25:53Z")

</div>

That is obviously not enough, and will be data dependent.  
For the original example given by OP, it will produce the plot below which is far from having aspect ratio = 1:

 ![Plot_not_isometric_if_using_size_only](https://global.discourse-cdn.com/julialang/original/3X/2/4/2413bb52db1f1ed5a20247a8d9c468020026b8d5.png)

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [April 19, 2021, 11:53am UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/11 "2021-04-19T11:53:09Z")

</div>

You are right: silly oversight from my side. 😊

---

<div class="post-metadata">

**Author:** ![scheinerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scheinerman/32/35303_2.png) [@scheinerman](https://discourse.julialang.org/u/scheinerman)\
**Post date:** [March 30, 2024, 4:17pm UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/12 "2024-03-30T16:17:30Z")

</div>

I’m wondering if there is any update to this because I’m having problems with 3D drawing in which the axes are not all equally spaced.

I am using `Plots` with the `GR` backend.

I was able to draw this ball, centered at the origin, just fine:

 ![ball](https://global.discourse-cdn.com/julialang/original/3X/1/8/18dabed5e6119737435ee199e4580d76f4beee2b.png)

But now I want to draw a rectangle to show the horizontal plane. When I do, the ball gets squished:

 ![ball+xy](https://global.discourse-cdn.com/julialang/original/3X/1/4/14375fc9fc4fc35a082991ce76b3d90f18c0d3db.png)

No amount of playing around with `plot!(aspectratio=??)` seems to help. How to fix??

Thanks.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [March 30, 2024, 5:20pm UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/13 "2024-03-30T17:20:08Z")

</div>

If you use the workaround provided above, which defines isometric cubic plot limits around the plot center, then the keyword `aspect_ratio=:equal` will work fine:

 ![Plots_3D_isometric_globe_with_a_plane](https://global.discourse-cdn.com/julialang/original/3X/7/0/70031a48dc31f1335cbd8780a7cb17ded5fce08e.png)

> **Code: Plots 3D isometric globe + plane**
>
> ```julia
> using Plots; gr(dpi=600)
> 
> # Plot meridians and parallels
> p = plot(framestyle=:none, ticks=:none)
> v = range(π/20, 19π/20, 100)
> for u in range(0, 2*π, 13)
> plot!(cos(u) * sin.(v), sin(u) * sin.(v), cos.(v), c=:lightgrey, lw=0.5)
> end
> u = range(0, 2π, 100)
> for v in range(π/20, 19π/20, 9)
> plot!(cos.(u) * sin(v), sin.(u) * sin(v), fill(cos(v),100), c=:lightgrey, lw=0.5)
> end
> 
> # Plot plane
> d = 3/2 # plane edge half-length (also equal here to the plot limits half-length cube edge) 
> plot!([-d,d,d,-d,-d], [-d,-d,d,d,-d], [0,0,0,0,0], c=:lightgrey)
> 
> # define isometric cube limits around plot center
> xm, ym, zm = 0, 0, 0 # center of the plot
> plot!(xlims=(xm-d,xm+d), ylims=(ym-d,ym+d), zlims=(zm-d,zm+d), aspect_ratio=:equal)
> 
> ```

---

<div class="post-metadata">

**Author:** ![scheinerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scheinerman/32/35303_2.png) [@scheinerman](https://discourse.julialang.org/u/scheinerman)\
**Post date:** [March 30, 2024, 7:22pm UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/14 "2024-03-30T19:22:01Z")

</div>

Wow! @rafael.guerra, you created the figure I was starting with. (I have more to do, but this is where I got into trouble.)

I’m trying to extract from the code in the examples what I need to do in my plotting. Can you provide the code you used to create the image I was hoping to make?

---

<div class="post-metadata">

**Author:** ![scheinerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scheinerman/32/35303_2.png) [@scheinerman](https://discourse.julialang.org/u/scheinerman)\
**Post date:** [March 30, 2024, 7:33pm UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/15 "2024-03-30T19:33:34Z")

</div>

PS Is this issue that I need to do something like this?

`plot!(xlims=(-r,r),ylims=(-r,r),zlims=(-r,r))`

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [March 30, 2024, 7:37pm UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/16 "2024-03-30T19:37:11Z")

</div>

Correct.

For plots whose centroid is not at the origin, the plot boundary cube is better defined around the centroid.

Note that ` xlims=(-r,r),ylims=(-r,r),zlims=(-r,r)` === `lims=(-r,r)`

_PS: I have included the code I used below the plot above._

---

<div class="post-metadata">

**Author:** ![scheinerman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/scheinerman/32/35303_2.png) [@scheinerman](https://discourse.julialang.org/u/scheinerman)\
**Post date:** [March 30, 2024, 7:43pm UTC](https://discourse.julialang.org/t/plots-jl-aspect-ratio-1-0-for-3d-plot/58607/17 "2024-03-30T19:43:25Z")

</div>

Got it! And now it’s working for me. Thank you!!
