Skip to content

Commit

Permalink
Merge pull request #3612 from t-bltg/mesh3d
Browse files Browse the repository at this point in the history
GR: add support for mesh3d
  • Loading branch information
t-bltg committed Jul 9, 2021
2 parents 20e24cf + f5e6ae9 commit 5d608d1
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 31 deletions.
1 change: 1 addition & 0 deletions src/backends.jl
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ const _gr_seriestype = [
:scatter3d,
:surface,
:wireframe,
:mesh3d,
:volume,
:shape,
]
Expand Down
43 changes: 38 additions & 5 deletions src/backends/gr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,7 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims, viewport_plotare
levels = _cbar_unique(contour_levels.(series, Ref(clims)), "levels")
# GR implicitly uses the maximal z value as the highest level
if levels[end] < clims[2]
@warn("GR: highest contour level less than maximal z value is not supported.")
@warn "GR: highest contour level less than maximal z value is not supported."
# replace levels, rather than assign to levels[end], to ensure type
# promotion in case levels is an integer array
levels = [levels[1:end-1]; clims[2]]
Expand Down Expand Up @@ -1682,7 +1682,7 @@ function gr_add_series(sp, series)
end
elseif st === :contour
gr_draw_contour(series, x, y, z, clims)
elseif st in (:surface, :wireframe)
elseif st in (:surface, :wireframe, :mesh3d)
gr_draw_surface(series, x, y, z, clims)
elseif st === :volume
sp[:legend] = :none
Expand Down Expand Up @@ -1838,7 +1838,7 @@ function gr_draw_contour(series, x, y, z, clims)
h = gr_contour_levels(series, clims)
if series[:fillrange] !== nothing
if series[:fillcolor] != series[:linecolor] && !is_lc_black
@warn("GR: filled contour only supported with black contour lines")
@warn "GR: filled contour only supported with black contour lines"
end
GR.contourf(x, y, h, z, series[:contour_labels] == true ? 1 : 0)
else
Expand All @@ -1849,7 +1849,8 @@ end

function gr_draw_surface(series, x, y, z, clims)
e_kwargs = series[:extra_kwargs]
if series[:seriestype] === :surface
st = series[:seriestype]
if st === :surface
fillalpha = get_fillalpha(series)
fillcolor = get_fillcolor(series)
# NOTE: setting nx = 0 or ny = 0 disables GR.gridit interpolation
Expand All @@ -1864,9 +1865,41 @@ function gr_draw_surface(series, x, y, z, clims)
else
GR.gr3.surface(x, y, z, d_opt)
end
else # wireframe
elseif st === :wireframe
GR.setfillcolorind(0)
GR.surface(x, y, z, get(e_kwargs, :display_option, GR.OPTION_FILLED_MESH))
elseif st === :mesh3d
@warn "GR: mesh3d is experimental (no face colors)"
conn = series[:connections]
if typeof(conn) <: Tuple{Array, Array, Array}
ci, cj, ck = conn
if !(length(ci) == length(cj) == length(ck))
throw(ArgumentError("Argument connections must consist of equally sized arrays."))
end
else
throw(ArgumentError("Argument connections has to be a tuple of three arrays."))
end
X = zeros(eltype(x), 4length(ci))
Y = zeros(eltype(y), 4length(cj))
Z = zeros(eltype(z), 4length(ck))
@inbounds for I 1:length(ci)
i = ci[I] + 1 # connections are 0-based
j = cj[I] + 1
k = ck[I] + 1
m = 4(I - 1) + 1; n = m + 1; o = m + 2; p = m + 3
X[m] = X[p] = x[i]
Y[m] = Y[p] = y[i]
Z[m] = Z[p] = z[i]
X[n] = x[j]
Y[n] = y[j]
Z[n] = z[j]
X[o] = x[k]
Y[o] = y[k]
Z[o] = z[k]
end
GR.polyline3d(X, Y, Z)
else
throw(ArgumentError("Not handled !"))
end
end

Expand Down
56 changes: 30 additions & 26 deletions src/examples.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1007,33 +1007,37 @@ const _examples = PlotExample[
end]
),
PlotExample( # 47
"Mesh3d",
"""
Allows to plot arbitrary 3d meshes. If only x,y,z are given the mesh is generated automatically.
You can also specify the connections using the connections keyword.
The connections are specified using a tuple of vectors. Each vector contains the 0-based indices of one point of a triangle,
such that elements at the same position of these vectors form a triangle.
""",
[
:(
begin
# specify the vertices
x=[0, 1, 2, 0]
y=[0, 0, 1, 2]
z=[0, 2, 0, 1]
"Mesh3d",
"""
Allows to plot arbitrary 3d meshes. If only x,y,z are given the mesh is generated automatically.
You can also specify the connections using the connections keyword.
The connections are specified using a tuple of vectors. Each vector contains the 0-based indices of one point of a triangle,
such that elements at the same position of these vectors form a triangle.
""",
[
:(
begin
# specify the vertices
x=[0, 1, 2, 0]
y=[0, 0, 1, 2]
z=[0, 2, 0, 1]

# specify the triangles
# every column is one triangle,
# where the values denote the indices of the vertices of the triangle
i=[0, 0, 0, 1]
j=[1, 2, 3, 2]
k=[2, 3, 1, 3]
# specify the triangles
# every column is one triangle,
# where the values denote the indices of the vertices of the triangle
i=[0, 0, 0, 1]
j=[1, 2, 3, 2]
k=[2, 3, 1, 3]

# the four triangles gives above give a tetrahedron
mesh3d(x,y,z;connections=(i,j,k))
end
),
],
# the four triangles gives above give a tetrahedron
mesh3d(
x, y, z; connections=(i, j, k),
title="triangles", xlabel="x", ylabel="y", zlabel="z",
legend=:none, margin=2Plots.mm
)
end
),
],
),
PlotExample( # 48
"Vectors of markershapes and segments",
Expand Down Expand Up @@ -1223,7 +1227,7 @@ const _examples = PlotExample[
# Some constants for PlotDocs and PlotReferenceImages
_animation_examples = [2, 31]
_backend_skips = Dict(
:gr => [25, 30, 47],
:gr => [25, 30],
:pyplot => [2, 25, 30, 31, 47, 49, 55],
:plotlyjs => [2, 21, 24, 25, 30, 31, 49, 51, 55],
:plotly => [2, 21, 24, 25, 30, 31, 49, 50, 51, 55],
Expand Down

0 comments on commit 5d608d1

Please sign in to comment.