code and utils for plotly shapes
This commit is contained in:
parent
ed243f4e3e
commit
e8ade18d47
@ -40,7 +40,7 @@ supported_args(::PlotlyBackend) = [
|
|||||||
|
|
||||||
supported_types(::PlotlyBackend) = [
|
supported_types(::PlotlyBackend) = [
|
||||||
:path, :scatter, :bar, :pie, :heatmap,
|
:path, :scatter, :bar, :pie, :heatmap,
|
||||||
:contour, :surface, :path3d, :scatter3d
|
:contour, :surface, :path3d, :scatter3d, :shape
|
||||||
]
|
]
|
||||||
supported_styles(::PlotlyBackend) = [:auto, :solid, :dash, :dot, :dashdot]
|
supported_styles(::PlotlyBackend) = [:auto, :solid, :dash, :dot, :dashdot]
|
||||||
supported_markers(::PlotlyBackend) = [
|
supported_markers(::PlotlyBackend) = [
|
||||||
@ -321,6 +321,17 @@ function plotly_subplot_index(sp::Subplot)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# the Shape contructor will automatically close the shape. since we need it closed,
|
||||||
|
# we split by NaNs and then construct/destruct the shapes to get the closed coords
|
||||||
|
function plotly_close_shapes(x, y)
|
||||||
|
xs, ys = nansplit(x), nansplit(y)
|
||||||
|
for i=1:length(xs)
|
||||||
|
shape = Shape(xs[i], ys[i])
|
||||||
|
xs[i], ys[i] = shape_coords(shape)
|
||||||
|
end
|
||||||
|
nanvcat(xs), nanvcat(ys)
|
||||||
|
end
|
||||||
|
|
||||||
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
|
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
|
||||||
function plotly_series(plt::Plot, series::Series)
|
function plotly_series(plt::Plot, series::Series)
|
||||||
d = series.d
|
d = series.d
|
||||||
@ -338,7 +349,8 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
st = d[:seriestype]
|
st = d[:seriestype]
|
||||||
isscatter = st in (:scatter, :scatter3d)
|
isscatter = st in (:scatter, :scatter3d)
|
||||||
hasmarker = isscatter || d[:markershape] != :none
|
hasmarker = isscatter || d[:markershape] != :none
|
||||||
hasline = !isscatter
|
# hasline = !isscatter
|
||||||
|
hasline = st in (:path, :path3d)
|
||||||
|
|
||||||
# set the "type"
|
# set the "type"
|
||||||
if st in (:path, :scatter)
|
if st in (:path, :scatter)
|
||||||
@ -356,6 +368,25 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
end
|
end
|
||||||
d_out[:x], d_out[:y] = x, y
|
d_out[:x], d_out[:y] = x, y
|
||||||
|
|
||||||
|
elseif st == :shape
|
||||||
|
# to draw polygons, we actually draw lines with fill
|
||||||
|
d_out[:type] = "scatter"
|
||||||
|
d_out[:mode] = "lines"
|
||||||
|
d_out[:x], d_out[:y] = plotly_close_shapes(x, y)
|
||||||
|
# @show map(length, (x,y,d_out[:x],d_out[:y]))
|
||||||
|
# @show d_out[:x] d_out[:y]
|
||||||
|
d_out[:fill] = "tozeroy"
|
||||||
|
d_out[:fillcolor] = webcolor(d[:markercolor], d[:markeralpha])
|
||||||
|
if d[:markerstrokewidth] > 0
|
||||||
|
d_out[:line] = KW(
|
||||||
|
:color => webcolor(d[:markerstrokecolor], d[:markerstrokealpha]),
|
||||||
|
:width => d[:markerstrokewidth],
|
||||||
|
:dash => string(d[:markerstrokestyle]),
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
elseif st == :bar
|
elseif st == :bar
|
||||||
d_out[:type] = "bar"
|
d_out[:type] = "bar"
|
||||||
d_out[:x], d_out[:y] = x, y
|
d_out[:x], d_out[:y] = x, y
|
||||||
|
|||||||
@ -12,8 +12,15 @@ compute_angle(v::P2) = (angle = atan2(v[2], v[1]); angle < 0 ? 2π - angle : ang
|
|||||||
# -------------------------------------------------------------
|
# -------------------------------------------------------------
|
||||||
|
|
||||||
immutable Shape
|
immutable Shape
|
||||||
x::AVec
|
x::Vector{Float64}
|
||||||
y::AVec
|
y::Vector{Float64}
|
||||||
|
function Shape(x::AVec, y::AVec)
|
||||||
|
if x[1] != x[end] || y[1] != y[end]
|
||||||
|
new(vcat(x, x[1]), vcat(y, y[1]))
|
||||||
|
else
|
||||||
|
new(x, y)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
Shape(verts::AVec) = Shape(unzip(verts)...)
|
Shape(verts::AVec) = Shape(unzip(verts)...)
|
||||||
|
|
||||||
|
|||||||
24
src/utils.jl
24
src/utils.jl
@ -306,6 +306,30 @@ Base.merge(a::AbstractVector, b::AbstractVector) = sort(unique(vcat(a,b)))
|
|||||||
nanpush!(a::AbstractVector, b) = (push!(a, NaN); push!(a, b))
|
nanpush!(a::AbstractVector, b) = (push!(a, NaN); push!(a, b))
|
||||||
nanappend!(a::AbstractVector, b) = (push!(a, NaN); append!(a, b))
|
nanappend!(a::AbstractVector, b) = (push!(a, NaN); append!(a, b))
|
||||||
|
|
||||||
|
function nansplit(v::AVec)
|
||||||
|
vs = Vector{eltype(v)}[]
|
||||||
|
while true
|
||||||
|
idx = findfirst(isnan, v)
|
||||||
|
if idx <= 0
|
||||||
|
# no nans
|
||||||
|
push!(vs, v)
|
||||||
|
break
|
||||||
|
elseif idx > 1
|
||||||
|
push!(vs, v[1:idx-1])
|
||||||
|
end
|
||||||
|
v = v[idx+1:end]
|
||||||
|
end
|
||||||
|
vs
|
||||||
|
end
|
||||||
|
|
||||||
|
function nanvcat(vs::AVec)
|
||||||
|
v_out = zeros(0)
|
||||||
|
for v in vs
|
||||||
|
nanappend!(v_out, v)
|
||||||
|
end
|
||||||
|
v_out
|
||||||
|
end
|
||||||
|
|
||||||
# given an array of discrete values, turn it into an array of indices of the unique values
|
# given an array of discrete values, turn it into an array of indices of the unique values
|
||||||
# returns the array of indices (znew) and a vector of unique values (vals)
|
# returns the array of indices (znew) and a vector of unique values (vals)
|
||||||
function indices_and_unique_values(z::AbstractArray)
|
function indices_and_unique_values(z::AbstractArray)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user