axis_drawing_info and get_ticks; parameterized Segments; GR manual drawing of 2D axes
This commit is contained in:
parent
dcab8e3ac2
commit
ee706ad8c7
11
src/Plots.jl
11
src/Plots.jl
@ -81,16 +81,6 @@ export
|
||||
arrow,
|
||||
Segments,
|
||||
|
||||
# colorscheme,
|
||||
# ColorScheme,
|
||||
# ColorGradient,
|
||||
# ColorVector,
|
||||
# ColorWrapper,
|
||||
# ColorFunction,
|
||||
# ColorZFunction,
|
||||
# getColor,
|
||||
# getColorZ,
|
||||
|
||||
debugplots,
|
||||
|
||||
supported_args,
|
||||
@ -109,6 +99,7 @@ export
|
||||
|
||||
test_examples,
|
||||
iter_segments,
|
||||
coords,
|
||||
|
||||
translate,
|
||||
translate!,
|
||||
|
||||
66
src/axes.jl
66
src/axes.jl
@ -117,21 +117,29 @@ Base.setindex!(axis::Axis, v, ks::Symbol...) = setindex!(axis.d, v, ks...)
|
||||
Base.haskey(axis::Axis, k::Symbol) = haskey(axis.d, k)
|
||||
Base.extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
|
||||
|
||||
# get discrete ticks, or not
|
||||
# return (continuous_values, discrete_values) for the ticks on this axis
|
||||
function get_ticks(axis::Axis)
|
||||
ticks = axis[:ticks]
|
||||
dvals = axis[:discrete_values]
|
||||
if !isempty(dvals) && ticks == :auto
|
||||
cv, dv = axis[:continuous_values], dvals
|
||||
# TODO: better/smarter cutoff values for sampling ticks
|
||||
if length(cv) > 30
|
||||
rng = Int[round(Int,i) for i in linspace(1, length(cv), 15)]
|
||||
cv[rng], dv[rng]
|
||||
else
|
||||
cv, dv
|
||||
end
|
||||
else
|
||||
cv, dv = if !isempty(dvals) && ticks == :auto
|
||||
# discrete ticks...
|
||||
axis[:continuous_values], dvals
|
||||
elseif ticks == :auto
|
||||
cv = optimize_ticks(map(Float64, axis_limits(axis))..., k_max=5)[1]
|
||||
cv, cv
|
||||
elseif typeof(ticks) <: NTuple{2}
|
||||
ticks
|
||||
else
|
||||
error("Unknown ticks type in get_ticks: $(typeof(ticks))")
|
||||
end
|
||||
# @show ticks dvals cv dv
|
||||
|
||||
# TODO: better/smarter cutoff values for sampling ticks
|
||||
if length(cv) > 30
|
||||
rng = Int[round(Int,i) for i in linspace(1, length(cv), 15)]
|
||||
cv[rng], dv[rng]
|
||||
else
|
||||
cv, dv
|
||||
end
|
||||
end
|
||||
|
||||
@ -339,3 +347,39 @@ function pie_labels(sp::Subplot, series::Series)
|
||||
d[:x]
|
||||
end
|
||||
end
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
# compute the line segments which should be drawn for this axis
|
||||
function axis_drawing_info(sp::Subplot)
|
||||
xaxis, yaxis = sp[:xaxis], sp[:yaxis]
|
||||
xmin, xmax = axis_limits(xaxis)
|
||||
ymin, ymax = axis_limits(yaxis)
|
||||
xticks = get_ticks(xaxis)
|
||||
yticks = get_ticks(yaxis)
|
||||
spine_segs = Segments(2)
|
||||
grid_segs = Segments(2)
|
||||
|
||||
# x axis
|
||||
ticksz = 0.015 * (ymax - ymin)
|
||||
push!(spine_segs, (xmin,ymin), (xmax,ymin)) # bottom spine
|
||||
push!(spine_segs, (xmin,ymax), (xmax,ymax)) # top spine
|
||||
for xtick in xticks[1]
|
||||
push!(spine_segs, (xtick, ymin), (xtick, ymin+ticksz)) # bottom tick
|
||||
push!(grid_segs, (xtick, ymin+ticksz), (xtick, ymax-ticksz)) # vertical grid
|
||||
push!(spine_segs, (xtick, ymax), (xtick, ymax-ticksz)) # top tick
|
||||
end
|
||||
|
||||
# y axis
|
||||
ticksz = 0.015 * (xmax - xmin)
|
||||
push!(spine_segs, (xmin,ymin), (xmin,ymax)) # left spine
|
||||
push!(spine_segs, (xmax,ymin), (xmax,ymax)) # right spine
|
||||
for ytick in yticks[1]
|
||||
push!(spine_segs, (xmin, ytick), (xmin+ticksz, ytick)) # left tick
|
||||
push!(grid_segs, (xmin+ticksz, ytick), (xmax-ticksz, ytick)) # horizontal grid
|
||||
push!(spine_segs, (xmax, ytick), (xmax-ticksz, ytick)) # right tick
|
||||
end
|
||||
|
||||
xticks, yticks, spine_segs, grid_segs
|
||||
end
|
||||
|
||||
|
||||
@ -328,7 +328,7 @@ end
|
||||
const _gr_point_mult = zeros(1)
|
||||
|
||||
# set the font attributes... assumes _gr_point_mult has been populated already
|
||||
function gr_set_font(f::Font)
|
||||
function gr_set_font(f::Font; halign = f.halign, valign = f.valign)
|
||||
family = lowercase(f.family)
|
||||
GR.setcharheight(_gr_point_mult[1] * f.pointsize)
|
||||
GR.setcharup(sin(f.rotation), cos(f.rotation))
|
||||
@ -336,7 +336,7 @@ function gr_set_font(f::Font)
|
||||
GR.settextfontprec(100 + gr_font_family[family], GR.TEXT_PRECISION_STRING)
|
||||
end
|
||||
gr_set_textcolor(f.color)
|
||||
GR.settextalign(gr_halign[f.halign], gr_valign[f.valign])
|
||||
GR.settextalign(gr_halign[halign], gr_valign[valign])
|
||||
end
|
||||
|
||||
# --------------------------------------------------------------------------------------
|
||||
@ -448,7 +448,7 @@ function gr_display(plt::Plot)
|
||||
|
||||
# update point mult
|
||||
px_per_pt = px / pt
|
||||
_gr_point_mult[1] = px_per_pt / h
|
||||
_gr_point_mult[1] = px_per_pt / max(h,w)
|
||||
|
||||
# subplots:
|
||||
for sp in plt.subplots
|
||||
@ -561,26 +561,55 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
gr_polaraxes(rmin, rmax)
|
||||
|
||||
elseif draw_axes
|
||||
if xmax > xmin && ymax > ymin
|
||||
GR.setwindow(xmin, xmax, ymin, ymax)
|
||||
end
|
||||
|
||||
xticks, yticks, spine_segs, grid_segs = axis_drawing_info(sp)
|
||||
# @show xticks yticks spine_segs grid_segs
|
||||
|
||||
# draw the grid lines
|
||||
# TODO: control line style/width
|
||||
# GR.setlinetype(GR.LINETYPE_DOTTED)
|
||||
if sp[:grid]
|
||||
gr_set_linecolor(sp[:foreground_color_grid])
|
||||
GR.grid(xtick, ytick, 0, 0, majorx, majory)
|
||||
# gr_set_linecolor(sp[:foreground_color_grid])
|
||||
# GR.grid(xtick, ytick, 0, 0, majorx, majory)
|
||||
gr_set_line(1, :dot, sp[:foreground_color_grid])
|
||||
GR.settransparency(0.5)
|
||||
gr_polyline(coords(grid_segs)...)
|
||||
end
|
||||
GR.settransparency(1.0)
|
||||
|
||||
# spine (border) and tick marks
|
||||
gr_set_line(1, :solid, sp[:xaxis][:foreground_color_axis])
|
||||
gr_polyline(coords(spine_segs)...)
|
||||
|
||||
# x labels
|
||||
gr_set_font(sp[:xaxis][:tickfont], valign = :top)
|
||||
for (cv, dv) in zip(xticks...)
|
||||
xi, yi = GR.wctondc(cv, ymin)
|
||||
# @show cv dv ymin xi yi
|
||||
gr_text(xi, yi-0.01, string(dv))
|
||||
end
|
||||
|
||||
window_diag = sqrt(gr_view_xdiff()^2 + gr_view_ydiff()^2)
|
||||
ticksize = 0.0075 * window_diag
|
||||
if outside_ticks
|
||||
ticksize = -ticksize
|
||||
# y labels
|
||||
gr_set_font(sp[:yaxis][:tickfont], halign = :right)
|
||||
for (cv, dv) in zip(yticks...)
|
||||
xi, yi = GR.wctondc(xmin, cv)
|
||||
# @show cv dv xmin xi yi
|
||||
gr_text(xi-0.01, yi, string(dv))
|
||||
end
|
||||
# TODO: this should be done for each axis separately
|
||||
gr_set_linecolor(xaxis[:foreground_color_axis])
|
||||
|
||||
x1, x2 = xaxis[:flip] ? (xmax,xmin) : (xmin,xmax)
|
||||
y1, y2 = yaxis[:flip] ? (ymax,ymin) : (ymin,ymax)
|
||||
GR.axes(xtick, ytick, x1, y1, 1, 1, ticksize)
|
||||
GR.axes(xtick, ytick, x2, y2, -1, -1, -ticksize)
|
||||
# window_diag = sqrt(gr_view_xdiff()^2 + gr_view_ydiff()^2)
|
||||
# ticksize = 0.0075 * window_diag
|
||||
# if outside_ticks
|
||||
# ticksize = -ticksize
|
||||
# end
|
||||
# # TODO: this should be done for each axis separately
|
||||
# gr_set_linecolor(xaxis[:foreground_color_axis])
|
||||
|
||||
# x1, x2 = xaxis[:flip] ? (xmax,xmin) : (xmin,xmax)
|
||||
# y1, y2 = yaxis[:flip] ? (ymax,ymin) : (ymin,ymax)
|
||||
# GR.axes(xtick, ytick, x1, y1, 1, 1, ticksize)
|
||||
# GR.axes(xtick, ytick, x2, y2, -1, -1, -ticksize)
|
||||
end
|
||||
# end
|
||||
|
||||
|
||||
35
src/utils.jl
35
src/utils.jl
@ -138,24 +138,41 @@ end
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
|
||||
type Segments
|
||||
pts::Vector{Float64}
|
||||
type Segments{T}
|
||||
pts::Vector{T}
|
||||
end
|
||||
|
||||
Segments() = Segments(zeros(0))
|
||||
# Segments() = Segments{Float64}(zeros(0))
|
||||
|
||||
function Base.push!(segments::Segments, vs...)
|
||||
push!(segments.pts, NaN)
|
||||
Segments() = Segments(Float64)
|
||||
Segments{T}(::Type{T}) = Segments(T[])
|
||||
Segments(p::Int) = Segments(NTuple{2,Float64}[])
|
||||
|
||||
|
||||
# Segments() = Segments(zeros(0))
|
||||
|
||||
to_nan(::Type{Float64}) = NaN
|
||||
to_nan(::Type{NTuple{2,Float64}}) = (NaN, NaN)
|
||||
|
||||
coords(segs::Segments{Float64}) = segs.pts
|
||||
coords(segs::Segments{NTuple{2,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts]
|
||||
|
||||
function Base.push!{T}(segments::Segments{T}, vs...)
|
||||
if !isempty(segments.pts)
|
||||
push!(segments.pts, to_nan(T))
|
||||
end
|
||||
for v in vs
|
||||
push!(segments.pts, v)
|
||||
push!(segments.pts, convert(T,v))
|
||||
end
|
||||
segments
|
||||
end
|
||||
|
||||
function Base.push!(segments::Segments, vs::AVec)
|
||||
push!(segments.pts, NaN)
|
||||
function Base.push!{T}(segments::Segments{T}, vs::AVec)
|
||||
if !isempty(segments.pts)
|
||||
push!(segments.pts, to_nan(T))
|
||||
end
|
||||
for v in vs
|
||||
push!(segments.pts, v)
|
||||
push!(segments.pts, convert(T,v))
|
||||
end
|
||||
segments
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user