# 3D polygons in Plots.jl

**URL:** <https://discourse.julialang.org/t/3d-polygons-in-plots-jl/9761>\
**Category:** General Usage\
**Tags:** plotting, polygons\
**Created:** [March 16, 2018, 6:23pm UTC](https://discourse.julialang.org/t/3d-polygons-in-plots-jl/9761 "2018-03-16T18:23:40Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rcnlee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rcnlee/32/4107_2.png) [@rcnlee](https://discourse.julialang.org/u/rcnlee)\
**Post date:** [March 16, 2018, 6:23pm UTC](https://discourse.julialang.org/t/3d-polygons-in-plots-jl/9761/1 "2018-03-16T18:23:40Z")

</div>

Is there an equivalent to Matlab’s `fill3` in Plots.jl to create filled shapes in 3D?

> **[Create filled 3-D patches - MATLAB fill3](https://www.mathworks.com/help/matlab/ref/fill3.html)**
>
> This MATLAB function plots filled polygonal regions on 3-D axes as Patch objects with vertices at the (x,y,z) locations specified by X, Y, and Z.

I see `Plots.Shape`, but it looks like it only supports 2D.

Thanks!

---

<div class="post-metadata">

**Author:** ![rcnlee](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rcnlee/32/4107_2.png) [@rcnlee](https://discourse.julialang.org/u/rcnlee)\
**Post date:** [March 16, 2018, 7:23pm UTC](https://discourse.julialang.org/t/3d-polygons-in-plots-jl/9761/2 "2018-03-16T19:23:12Z")

</div>

I found it. Looks like setting `seriestype=:surface` will do it.

---

<div class="post-metadata">

**Author:** ![Brad\_Hines](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brad_hines/32/9885_2.png) [@Brad\_Hines](https://discourse.julialang.org/u/Brad_Hines)\
**Post date:** [September 2, 2019, 4:09am UTC](https://discourse.julialang.org/t/3d-polygons-in-plots-jl/9761/3 "2019-09-02T04:09:00Z")

</div>

**Summary**

An arguably better way to plot 3D polygons, that works even when your polygon lies in a vertical plane. This should be of special interest to people who want to mimic Matlab’s `fill3d()` in Julia.

The solution presented is for raw PyPlots. Hopefully somebody can massage it into something that works with Plots.jl.

I’d also be interested to hear if anyone has any success plotting polygons with holes in them. Probably the Python libraries have the capability to do this, but I am not very familiar with them. That’s another thing that’s probably pretty hard with `surf()`. _(Polygons with holes aren’t too hard in 2D - you can just draw the outline in one color then draw the holes in another. But in 3D, the “holes” are never quite in the same plane as the main polygon at the 10th decimal place, so you get weird effects.)_

**Details**

_ **Background** _  
For folks that have been following other threads, I’ve been fighting with this a bit. I’ve had issues getting the PyPlot backend to work when used from a script - it works fine interactively, but from a script I get that “\_display is not defined” when I call `PyPlot.gui()`, and I haven’t been able to resolve that and haven’t seen anything about it online.

In any event, I switched to using straight PyPlot, and started plotting 3D polygons using `surf()` in PyPlot, which is the raw-PyPlot equivalent to the suggestion by rcnlee from March 2018.

_ **The problem I’m trying to solve** _  
What I ran into is that the PyPlot “surf” approach works fairly well, but at its core it appears to be a package that says “give me a z for every x and y”, and if you have a polygon that lies entirely in a vertical plane (e.g. every x-y-z point has x=0), it complains.

Some research indicated that what you want is to use the “Poly3DCollection” from matplotlib.pyplots and mpl\_toolkits.mplot3d. I have verified that this makes nice clean polygons, a la Matlab fill3d.

_ **What I came up with** _  
After long futzing, reading the PyPlot code, and so on, I’ve come up with this. I am far from an expert, so I’m sure I’ll say some things wrong, but here is a set of steps.

First. get mplot3d. I think this step is required but not sure. This is also necessary in order to access certain PyPlot functions, I believe.

```julia
Pkg.add("PyCall")
using Pycall
pyimport_conda(“mpl_toolkits.mplot3d”, “mpl_toolkits”)

```

Now, at the root of what we want to do is call into Python’s `ax.add_collection3d()` and add a `Poly3DCollection` to the plot. That will render a polygon, even a vertical one.

Here is a code example that draws two polygons, including a vertical one, and also shows how to use some of the other options available. It also shows how you can mix native PyPlot calls with pycalls that reach more deeply into the 3D polygon objects and axes.

```julia
#####################
# Demo of 3D polygons including a vertical surface
#

using PyPlot
using PyCall
fig = figure()
art3d = PyObject(PyPlot.art3D)

# I use semicolons instead of commas, becaues I think of these as column
# vectors. It doesn't really matter, but I guess I'm a purist.
xc = [0;0;1;1]
yc = [0;1;1;0]
zc = [1;1;2;2]
verts = (collect(zip(xc,yc,zc)),)
p3c = PyObject(art3d.Poly3DCollection(verts))

# This is necessary in order to get to a 3D axis
ax = gca(projection="3d")
# PyObject, PyPlot allows us use obj[:function_name] to call the member function
# ax[:plot](x, y, z). But add_collection3d is not one of the symbols it
# defines. This is what it would do if it were defined.
pycall(ax.add_collection3d, PyAny, p3c)

# Here I simply list them as points rather than x-y-z arrays
# Then you don't have to zip() them, and this is arguably more natural
# Just including this variant in case it's useful to anyone
p1 = [0;0;1]
p2 = [0;1;1]
p3 = [0;1;2]
p4 = [0;0;2]
verts2 = ([tuple(p1...); tuple(p2...); tuple(p3...); tuple(p4...)],)

p3c2 = PyObject(art3d.Poly3DCollection(verts2, alpha=0.5))
face_color = [1, 0, 0]
pycall(p3c2.set_facecolor, PyAny, face_color)
pycall(ax.add_collection3d, PyAny, p3c2)
ax.view_init(50,30)
zlim(0,2)

```

And the result:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/7/4/74a92ddbd36d58986283068adeb66dfa58472477.png)

Hopefully this helps the next person.

Brad

---

<div class="post-metadata">

**Author:** ![roi.holtzman](https://avatars.discourse-cdn.com/v4/letter/r/f05b48/32.png) [@roi.holtzman](https://discourse.julialang.org/u/roi.holtzman)\
**Post date:** [April 24, 2020, 8:05pm UTC](https://discourse.julialang.org/t/3d-polygons-in-plots-jl/9761/4 "2020-04-24T20:05:38Z")

</div>

I was wondering if these days there is a way to this in Julia? (I would like to plot a cylinder along the z axis).

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [April 24, 2020, 8:55pm UTC](https://discourse.julialang.org/t/3d-polygons-in-plots-jl/9761/5 "2020-04-24T20:55:01Z")

</div>

Makie is the best option for this.
