don't export Axis/Plot/etc; closes #552; fix series_annotations; support SeriesAnnotations in gr; fix scale/translate

This commit is contained in:
Thomas Breloff 2016-11-03 22:02:23 -04:00
parent 350ffdee25
commit af1896dc36
6 changed files with 85 additions and 51 deletions

View File

@ -10,18 +10,18 @@ using Base.Meta
import Showoff import Showoff
export export
AbstractPlot, # AbstractPlot,
Plot, # Plot,
Subplot, # Subplot,
AbstractLayout, # AbstractLayout,
GridLayout, # GridLayout,
grid, grid,
EmptyLayout, # EmptyLayout,
bbox, bbox,
plotarea, plotarea,
@layout, @layout,
AVec, # AVec,
AMat, # AMat,
KW, KW,
wrap, wrap,
@ -77,7 +77,7 @@ export
Shape, Shape,
text, text,
font, font,
Axis, # Axis,
stroke, stroke,
brush, brush,
Surface, Surface,

View File

@ -41,7 +41,7 @@ end
# most things will implement this # most things will implement this
function animate(obj, fn = giffn(); every=1, fps=20, loop=0, kw...) function animate(obj, fn = giffn(); every=1, fps=20, loop=0, kw...)
animate(FrameIterator(obj, every, kw); fps=fps, loop=loop) animate(FrameIterator(obj, every, kw), fn; fps=fps, loop=loop)
end end
# ----------------------------------------------- # -----------------------------------------------

View File

@ -55,8 +55,9 @@ guide_padding(axis::Axis) = axis[:guide] == "" ? 0mm : axis[:guidefont].pointsiz
function text_size(lablen::Int, sz::Number, rot::Number = 0) function text_size(lablen::Int, sz::Number, rot::Number = 0)
# we need to compute the size of the ticks generically # we need to compute the size of the ticks generically
# this means computing the bounding box and then getting the width/height # this means computing the bounding box and then getting the width/height
ptsz = sz * pt # note:
width = 0.8lablen * ptsz ptsz = 1.5sz * pt
width = 0.5lablen * ptsz
# now compute the generalized "height" after rotation as the "opposite+adjacent" of 2 triangles # now compute the generalized "height" after rotation as the "opposite+adjacent" of 2 triangles
height = abs(sind(rot)) * width + abs(cosd(rot)) * ptsz height = abs(sind(rot)) * width + abs(cosd(rot)) * ptsz

View File

