# Drawing 3d polygons in Makie

**URL:** <https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466>\
**Category:** Visualization\
**Tags:** makie\
**Created:** [July 28, 2021, 10:43pm UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466 "2021-07-28T22:43:16Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![t-bltg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/t-bltg/32/25526_2.png) [@t-bltg](https://discourse.julialang.org/u/t-bltg)\
**Post date:** [July 28, 2021, 10:43pm UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/1 "2021-07-28T22:43:16Z")

</div>

I’m trying to draw 3D polygons, but the only working way I found is cumbersome: is there some simple command I missed e.g. `poly(X, Y, Z, color=C)` that will allow me to plot 3D polygons in Makie ?

```julia
using GLMakie

# cols = triangle number (here 4 tris), rows = coordinates for triangle vertex 1->3
X = [0. 1 1 2; 1 1 2 2; 0 0 1 1]
Y = [1. 1 1 1; 1 0 1 0; 0 0 0 0]
Z = [1. 1 1 1; 1 0 1 0; 0 0 0 0]
C = [.5 1. 1. .5; 1. .5 .5 .1667; .333 .333 .5 .5]

ntris = size(X, 2)

# this works, but I find it cumbersome and unefficient
vertices = [Point(X[v, n], Y[v, n], Z[v, n]) for n ∈ 1:ntris for v ∈ 1:3]
indices = [TriangleFace(n, n + 1, n + 2) for n ∈ 1:3:length(X)]
fap = poly(vertices, indices, color=C[:], strokewidth=1)

# fails
shapes = [
  Polygon(
    Point3f0[
      (X[1, n], Y[1, n], Z[1, n]),
      (X[2, n], Y[2, n], Z[2, n]),
      (X[3, n], Y[3, n], Z[3, n]),
    ]
  ) for n ∈ 1:size(X, 2)
]
fap = poly(shapes)
# MethodError: no method matching earcut_triangulate(::Vector{Vector{Point{3, Float32}}})

# converting to Nsimples{3} (triangles) or NNgon{3} (also a triangle) also fails
xyz = reshape([X[:] Y[:] Z[:]]', :)
triangles = connect(connect(xyz, Point{3}), NSimplex{3})
fap = poly(triangles)
# ERROR: `Makie.convert_arguments` for the plot type Scatter{ArgType} where ArgType and its conversion trait PointBased() was unsuccessful.

# wished for, but fails
fap = poly(X, Y, Z, color=C)
# ERROR: `Makie.convert_arguments` for the plot type Scatter{ArgType} where ArgType and its conversion trait PointBased() was unsuccessful.

cam3d!(fap.axis.scene)
display(fap)

```

---

<div class="post-metadata">

**Author:** ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)\
**Post date:** [July 29, 2021, 5:45am UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/2 "2021-07-29T05:45:44Z")

</div>

I’m not sure what a 3D polygon even is? The algorithm to cut a polygon into triangles can only work in 2D, that’s why there’s no 3D convert I think.

---

<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:** [July 29, 2021, 7:47am UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/3 "2021-07-29T07:47:33Z")

</div>

Some definition in the internet: _Polygons are straight-sided shapes (3 or more sides), defined by three-dimensional points (vertices) and the straight lines that connect them (edges)._

But it seems they mean a 2d polygon rotated in 3d space.

---

<div class="post-metadata">

