Drawing 3d polygons in Makie

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 ?

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)

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.

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.

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:

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)

I found an acceptable solution to this:

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)

You can also do something like:

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

Hi Simon, unfortunately, that seems to fail:

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

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?

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

 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!

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
image

Edit: I realize there is 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.

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

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

3 Likes

Is it still the recommanded solution?