@ -549,16 +549,16 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# set the scale flags and window # set the scale flags and window
xmin, xmax, ymin, ymax = data_lims xmin, xmax, ymin, ymax = data_lims
scale = 0 scaleop = 0
xtick, ytick = 1, 1 xtick, ytick = 1, 1
if xmax > xmin && ymax > ymin if xmax > xmin && ymax > ymin
# NOTE: for log axes, the major_x and major_y - if non-zero (omit labels) - control the minor grid lines (1 = draw 9 minor grid lines, 2 = no minor grid lines) # NOTE: for log axes, the major_x and major_y - if non-zero (omit labels) - control the minor grid lines (1 = draw 9 minor grid lines, 2 = no minor grid lines)
# NOTE: for log axes, the x_tick and y_tick - if non-zero (omit axes) - only affect the output appearance (1 = nomal, 2 = scientiic notation) # NOTE: for log axes, the x_tick and y_tick - if non-zero (omit axes) - only affect the output appearance (1 = nomal, 2 = scientiic notation)
xaxis[:scale] == :log10 && (scale |= GR.OPTION_X_LOG) xaxis[:scale] == :log10 && (scaleop |= GR.OPTION_X_LOG)
yaxis[:scale] == :log10 && (scale |= GR.OPTION_Y_LOG) yaxis[:scale] == :log10 && (scaleop |= GR.OPTION_Y_LOG)
xaxis[:flip] && (scale |= GR.OPTION_FLIP_X) xaxis[:flip] && (scaleop |= GR.OPTION_FLIP_X)
yaxis[:flip] && (scale |= GR.OPTION_FLIP_Y) yaxis[:flip] && (scaleop |= GR.OPTION_FLIP_Y)
if scale & GR.OPTION_X_LOG == 0 if scaleop & GR.OPTION_X_LOG == 0
majorx = 1 #5 majorx = 1 #5
xtick = GR.tick(xmin, xmax) / majorx xtick = GR.tick(xmin, xmax) / majorx
else else
@ -566,7 +566,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
xtick = 2 # scientific notation xtick = 2 # scientific notation
majorx = 2 # no minor grid lines majorx = 2 # no minor grid lines
end end
if scale & GR.OPTION_Y_LOG == 0 if scaleop & GR.OPTION_Y_LOG == 0
majory = 1 #5 majory = 1 #5
ytick = GR.tick(ymin, ymax) / majory ytick = GR.tick(ymin, ymax) / majory
else else
@ -577,7 +577,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
# NOTE: setwindow sets the "data coordinate" limits of the current "viewport" # NOTE: setwindow sets the "data coordinate" limits of the current "viewport"
GR.setwindow(xmin, xmax, ymin, ymax) GR.setwindow(xmin, xmax, ymin, ymax)
GR.setscale(scale) GR.setscale(scaleop)
end end
# draw the axes # draw the axes
@ -1021,8 +1021,45 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
end end
end end
for ann in sp[:annotations] for ann in sp[:annotations]
if isa(ann, SeriesAnnotation) if isa(ann, SeriesAnnotations)
# TODO handle series annotations # TODO handle series annotations
# TODO: this should be moved with SeriesAnnotations... iterate like:
# for (xi,yi,str,shape) in eachann(anns, sp) ... end
# or maybe
# anns.sp = sp
# for (xi,yi,str,shape) in anns ... end
@assert !is3d(sp)
shapefillcolor = plot_color(ann.shapefill.color, ann.shapefill.alpha)
shapestrokecolor = plot_color(ann.shapestroke.color, ann.shapestroke.alpha)
for i=1:length(ann.y)
xi = cycle(ann.x,i)
yi = cycle(ann.y,i)
str = cycle(ann.strs,i)
if !isnull(ann.baseshape)
# get the width and height of the string (in mm)
sw, sh = text_size(str, ann.font.pointsize)
# how much to scale the base shape?
xscale = 0.5 * resolve_mixed(MixedMeasures(0, 0, sw), sp, :x)
yscale = 0.5 * resolve_mixed(MixedMeasures(0, 0, sh), sp, :y)
# get the shape for this x/y/str
shape = scale(get(ann.baseshape), xscale, yscale)
translate!(shape, xi, yi)
# draw the interior
gr_set_fill(shapefillcolor)
GR.fillarea(shape_coords(shape)...)
# draw the shapes
gr_set_line(ann.shapestroke.width, ann.shapestroke.style, shapestrokecolor)
GR.polyline(shape_coords(shape)...)
end
gr_set_font(ann.font)
gr_text(GR.wctondc(xi, yi)..., str)
end
else else
x, y, val = ann x, y, val = ann
x, y = if is3d(sp) x, y = if is3d(sp)

View File

