Merge pull request #3612 from t-bltg/mesh3d

GR: add support for mesh3d
This commit is contained in:
t-bltg 2021-07-09 23:15:17 +02:00 committed by GitHub
commit 5d608d1e77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 69 additions and 31 deletions

View File

@ -353,6 +353,7 @@ const _gr_seriestype = [
:scatter3d, :scatter3d,
:surface, :surface,
:wireframe, :wireframe,
:mesh3d,
:volume, :volume,
:shape, :shape,
] ]

View File

@ -524,7 +524,7 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims, viewport_plotare
levels = _cbar_unique(contour_levels.(series, Ref(clims)), "levels") levels = _cbar_unique(contour_levels.(series, Ref(clims)), "levels")
# GR implicitly uses the maximal z value as the highest level # GR implicitly uses the maximal z value as the highest level
if levels[end] < clims[2] 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 # replace levels, rather than assign to levels[end], to ensure type
# promotion in case levels is an integer array # promotion in case levels is an integer array
levels = [levels[1:end-1]; clims[2]] levels = [levels[1:end-1]; clims[2]]
@ -1682,7 +1682,7 @@ function gr_add_series(sp, series)
end end
elseif st === :contour elseif st === :contour
gr_draw_contour(series, x, y, z, clims) 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) gr_draw_surface(series, x, y, z, clims)
elseif st === :volume elseif st === :volume
sp[:legend] = :none sp[:legend] = :none
@ -1838,7 +1838,7 @@ function gr_draw_contour(series, x, y, z, clims)
h = gr_contour_levels(series, clims) h = gr_contour_levels(series, clims)
if series[:fillrange] !== nothing if series[:fillrange] !== nothing
if series[:fillcolor] != series[:linecolor] && !is_lc_black 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 end
GR.contourf(x, y, h, z, series[:contour_labels] == true ? 1 : 0) GR.contourf(x, y, h, z, series[:contour_labels] == true ? 1 : 0)
else else
@ -1849,7 +1849,8 @@ end
function gr_draw_surface(series, x, y, z, clims) function gr_draw_surface(series, x, y, z, clims)
e_kwargs = series[:extra_kwargs] e_kwargs = series[:extra_kwargs]
if series[:seriestype] === :surface st = series[:seriestype]
if st === :surface
fillalpha = get_fillalpha(series) fillalpha = get_fillalpha(series)
fillcolor = get_fillcolor(series) fillcolor = get_fillcolor(series)
# NOTE: setting nx = 0 or ny = 0 disables GR.gridit interpolation # NOTE: setting nx = 0 or ny = 0 disables GR.gridit interpolation
@ -1864,9 +1865,41 @@ function gr_draw_surface(series, x, y, z, clims)
else else
GR.gr3.surface(x, y, z, d_opt) GR.gr3.surface(x, y, z, d_opt)
end end
else # wireframe elseif st === :wireframe
GR.setfillcolorind(0) GR.setfillcolorind(0)
GR.surface(x, y, z, get(e_kwargs, :display_option, GR.OPTION_FILLED_MESH)) 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
end end

View File

@ -1007,33 +1007,37 @@ const _examples = PlotExample[
end] end]
), ),
PlotExample( # 47 PlotExample( # 47
"Mesh3d", "Mesh3d",
""" """
Allows to plot arbitrary 3d meshes. If only x,y,z are given the mesh is generated automatically. 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. 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, 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. such that elements at the same position of these vectors form a triangle.
""", """,
[ [
:( :(
begin begin
# specify the vertices # specify the vertices
x=[0, 1, 2, 0] x=[0, 1, 2, 0]
y=[0, 0, 1, 2] y=[0, 0, 1, 2]
z=[0, 2, 0, 1] z=[0, 2, 0, 1]
# specify the triangles # specify the triangles
# every column is one triangle, # every column is one triangle,
# where the values denote the indices of the vertices of the triangle # where the values denote the indices of the vertices of the triangle
i=[0, 0, 0, 1] i=[0, 0, 0, 1]
j=[1, 2, 3, 2] j=[1, 2, 3, 2]
k=[2, 3, 1, 3] k=[2, 3, 1, 3]
# the four triangles gives above give a tetrahedron # the four triangles gives above give a tetrahedron
mesh3d(x,y,z;connections=(i,j,k)) mesh3d(
end x, y, z; connections=(i, j, k),
), title="triangles", xlabel="x", ylabel="y", zlabel="z",
], legend=:none, margin=2Plots.mm
)
end
),
],
), ),
PlotExample( # 48 PlotExample( # 48
"Vectors of markershapes and segments", "Vectors of markershapes and segments",
@ -1223,7 +1227,7 @@ const _examples = PlotExample[
# Some constants for PlotDocs and PlotReferenceImages # Some constants for PlotDocs and PlotReferenceImages
_animation_examples = [2, 31] _animation_examples = [2, 31]
_backend_skips = Dict( _backend_skips = Dict(
:gr => [25, 30, 47], :gr => [25, 30],
:pyplot => [2, 25, 30, 31, 47, 49, 55], :pyplot => [2, 25, 30, 31, 47, 49, 55],
:plotlyjs => [2, 21, 24, 25, 30, 31, 49, 51, 55], :plotlyjs => [2, 21, 24, 25, 30, 31, 49, 51, 55],
:plotly => [2, 21, 24, 25, 30, 31, 49, 50, 51, 55], :plotly => [2, 21, 24, 25, 30, 31, 49, 50, 51, 55],