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,
|
arrow,
|
||||||
Segments,
|
Segments,
|
||||||
|
|
||||||
# colorscheme,
|
|
||||||
# ColorScheme,
|
|
||||||
# ColorGradient,
|
|
||||||
# ColorVector,
|
|
||||||
# ColorWrapper,
|
|
||||||
# ColorFunction,
|
|
||||||
# ColorZFunction,
|
|
||||||
# getColor,
|
|
||||||
# getColorZ,
|
|
||||||
|
|
||||||
debugplots,
|
debugplots,
|
||||||
|
|
||||||
supported_args,
|
supported_args,
|
||||||
@ -109,6 +99,7 @@ export
|
|||||||
|
|
||||||
test_examples,
|
test_examples,
|
||||||
iter_segments,
|
iter_segments,
|
||||||
|
coords,
|
||||||
|
|
||||||
translate,
|
translate,
|
||||||
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.haskey(axis::Axis, k::Symbol) = haskey(axis.d, k)
|
||||||
Base.extrema(axis::Axis) = (ex = axis[:extrema]; (ex.emin, ex.emax))
|
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)
|
function get_ticks(axis::Axis)
|
||||||
ticks = axis[:ticks]
|
ticks = axis[:ticks]
|
||||||
dvals = axis[:discrete_values]
|
dvals = axis[:discrete_values]
|
||||||
if !isempty(dvals) && ticks == :auto
|
cv, dv = if !isempty(dvals) && ticks == :auto
|
||||||
cv, dv = axis[:continuous_values], dvals
|
# discrete ticks...
|
||||||
# TODO: better/smarter cutoff values for sampling ticks
|
axis[:continuous_values], dvals
|
||||||
if length(cv) > 30
|
elseif ticks == :auto
|
||||||
rng = Int[round(Int,i) for i in linspace(1, length(cv), 15)]
|
cv = optimize_ticks(map(Float64, axis_limits(axis))..., k_max=5)[1]
|
||||||
cv[rng], dv[rng]
|
cv, cv
|
||||||
else
|
elseif typeof(ticks) <: NTuple{2}
|
||||||
cv, dv
|
|
||||||
end
|
|
||||||
else
|
|
||||||
ticks
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -339,3 +347,39 @@ function pie_labels(sp::Subplot, series::Series)
|
|||||||
d[:x]
|
d[:x]
|
||||||
end
|
end
|
||||||
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)
|
const _gr_point_mult = zeros(1)
|
||||||
|
|
||||||
# set the font attributes... assumes _gr_point_mult has been populated already
|
# 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)
|
family = lowercase(f.family)
|
||||||
GR.setcharheight(_gr_point_mult[1] * f.pointsize)
|
GR.setcharheight(_gr_point_mult[1] * f.pointsize)
|
||||||
GR.setcharup(sin(f.rotation), cos(f.rotation))
|
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)
|
GR.settextfontprec(100 + gr_font_family[family], GR.TEXT_PRECISION_STRING)
|
||||||
end
|
end
|
||||||
gr_set_textcolor(f.color)
|
gr_set_textcolor(f.color)
|
||||||
GR.settextalign(gr_halign[f.halign], gr_valign[f.valign])
|
GR.settextalign(gr_halign[halign], gr_valign[valign])
|
||||||
end
|
end
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------
|
||||||
@ -448,7 +448,7 @@ function gr_display(plt::Plot)
|
|||||||
|
|
||||||
# update point mult
|
# update point mult
|
||||||
px_per_pt = px / pt
|
px_per_pt = px / pt
|
||||||
_gr_point_mult[1] = px_per_pt / h
|
_gr_point_mult[1] = px_per_pt / max(h,w)
|
||||||
|
|
||||||
# subplots:
|
# subplots:
|
||||||
for sp in plt.subplots
|
for sp in plt.subplots
|
||||||
@ -561,26 +561,55 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
gr_polaraxes(rmin, rmax)
|
gr_polaraxes(rmin, rmax)
|
||||||
|
|
||||||
elseif draw_axes
|
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
|
# draw the grid lines
|
||||||
# TODO: control line style/width
|
|
||||||
# GR.setlinetype(GR.LINETYPE_DOTTED)
|
|
||||||
if sp[:grid]
|
if sp[:grid]
|
||||||
gr_set_linecolor(sp[:foreground_color_grid])
|
# gr_set_linecolor(sp[:foreground_color_grid])
|
||||||
GR.grid(xtick, ytick, 0, 0, majorx, majory)
|
# 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
|
end
|
||||||
|
|
||||||
window_diag = sqrt(gr_view_xdiff()^2 + gr_view_ydiff()^2)
|
# y labels
|
||||||
ticksize = 0.0075 * window_diag
|
gr_set_font(sp[:yaxis][:tickfont], halign = :right)
|
||||||
if outside_ticks
|
for (cv, dv) in zip(yticks...)
|
||||||
ticksize = -ticksize
|
xi, yi = GR.wctondc(xmin, cv)
|
||||||
|
# @show cv dv xmin xi yi
|
||||||
|
gr_text(xi-0.01, yi, string(dv))
|
||||||
end
|
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)
|
# window_diag = sqrt(gr_view_xdiff()^2 + gr_view_ydiff()^2)
|
||||||
y1, y2 = yaxis[:flip] ? (ymax,ymin) : (ymin,ymax)
|
# ticksize = 0.0075 * window_diag
|
||||||
GR.axes(xtick, ytick, x1, y1, 1, 1, ticksize)
|
# if outside_ticks
|
||||||
GR.axes(xtick, ytick, x2, y2, -1, -1, -ticksize)
|
# 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
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
|||||||
35
src/utils.jl
35
src/utils.jl
@ -138,24 +138,41 @@ end
|
|||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
type Segments
|
type Segments{T}
|
||||||
pts::Vector{Float64}
|
pts::Vector{T}
|
||||||
end
|
end
|
||||||
|
|
||||||
Segments() = Segments(zeros(0))
|
# Segments() = Segments{Float64}(zeros(0))
|
||||||
|
|
||||||
function Base.push!(segments::Segments, vs...)
|
Segments() = Segments(Float64)
|
||||||
push!(segments.pts, NaN)
|
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
|
for v in vs
|
||||||
push!(segments.pts, v)
|
push!(segments.pts, convert(T,v))
|
||||||
end
|
end
|
||||||
segments
|
segments
|
||||||
end
|
end
|
||||||
|
|
||||||
function Base.push!(segments::Segments, vs::AVec)
|
function Base.push!{T}(segments::Segments{T}, vs::AVec)
|
||||||
push!(segments.pts, NaN)
|
if !isempty(segments.pts)
|
||||||
|
push!(segments.pts, to_nan(T))
|
||||||
|
end
|
||||||
for v in vs
|
for v in vs
|
||||||
push!(segments.pts, v)
|
push!(segments.pts, convert(T,v))
|
||||||
end
|
end
|
||||||
segments
|
segments
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user