@ -72,13 +72,13 @@ function makestar(n; offset = -0.5, radius = 1.0)
z2 = z1 + π / (n) z2 = z1 + π / (n)
outercircle = partialcircle(z1, z1 + 2π, n+1, radius) outercircle = partialcircle(z1, z1 + 2π, n+1, radius)
innercircle = partialcircle(z2, z2 + 2π, n+1, 0.4radius) innercircle = partialcircle(z2, z2 + 2π, n+1, 0.4radius)
Shape(weave(outercircle, innercircle)[1:end-2]) Shape(weave(outercircle, innercircle))
end end
"create a shape by picking points around the unit circle. `n` is the number of point/sides, `offset` is the starting angle" "create a shape by picking points around the unit circle. `n` is the number of point/sides, `offset` is the starting angle"
function makeshape(n; offset = -0.5, radius = 1.0) function makeshape(n; offset = -0.5, radius = 1.0)
z = offset * π z = offset * π
Shape(partialcircle(z, z + 2π, n+1, radius)[1:end-1]) Shape(partialcircle(z, z + 2π, n+1, radius))
end end
@ -88,7 +88,7 @@ function makecross(; offset = -0.5, radius = 1.0)
outercircle = partialcircle(z1, z1 + 2π, 9, radius) outercircle = partialcircle(z1, z1 + 2π, 9, radius)
innercircle = partialcircle(z2, z2 + 2π, 5, 0.5radius) innercircle = partialcircle(z2, z2 + 2π, 5, 0.5radius)
Shape(weave(outercircle, innercircle, Shape(weave(outercircle, innercircle,
ordering=Vector[outercircle,innercircle,outercircle])[1:end-2]) ordering=Vector[outercircle,innercircle,outercircle]))
end end
@ -177,7 +177,7 @@ end
function Base.scale(shape::Shape, x::Real, y::Real = x, c = center(shape)) function Base.scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
shapecopy = deepcopy(shape) shapecopy = deepcopy(shape)
scale!(shape, x, y, c) scale!(shapecopy, x, y, c)
end end
function translate!(shape::Shape, x::Real, y::Real = x) function translate!(shape::Shape, x::Real, y::Real = x)
@ -191,7 +191,7 @@ end
function translate(shape::Shape, x::Real, y::Real = x) function translate(shape::Shape, x::Real, y::Real = x)
shapecopy = deepcopy(shape) shapecopy = deepcopy(shape)
translate!(shape, x, y) translate!(shapecopy, x, y)
end end
function rotate_x(x::Real, y::Real, Θ::Real, centerx::Real, centery::Real) function rotate_x(x::Real, y::Real, Θ::Real, centerx::Real, centery::Real)
@ -321,9 +321,9 @@ immutable Stroke
end end
function stroke(args...; alpha = nothing) function stroke(args...; alpha = nothing)
width = nothing width = 1
color = nothing color = :black
style = nothing style = :solid
for arg in args for arg in args
T = typeof(arg) T = typeof(arg)
@ -357,8 +357,8 @@ immutable Brush
end end
function brush(args...; alpha = nothing) function brush(args...; alpha = nothing)
size = nothing size = 1
color = nothing color = :black
for arg in args for arg in args
T = typeof(arg) T = typeof(arg)
@ -386,16 +386,18 @@ end
type SeriesAnnotations type SeriesAnnotations
strs::AbstractVector # the labels/names strs::AbstractVector # the labels/names
font::Font font::Font
shape::Nullable{Shape} baseshape::Nullable{Shape}
shapefill::Brush shapefill::Brush
shapestroke::Stroke shapestroke::Stroke
bboxes::Vector{BBox} x
y
end end
function SeriesAnnotations(strs::AbstractVector, args...) function series_annotations(strs::AbstractVector, args...)
fnt = font() fnt = font()
shp = Nullable{Shape}() shp = Nullable{Shape}()
br = brush(:steelblue) br = brush(:steelblue)
stk = stroke(:black, 1) stk = stroke()
α = nothing
for arg in args for arg in args
if isa(arg, Shape) if isa(arg, Shape)
shp = Nullable{Shape}(arg) shp = Nullable{Shape}(arg)
@ -406,13 +408,19 @@ function SeriesAnnotations(strs::AbstractVector, args...)
elseif isa(arg, Font) elseif isa(arg, Font)
fnt = arg fnt = arg
elseif isa(arg, Symbol) && haskey(_shapes, arg) elseif isa(arg, Symbol) && haskey(_shapes, arg)
shape = _shapes[arg] shp = _shapes[arg]
elseif allAlphas(arg)
α = arg
else else
warn("Unused SeriesAnnotations arg: $arg ($(typeof(arg)))") warn("Unused SeriesAnnotations arg: $arg ($(typeof(arg)))")
end end
end end
if α != nothing
br.alpha = α
stk.alpha = α
end
# note: x/y coords are added later # note: x/y coords are added later
SeriesAnnotations(strs, fnt, shp, br, stk, BBox[]) SeriesAnnotations(strs, fnt, shp, br, stk, nothing, nothing)
end end

View File

@ -335,18 +335,8 @@ function _prepare_annotations(sp::Subplot, d::KW)
sp_anns = annotations(sp[:annotations]) sp_anns = annotations(sp[:annotations])
series_anns = annotations(pop!(d, :series_annotations, [])) series_anns = annotations(pop!(d, :series_annotations, []))
if isa(series_anns, SeriesAnnotations) if isa(series_anns, SeriesAnnotations)
# x, y = d[:x], d[:y] series_anns.x = d[:x]
# nx, ny, na = map(length, (x,y,series_anns.strs)) series_anns.y = d[:y]
# 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 elseif length(series_anns) > 0
x, y = d[:x], d[:y] x, y = d[:x], d[:y]
nx, ny, na = map(length, (x,y,series_anns)) nx, ny, na = map(length, (x,y,series_anns))
@ -354,8 +344,6 @@ function _prepare_annotations(sp::Subplot, d::KW)
series_anns = [(x[mod1(i,nx)], y[mod1(i,ny)], text(series_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 end
sp.attr[:annotations] = vcat(sp_anns, series_anns) sp.attr[:annotations] = vcat(sp_anns, series_anns)
# sp[:series_annotations] = series_anns
# sp[:annotations] = sp_anns
end end
function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol) function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol)