Base.cycle to cycle; text_size; animate; MixedMeasures; SeriesAnnotations
This commit is contained in:
parent
281b92c262
commit
350ffdee25
@ -89,6 +89,7 @@ export
|
||||
Animation,
|
||||
frame,
|
||||
gif,
|
||||
animate,
|
||||
@animate,
|
||||
@gif,
|
||||
|
||||
|
||||
@ -16,6 +16,33 @@ function frame{P<:AbstractPlot}(anim::Animation, plt::P=current())
|
||||
push!(anim.frames, filename)
|
||||
end
|
||||
|
||||
giffn() = (isijulia() ? "tmp.gif" : tempname()*".gif")
|
||||
|
||||
type FrameIterator
|
||||
itr
|
||||
every::Int
|
||||
kw
|
||||
end
|
||||
FrameIterator(itr; every=1, kw...) = FrameIterator(itr, every, kw)
|
||||
|
||||
"""
|
||||
Animate from an iterator which returns the plot args each iteration.
|
||||
"""
|
||||
function animate(fitr::FrameIterator, fn = giffn(); kw...)
|
||||
anim = Animation()
|
||||
for (i, plotargs) in enumerate(fitr.itr)
|
||||
if mod1(i, fitr.every) == 1
|
||||
plot(wraptuple(plotargs)...; fitr.kw...)
|
||||
frame(anim)
|
||||
end
|
||||
end
|
||||
gif(anim, fn; kw...)
|
||||
end
|
||||
|
||||
# most things will implement this
|
||||
function animate(obj, fn = giffn(); every=1, fps=20, loop=0, kw...)
|
||||
animate(FrameIterator(obj, every, kw); fps=fps, loop=loop)
|
||||
end
|
||||
|
||||
# -----------------------------------------------
|
||||
|
||||
@ -24,7 +51,7 @@ immutable AnimatedGif
|
||||
filename::String
|
||||
end
|
||||
|
||||
function gif(anim::Animation, fn = (isijulia() ? "tmp.gif" : tempname()*".gif"); fps::Integer = 20, loop::Integer = 0)
|
||||
function gif(anim::Animation, fn = giffn(); fps::Integer = 20, loop::Integer = 0)
|
||||
fn = abspath(fn)
|
||||
|
||||
try
|
||||
|
||||
@ -51,6 +51,20 @@ _before_layout_calcs(plt::Plot) = nothing
|
||||
title_padding(sp::Subplot) = sp[:title] == "" ? 0mm : sp[:titlefont].pointsize * pt
|
||||
guide_padding(axis::Axis) = axis[:guide] == "" ? 0mm : axis[:guidefont].pointsize * pt
|
||||
|
||||
"Returns the (width,height) of a text label."
|
||||
function text_size(lablen::Int, sz::Number, rot::Number = 0)
|
||||
# we need to compute the size of the ticks generically
|
||||
# this means computing the bounding box and then getting the width/height
|
||||
ptsz = sz * pt
|
||||
width = 0.8lablen * ptsz
|
||||
|
||||
# now compute the generalized "height" after rotation as the "opposite+adjacent" of 2 triangles
|
||||
height = abs(sind(rot)) * width + abs(cosd(rot)) * ptsz
|
||||
width = abs(sind(rot+90)) * width + abs(cosd(rot+90)) * ptsz
|
||||
width, height
|
||||
end
|
||||
text_size(lab::AbstractString, sz::Number, rot::Number = 0) = text_size(length(lab), sz, rot)
|
||||
|
||||
# account for the size/length/rotation of tick labels
|
||||
function tick_padding(axis::Axis)
|
||||
ticks = get_ticks(axis)
|
||||
@ -59,19 +73,23 @@ function tick_padding(axis::Axis)
|
||||
else
|
||||
vals, labs = ticks
|
||||
isempty(labs) && return 0mm
|
||||
ptsz = axis[:tickfont].pointsize * pt
|
||||
|
||||
# we need to compute the size of the ticks generically
|
||||
# this means computing the bounding box and then getting the width/height
|
||||
# ptsz = axis[:tickfont].pointsize * pt
|
||||
longest_label = maximum(length(lab) for lab in labs)
|
||||
labelwidth = 0.8longest_label * ptsz
|
||||
|
||||
# generalize by "rotating" y labels
|
||||
rot = axis[:rotation] + (axis[:letter] == :y ? 90 : 0)
|
||||
|
||||
# now compute the generalized "height" after rotation as the "opposite+adjacent" of 2 triangles
|
||||
hgt = abs(sind(rot)) * labelwidth + abs(cosd(rot)) * ptsz + 1mm
|
||||
hgt
|
||||
# # we need to compute the size of the ticks generically
|
||||
# # this means computing the bounding box and then getting the width/height
|
||||
# labelwidth = 0.8longest_label * ptsz
|
||||
#
|
||||
#
|
||||
# # now compute the generalized "height" after rotation as the "opposite+adjacent" of 2 triangles
|
||||
# hgt = abs(sind(rot)) * labelwidth + abs(cosd(rot)) * ptsz + 1mm
|
||||
# hgt
|
||||
|
||||
# get the height of the rotated label
|
||||
text_size(longest_label, axis[:tickfont].pointsize, rot)[2]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -1021,14 +1021,18 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
end
|
||||
end
|
||||
for ann in sp[:annotations]
|
||||
x, y, val = ann
|
||||
x, y = if is3d(sp)
|
||||
# GR.wc3towc(x, y, z)
|
||||
if isa(ann, SeriesAnnotation)
|
||||
# TODO handle series annotations
|
||||
else
|
||||
GR.wctondc(x, y)
|
||||
x, y, val = ann
|
||||
x, y = if is3d(sp)
|
||||
# GR.wc3towc(x, y, z)
|
||||
else
|
||||
GR.wctondc(x, y)
|
||||
end
|
||||
gr_set_font(val.font)
|
||||
gr_text(x, y, val.str)
|
||||
end
|
||||
gr_set_font(val.font)
|
||||
gr_text(x, y, val.str)
|
||||
end
|
||||
GR.restorestate()
|
||||
end
|
||||
|
||||
@ -308,10 +308,6 @@ function text(str, args...)
|
||||
end
|
||||
|
||||
|
||||
annotations(::Void) = []
|
||||
annotations(anns::AVec) = anns
|
||||
annotations(anns) = Any[anns]
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
@ -387,6 +383,47 @@ end
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
type SeriesAnnotations
|
||||
strs::AbstractVector # the labels/names
|
||||
font::Font
|
||||
shape::Nullable{Shape}
|
||||
shapefill::Brush
|
||||
shapestroke::Stroke
|
||||
bboxes::Vector{BBox}
|
||||
end
|
||||
function SeriesAnnotations(strs::AbstractVector, args...)
|
||||
fnt = font()
|
||||
shp = Nullable{Shape}()
|
||||
br = brush(:steelblue)
|
||||
stk = stroke(:black, 1)
|
||||
for arg in args
|
||||
if isa(arg, Shape)
|
||||
shp = Nullable{Shape}(arg)
|
||||
elseif isa(arg, Brush)
|
||||
brush = arg
|
||||
elseif isa(arg, Stroke)
|
||||
stk = arg
|
||||
elseif isa(arg, Font)
|
||||
fnt = arg
|
||||
elseif isa(arg, Symbol) && haskey(_shapes, arg)
|
||||
shape = _shapes[arg]
|
||||
else
|
||||
warn("Unused SeriesAnnotations arg: $arg ($(typeof(arg)))")
|
||||
end
|
||||
end
|
||||
# note: x/y coords are added later
|
||||
SeriesAnnotations(strs, fnt, shp, br, stk, BBox[])
|
||||
end
|
||||
|
||||
|
||||
|
||||
annotations(::Void) = []
|
||||
annotations(anns::AVec) = anns
|
||||
annotations(anns) = Any[anns]
|
||||
annotations(sa::SeriesAnnotations) = sa
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
"type which represents z-values for colors and sizes (and anything else that might come up)"
|
||||
immutable ZValues
|
||||
values::Vector{Float64}
|
||||
|
||||
@ -96,6 +96,31 @@ function Base.show(io::IO, bbox::BoundingBox)
|
||||
print(io, "BBox{l,t,r,b,w,h = $(left(bbox)),$(top(bbox)), $(right(bbox)),$(bottom(bbox)), $(width(bbox)),$(height(bbox))}")
|
||||
end
|
||||
|
||||
# -----------------------------------------------------------
|
||||
|
||||
# points combined by x/y, pct, and length
|
||||
type MixedMeasures
|
||||
xy::Float64
|
||||
pct::Float64
|
||||
len::AbsoluteLength
|
||||
end
|
||||
|
||||
function resolve_mixed(mix::MixedMeasures, sp::Subplot, letter::Symbol)
|
||||
xy = mix.xy
|
||||
pct = mix.pct
|
||||
if mix.len != 0mm
|
||||
f = (letter == :x ? width : height)
|
||||
totlen = f(plotarea(sp))
|
||||
pct += mix.len / totlen
|
||||
end
|
||||
if pct != 0
|
||||
amin, amax = axis_limits(sp[Symbol(letter,:axis)])
|
||||
xy += pct * (amax-amin)
|
||||
end
|
||||
xy
|
||||
end
|
||||
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# AbstractLayout
|
||||
|
||||
|
||||
@ -333,14 +333,29 @@ function _prepare_annotations(sp::Subplot, d::KW)
|
||||
# strip out series annotations (those which are based on series x/y coords)
|
||||
# and add them to the subplot attr
|
||||
sp_anns = annotations(sp[:annotations])
|
||||
anns = annotations(pop!(d, :series_annotations, []))
|
||||
if length(anns) > 0
|
||||
series_anns = annotations(pop!(d, :series_annotations, []))
|
||||
if isa(series_anns, SeriesAnnotations)
|
||||
# x, y = d[:x], d[:y]
|
||||
# nx, ny, na = map(length, (x,y,series_anns.strs))
|
||||
# n = max(nx, ny, na)
|
||||
# for i=1:n
|
||||
# str = cycle(series_anns.strs,i)
|
||||
# xi = cycle(x,i)
|
||||
# yi = cycle(y,i)
|
||||
# mwidth, mheight = text_size(str, series_anns.font.pointsize)
|
||||
# xsz = measure_to_data(sp[:xaxis], mwidth)
|
||||
# ysz = measure_to_data(sp[:yaxis], mheight)
|
||||
error()
|
||||
|
||||
elseif length(series_anns) > 0
|
||||
x, y = d[:x], d[:y]
|
||||
nx, ny, na = map(length, (x,y,anns))
|
||||
nx, ny, na = map(length, (x,y,series_anns))
|
||||
n = max(nx, ny, na)
|
||||
anns = [(x[mod1(i,nx)], y[mod1(i,ny)], text(anns[mod1(i,na)])) for i=1:n]
|
||||
series_anns = [(x[mod1(i,nx)], y[mod1(i,ny)], text(series_anns[mod1(i,na)])) for i=1:n]
|
||||
end
|
||||
sp.attr[:annotations] = vcat(sp_anns, anns)
|
||||
sp.attr[:annotations] = vcat(sp_anns, series_anns)
|
||||
# sp[:series_annotations] = series_anns
|
||||
# sp[:annotations] = sp_anns
|
||||
end
|
||||
|
||||
function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol)
|
||||
|
||||
20
src/utils.jl
20
src/utils.jl
@ -234,19 +234,19 @@ end
|
||||
nop() = nothing
|
||||
notimpl() = error("This has not been implemented yet")
|
||||
|
||||
Base.cycle(wrapper::InputWrapper, idx::Int) = wrapper.obj
|
||||
Base.cycle(wrapper::InputWrapper, idx::AVec{Int}) = wrapper.obj
|
||||
cycle(wrapper::InputWrapper, idx::Int) = wrapper.obj
|
||||
cycle(wrapper::InputWrapper, idx::AVec{Int}) = wrapper.obj
|
||||
|
||||
Base.cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
|
||||
Base.cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
|
||||
Base.cycle(v, idx::Int) = v
|
||||
cycle(v::AVec, idx::Int) = v[mod1(idx, length(v))]
|
||||
cycle(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
|
||||
cycle(v, idx::Int) = v
|
||||
|
||||
Base.cycle(v::AVec, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
|
||||
Base.cycle(v::AMat, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
|
||||
Base.cycle(v, indices::AVec{Int}) = fill(v, length(indices))
|
||||
cycle(v::AVec, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
|
||||
cycle(v::AMat, indices::AVec{Int}) = map(i -> cycle(v,i), indices)
|
||||
cycle(v, indices::AVec{Int}) = fill(v, length(indices))
|
||||
|
||||
Base.cycle(grad::ColorGradient, idx::Int) = cycle(grad.colors, idx)
|
||||
Base.cycle(grad::ColorGradient, indices::AVec{Int}) = cycle(grad.colors, indices)
|
||||
cycle(grad::ColorGradient, idx::Int) = cycle(grad.colors, idx)
|
||||
cycle(grad::ColorGradient, indices::AVec{Int}) = cycle(grad.colors, indices)
|
||||
|
||||
makevec(v::AVec) = v
|
||||
makevec{T}(v::T) = T[v]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user