**Author:** ![t-bltg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/t-bltg/32/25526_2.png) [@t-bltg](https://discourse.julialang.org/u/t-bltg)\
**Post date:** [July 29, 2021, 8:32am UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/4 "2021-07-29T08:32:33Z")

</div>

Yes, polygons are mathematically defined in 3D. I guess then I will submit a patch to avoid calling `earcut_triangulate` since there is no need for triangulation here.

Something more compact, but not as compact as wished for:

```julia
faces = [TriangleFace(n, n + 1, n + 2) for n ∈ 1:3:length(X)]
fap = poly(connect(reshape([X[:] Y[:] Z[:]]', :), Point{3}), faces, color=C[:], strokewidth=1)

```

---

<div class="post-metadata">

**Author:** ![t-bltg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/t-bltg/32/25526_2.png) [@t-bltg](https://discourse.julialang.org/u/t-bltg)\
**Post date:** [July 29, 2021, 10:20am UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/5 "2021-07-29T10:20:18Z")

</div>

I found an acceptable solution to this:

```julia
using GeometryBasics, GLMakie

X = [0. 1 1 2; 1 1 2 2; 0 0 1 1]
Y = [1. 1 1 1; 1 0 1 0; 0 0 0 0]
Z = [1. 1 1 1; 1 0 1 0; 0 0 0 0]
C = [.5 1. 1. .5; 1. .5 .5 .1667; .333 .333 .5 .5]

xyz = reshape([X[:] Y[:] Z[:]]', :)
fap = poly(connect(xyz, Point{3}), connect(1:length(X), TriangleFace); color=C[:], strokewidth=1)

display(fap)

```

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [July 29, 2021, 10:29am UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/6 "2021-07-29T10:29:09Z")

</div>

You can also do something like:

```julia
xyz = connect(xyz, Point{3})
xy = Point2f0.(xyz)
f = faces(Polygon(xy))
m = GeometryBascis.Mesh(xyz, f)
Makie.mesh(m, color=C[:])

```

---

<div class="post-metadata">

**Author:** ![t-bltg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/t-bltg/32/25526_2.png) [@t-bltg](https://discourse.julialang.org/u/t-bltg)\
**Post date:** [July 29, 2021, 10:35am UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/7 "2021-07-29T10:35:45Z")

</div>

Hi Simon, unfortunately, that seems to fail:

```julia
xyz = connect(xyz, Point{3})
poly(GeometryBasics.Mesh(xyz, GeometryBasics.faces(Polygon(Point2f0.(xyz)))))
# ERROR: Metadata needs to be an array with the same length as data items. Found: Bool

```

---

<div class="post-metadata">

**Author:** ![goretkin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goretkin/32/167_2.png) [@goretkin](https://discourse.julialang.org/u/goretkin)\
**Post date:** [August 18, 2021, 11:45pm UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/8 "2021-08-18T23:45:49Z")

</div>

What I’d like is to specify a polygon in 2D, and then provide an affine transformation into the 3D scene. Is there a way to do that?

---

<div class="post-metadata">

**Author:** ![sdanisch](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sdanisch/32/1406_2.png) [@sdanisch](https://discourse.julialang.org/u/sdanisch)\
**Post date:** [August 19, 2021, 10:37am UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/9 "2021-08-19T10:37:20Z")

</div>

Huh, somehow it doesn’t like the return value from connect…  
Try:

```julia
 m = GeometryBasics.Mesh(Point3f0.(xyz), f)

```

@goretkin:  
Uh, in theory yes, but it seems so under tested right now, that I can’t get it to work… Will take a look later!

---

<div class="post-metadata">

**Author:** ![goretkin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goretkin/32/167_2.png) [@goretkin](https://discourse.julialang.org/u/goretkin)\
**Post date:** [September 7, 2021, 3:33pm UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/10 "2021-09-07T15:33:15Z")

</div>

Is there generally some way of embedding an `Axis` into an `Axis3`? Not exactly, but similar to

[https://matplotlib.org/2.0.2/examples/mplot3d/2dcollections3d\_demo.html](https://matplotlib.org/2.0.2/examples/mplot3d/2dcollections3d_demo.html)  
 ![image](https://global.discourse-cdn.com/julialang/original/3X/6/c/6c7f1ba2b90344c706264c74baf0b33310f44244.png)

> <https://github.com/matplotlib/matplotlib/issues/3919>
>
> Is it possible to create plots like the one below with matplotlib? If not, would… it be difficult to add support for such plots in the mplot3d backend?
> 
> !\[slice\](http://www.dartmouth.edu/~rc/classes/visit/three\_slice.gif)
> 
> I know that such plots can be created with VTK but VTK is still limited to python 2 :-1:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/f/2/f2de52d2087f52a4c6de5f61fd484de0f074054c.png)

Edit: I realize there is [https://makie.juliaplots.org/v0.15.2/examples/plotting\_functions/volumeslices/index.html](https://makie.juliaplots.org/v0.15.2/examples/plotting_functions/volumeslices/index.html) , but I tried to mean a general way to plot into 2D subspaces of a 3D axis, not specifically volume slices.

---

<div class="post-metadata">

**Author:** ![lazarusA](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lazarusa/32/6571_2.png) [@lazarusA](https://discourse.julialang.org/u/lazarusA)\
**Post date:** [September 7, 2021, 4:44pm UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/11 "2021-09-07T16:44:48Z")

</div>

Not sure if your are asking for `transformation = (:yz, a)`, as in

```julia
heatmap(x, y, z; colormap = :viridis,
        transformation = (:yz, 3.5))

```

you can basically plot on any plane at any position. See section 6.7.2 Surfaces, wireframe, contour, contourf and contour3d at [GLMakie.jl - Julia Data Science](https://juliadatascience.io/glmakie)

---

<div class="post-metadata">

**Author:** ![rveltz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rveltz/32/2707_2.png) [@rveltz](https://discourse.julialang.org/u/rveltz)\
**Post date:** [April 24, 2024, 2:26pm UTC](https://discourse.julialang.org/t/drawing-3d-polygons-in-makie/65466/12 "2024-04-24T14:26:55Z")

</div>

Is it still the recommanded solution?
