diff --git a/src/examples.jl b/src/examples.jl index d5bf01f3..418f48f8 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -1081,6 +1081,27 @@ const _examples = PlotExample[ plot!(sin, -π, π, lw=3, color=:red) end] ), + PlotExample( + "3d quiver", + "", + [quote + using Plots + + ϕs = range(-π, π, length=50) + θs = range(0, π, length=25) + θqs = range(1, π-1, length=25) + + x = vec([sin(θ) * cos(ϕ) for (ϕ, θ) in Iterators.product(ϕs, θs)]) + y = vec([sin(θ) * sin(ϕ) for (ϕ, θ) in Iterators.product(ϕs, θs)]) + z = vec([cos(θ) for (ϕ, θ) in Iterators.product(ϕs, θs)]) + + u = 0.1 * vec([sin(θ) * cos(ϕ) for (ϕ, θ) in Iterators.product(ϕs, θqs)]) + v = 0.1 * vec([sin(θ) * sin(ϕ) for (ϕ, θ) in Iterators.product(ϕs, θqs)]) + w = 0.1 * vec([cos(θ) for (ϕ, θ) in Iterators.product(ϕs, θqs)]) + + quiver(x,y,z, quiver=(u,v,w)) + end] + ), ] # Some constants for PlotDocs and PlotReferenceImages @@ -1099,6 +1120,7 @@ _backend_skips = Dict( 32, # spy 49, # polar heatmap 51, # image with custom axes + 52, # 3d quiver ], ) diff --git a/src/recipes.jl b/src/recipes.jl index 80ccc86f..41d36714 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -1197,35 +1197,51 @@ function quiver_using_arrows(plotattributes::AKW) if !isa(plotattributes[:arrow], Arrow) plotattributes[:arrow] = arrow() end - + is_3d = haskey(plotattributes,:z) && !isnothing(plotattributes[:z]) velocity = error_zipit(plotattributes[:quiver]) xorig, yorig = plotattributes[:x], plotattributes[:y] + zorig = is_3d ? plotattributes[:z] : [] # for each point, we create an arrow of velocity vi, translated to the x/y coordinates x, y = zeros(0), zeros(0) - for i = 1:max(length(xorig), length(yorig)) + is_3d && ( z = zeros(0)) + for i = 1:max(length(xorig), length(yorig), is_3d ? 0 : length(zorig)) # get the starting position xi = _cycle(xorig, i) yi = _cycle(yorig, i) - + zi = is_3d ? _cycle(zorig, i) : 0 # get the velocity vi = _cycle(velocity, i) - vx, vy = if istuple(vi) - first(vi), last(vi) - elseif isscalar(vi) - vi, vi - elseif isa(vi, Function) - vi(xi, yi) - else - error("unexpected vi type $(typeof(vi)) for quiver: $vi") + if is_3d + vx, vy, vz = if istuple(vi) + vi[1], vi[2], vi[3] + elseif isscalar(vi) + vi, vi, vi + elseif isa(vi, Function) + vi(xi, yi, zi) + else + error("unexpected vi type $(typeof(vi)) for quiver: $vi") + end + else # 2D quiver + vx, vy = if istuple(vi) + first(vi), last(vi) + elseif isscalar(vi) + vi, vi + elseif isa(vi, Function) + vi(xi, yi) + else + error("unexpected vi type $(typeof(vi)) for quiver: $vi") + end end - # add the points nanappend!(x, [xi, xi + vx, NaN]) nanappend!(y, [yi, yi + vy, NaN]) + is_3d && nanappend!(z, [zi, zi + vz, NaN]) end - plotattributes[:x], plotattributes[:y] = x, y + if is_3d + plotattributes[:z] = z + end # KW[plotattributes] end