PlotText/text for annotations; fixes

This commit is contained in:
Thomas Breloff 2015-10-15 14:46:29 -04:00
parent eab46ba9c4
commit 407df158ef
16 changed files with 208 additions and 221 deletions

View File

@ -221,6 +221,10 @@ Keyword | Default | Type | Aliases
`:linestyle` | `solid` | Series | `:linestyles`, `:ls`, `:s`, `:style`
`:linetype` | `path` | Series | `:linetypes`, `:lt`, `:t`, `:type`
`:linewidth` | `1` | Series | `:linewidths`, `:lw`, `:w`, `:width`
`:link` | `false` | Plot |
`:linkfunc` | `nothing` | Plot |
`:linkx` | `false` | Plot | `:xlink`
`:linky` | `false` | Plot | `:ylink`
`:marker` | `nothing` | Series | `:m`, `:mark`
`:markercolor` | `match` | Series | `:markercolors`, `:mc`, `:mcolor`
`:markershape` | `none` | Series | `:markershapes`, `:shape`
@ -289,19 +293,25 @@ Type | Aliases
---- | ----
`:none` | `:n`, `:no`
`:auto` | `:a`
`:ellipse` | `:c`, `:circle`
`:rect` | `:r`, `:sq`, `:square`
`:diamond` | `:d`
`:utriangle` | `:^`, `:uptri`, `:uptriangle`, `:ut`, `:utri`
`:dtriangle` | `:V`, `:downtri`, `:downtriangle`, `:dt`, `:dtri`, `:v`
`:cross` | `:+`, `:plus`
`:xcross` | `:X`, `:x`
`:star1` | `:s`, `:star`
`:star2` | `:s2`
`:diamond` | `:d`
`:dtriangle` | `:V`, `:downtri`, `:downtriangle`, `:dt`, `:dtri`, `:v`
`:ellipse` | `:c`, `:circle`
`:heptagon` | `:hep`
`:hexagon` | `:h`, `:hex`
`:octagon` | `:o`, `:oct`
`:pentagon` | `:p`, `:pent`
`:rect` | `:r`, `:sq`, `:square`
`:star4` |
`:star5` | `:s`, `:star`, `:star1`
`:star6` |
`:star7` |
`:star8` | `:s2`, `:star2`
`:utriangle` | `:^`, `:uptri`, `:uptriangle`, `:ut`, `:utri`
`:xcross` | `:X`, `:x`
__Tip__: With supported backends, you can pass a `Plots.Shape` object for the `marker`/`markershape` arguments. `Shape` takes a vector of 2-tuples in the constructor, defining the points of the polygon's shape in a unit-scaled coordinate space. To make a square, for example, you could do `Shape([(1,1),(1,-1),(-1,-1),(-1,1)])`
__Tip__: You can see the default value for a given argument with `default(arg::Symbol)`, and set the default value with `default(arg::Symbol, value)` or `default(; kw...)`. For example set the default window size and whether we should show a legend with `default(size=(600,400), leg=false)`.
@ -323,7 +333,7 @@ __Tip__: When plotting multiple lines, you can set all series to use the same va
```julia
plot(rand(100,4); color = [:red RGB(0,0,1)], # (Matrix) lines 1 and 3 are red, lines 2 and 4 are blue
axis = :auto, # lines 1 and 3 are on the left axis, lines 2 and 4 are on the right
markershape = [:rect, :star1] # (Vector) ALL lines are passed the vector [:rect, :star1]
markershape = [:rect, :star] # (Vector) ALL lines are passed the vector [:rect, :star1]
width = 5) # all lines have a width of 5
```
@ -339,8 +349,9 @@ __Tip__: Call `gui()` to display the plot in a window. Interactivity depends on
- [x] Annotations
- [x] Scales
- [x] Categorical Inputs (strings, etc... for hist, bar? or can split one series into multiple?)
- [ ] Custom markers
- [ ] Special plots (boxplot, ohlc?)
- [x] Custom markers
- [ ] Contours
- [ ] Boxplots
- [x] Subplots
- [x] Histograms
- [ ] 3D plotting

View File

@ -71,7 +71,7 @@ const examples = PlotExample[
[:(styles = setdiff(supportedStyles(), [:auto])'), :(plot(cumsum(randn(20,length(styles)),1); style=:auto, label=map(string,styles), w=5))]),
PlotExample("Marker types",
"",
[:(markers = setdiff(supportedMarkers(), [:none,:auto])'), :(scatter(0.5:9.5, [fill(i-0.5,10) for i=length(markers):-1:1]; marker=:auto, label=map(string,markers), ms=12, ylim=(0,length(markers)+1)))]),
[:(markers = setdiff(supportedMarkers(), [:none,:auto,Shape])'), :(n = length(markers)), :(scatter(0.5:9.5, [fill(i-0.5,10) for i=n:-1:1]; marker=(12,:auto), lab=map(string,markers), ms=12, ylim=(0,n), bg=RGB(0.2,0.2,0.2)))]),
PlotExample("Bar",
"x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)",
[:(bar(randn(999)))]),

View File

@ -215,6 +215,7 @@ Markers:
[[MARKERS_TABLE]]
__Tip__: With supported backends, you can pass a `Plots.Shape` object for the `marker`/`markershape` arguments. `Shape` takes a vector of 2-tuples in the constructor, defining the points of the polygon's shape in a unit-scaled coordinate space. To make a square, for example, you could do `Shape([(1,1),(1,-1),(-1,-1),(-1,1)])`
__Tip__: You can see the default value for a given argument with `default(arg::Symbol)`, and set the default value with `default(arg::Symbol, value)` or `default(; kw...)`. For example set the default window size and whether we should show a legend with `default(size=(600,400), leg=false)`.
@ -252,8 +253,9 @@ __Tip__: Call `gui()` to display the plot in a window. Interactivity depends on
- [x] Annotations
- [x] Scales
- [x] Categorical Inputs (strings, etc... for hist, bar? or can split one series into multiple?)
- [ ] Custom markers
- [ ] Special plots (boxplot, ohlc?)
- [x] Custom markers
- [ ] Contours
- [ ] Boxplots
- [x] Subplots
- [x] Histograms
- [ ] 3D plotting

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -60,6 +60,8 @@ export
dataframes,
Shape,
PlotText,
text,
OHLC,
colorscheme,
@ -125,39 +127,43 @@ ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc)
ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc)
title!(s::@compat(AbstractString)) = plot!(title = s)
xlabel!(s::@compat(AbstractString)) = plot!(xlabel = s)
ylabel!(s::@compat(AbstractString)) = plot!(ylabel = s)
xlims!{T<:Real,S<:Real}(lims::@compat(Tuple{T,S})) = plot!(xlims = lims)
ylims!{T<:Real,S<:Real}(lims::@compat(Tuple{T,S})) = plot!(ylims = lims)
xlims!(xmin::Real, xmax::Real) = plot!(xlims = (xmin,xmax))
ylims!(ymin::Real, ymax::Real) = plot!(ylims = (ymin,ymax))
xticks!{T<:Real}(v::AVec{T}) = plot!(xticks = v)
yticks!{T<:Real}(v::AVec{T}) = plot!(yticks = v)
xticks!{T<:Real,S<:@compat(AbstractString)}(ticks::AVec{T}, labels::AVec{S}) = plot!(xticks = (ticks,labels))
yticks!{T<:Real,S<:@compat(AbstractString)}(ticks::AVec{T}, labels::AVec{S}) = plot!(yticks = (ticks,labels))
annotate!(anns) = plot!(annotation = anns)
xflip!(flip::Bool = true) = plot!(xflip = flip)
yflip!(flip::Bool = true) = plot!(yflip = flip)
xaxis!(args...) = plot!(xaxis = args)
yaxis!(args...) = plot!(yaxis = args)
title!(s::@compat(AbstractString); kw...) = plot!(; title = s, kw...)
xlabel!(s::@compat(AbstractString); kw...) = plot!(; xlabel = s, kw...)
ylabel!(s::@compat(AbstractString); kw...) = plot!(; ylabel = s, kw...)
xlims!{T<:Real,S<:Real}(lims::@compat(Tuple{T,S}); kw...) = plot!(; xlims = lims, kw...)
ylims!{T<:Real,S<:Real}(lims::@compat(Tuple{T,S}); kw...) = plot!(; ylims = lims, kw...)
xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...)
ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...)
xticks!{T<:Real}(v::AVec{T}; kw...) = plot!(; xticks = v, kw...)
yticks!{T<:Real}(v::AVec{T}; kw...) = plot!(; yticks = v, kw...)
xticks!{T<:Real,S<:@compat(AbstractString)}(
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; xticks = (ticks,labels), kw...)
yticks!{T<:Real,S<:@compat(AbstractString)}(
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; yticks = (ticks,labels), kw...)
annotate!(anns...; kw...) = plot!(; annotation = anns, kw...)
xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...)
yflip!(flip::Bool = true; kw...) = plot!(; yflip = flip, kw...)
xaxis!(args...; kw...) = plot!(; xaxis = args, kw...)
yaxis!(args...; kw...) = plot!(; yaxis = args, kw...)
title!(plt::Plot, s::@compat(AbstractString)) = plot!(plt; title = s)
xlabel!(plt::Plot, s::@compat(AbstractString)) = plot!(plt; xlabel = s)
ylabel!(plt::Plot, s::@compat(AbstractString)) = plot!(plt; ylabel = s)
xlims!{T<:Real,S<:Real}(plt::Plot, lims::@compat(Tuple{T,S})) = plot!(plt; xlims = lims)
ylims!{T<:Real,S<:Real}(plt::Plot, lims::@compat(Tuple{T,S})) = plot!(plt; ylims = lims)
xlims!(plt::Plot, xmin::Real, xmax::Real) = plot!(plt; xlims = (xmin,xmax))
ylims!(plt::Plot, ymin::Real, ymax::Real) = plot!(plt; ylims = (ymin,ymax))
xticks!{T<:Real}(plt::Plot, ticks::AVec{T}) = plot!(plt; xticks = ticks)
yticks!{T<:Real}(plt::Plot, ticks::AVec{T}) = plot!(plt; yticks = ticks)
xticks!{T<:Real,S<:@compat(AbstractString)}(plt::Plot, ticks::AVec{T}, labels::AVec{S}) = plot!(plt; xticks = (ticks,labels))
yticks!{T<:Real,S<:@compat(AbstractString)}(plt::Plot, ticks::AVec{T}, labels::AVec{S}) = plot!(plt; yticks = (ticks,labels))
annotate!(plt::Plot, anns) = plot!(plt; annotation = anns)
xflip!(plt::Plot, flip::Bool = true) = plot!(plt; xflip = flip)
yflip!(plt::Plot, flip::Bool = true) = plot!(plt; yflip = flip)
xaxis!(plt::Plot, args...) = plot!(plt; xaxis = args)
yaxis!(plt::Plot, args...) = plot!(plt; yaxis = args)
title!(plt::Plot, s::@compat(AbstractString); kw...) = plot!(plt; title = s, kw...)
xlabel!(plt::Plot, s::@compat(AbstractString); kw...) = plot!(plt; xlabel = s, kw...)
ylabel!(plt::Plot, s::@compat(AbstractString); kw...) = plot!(plt; ylabel = s, kw...)
xlims!{T<:Real,S<:Real}(plt::Plot, lims::@compat(Tuple{T,S}); kw...) = plot!(plt; xlims = lims, kw...)
ylims!{T<:Real,S<:Real}(plt::Plot, lims::@compat(Tuple{T,S}); kw...) = plot!(plt; ylims = lims, kw...)
xlims!(plt::Plot, xmin::Real, xmax::Real; kw...) = plot!(plt; xlims = (xmin,xmax), kw...)
ylims!(plt::Plot, ymin::Real, ymax::Real; kw...) = plot!(plt; ylims = (ymin,ymax), kw...)
xticks!{T<:Real}(plt::Plot, ticks::AVec{T}; kw...) = plot!(plt; xticks = ticks, kw...)
yticks!{T<:Real}(plt::Plot, ticks::AVec{T}; kw...) = plot!(plt; yticks = ticks, kw...)
xticks!{T<:Real,S<:@compat(AbstractString)}(plt::Plot,
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(plt; xticks = (ticks,labels), kw...)
yticks!{T<:Real,S<:@compat(AbstractString)}(plt::Plot,
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(plt; yticks = (ticks,labels), kw...)
annotate!(plt::Plot, anns...; kw...) = plot!(plt; annotation = anns, kw...)
xflip!(plt::Plot, flip::Bool = true; kw...) = plot!(plt; xflip = flip, kw...)
yflip!(plt::Plot, flip::Bool = true; kw...) = plot!(plt; yflip = flip, kw...)
xaxis!(plt::Plot, args...; kw...) = plot!(plt; xaxis = args, kw...)
yaxis!(plt::Plot, args...; kw...) = plot!(plt; yaxis = args, kw...)
# ---------------------------------------------------------

View File

@ -615,7 +615,9 @@ function getSeriesArgs(pkg::PlottingPackage, initargs::Dict, kw, commandIndex::I
aliasesAndAutopick(d, :markershape, _markerAliases, supportedMarkers(pkg), plotIndex)
# update color
dumpdict(d, "before color")
d[:color] = getSeriesRGBColor(d[:color], initargs, plotIndex)
dumpdict(d, "after color")
# update markercolor
mc = d[:markercolor]

View File

@ -497,6 +497,20 @@ function createGadflyAnnotationObject(x, y, val::@compat(AbstractString))
))
end
function createGadflyAnnotationObject(x, y, txt::PlotText)
halign = (txt.halign == :hcenter ? Compose.hcenter : (txt.halign == :left ? Compose.hleft : Compose.hright))
valign = (txt.valign == :vcenter ? Compose.vcenter : (txt.valign == :top ? Compose.vtop : Compose.vbottom))
rotations = (txt.rotation == 0.0 ? [] : [Compose.Rotation(txt.rotation, Compose.Point(Compose.x_measure(x), Compose.y_measure(y)))])
Gadfly.Guide.annotation(Compose.compose(
Compose.context(),
Compose.text(x, y, txt.str, halign, valign, rotations...),
Compose.font(string(txt.family)),
Compose.fontsize(txt.pointsize * Gadfly.pt),
Compose.stroke(txt.color),
Compose.fill(txt.color)
))
end
function addAnnotations{X,Y,V}(plt::Plot{GadflyPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
push!(plt.o.guides, createGadflyAnnotationObject(ann...))

View File

@ -102,6 +102,7 @@ function plot!(plt::Plot, args...; kw...)
preparePlotUpdate(plt)
# get the list of dictionaries, one per series
dumpdict(d, "before createKWargsList")
kwList, xmeta, ymeta = createKWargsList(plt, groupargs..., args...; d...)
# if we were able to extract guide information from the series inputs, then update the plot
@ -185,8 +186,8 @@ updateDictWithMeta(d::Dict, initargs::Dict, meta, isx::Bool) = nothing
# --------------------------------------------------------------------
annotations(::@compat(Void)) = []
annotations{X<:Real, Y<:Real, V}(v::AVec{@compat(Tuple{X,Y,V})}) = v
annotations{X<:Real, Y<:Real, V}(t::@compat(Tuple{X,Y,V})) = [t]
annotations{X,Y,V}(v::AVec{@compat(Tuple{X,Y,V})}) = v
annotations{X,Y,V}(t::@compat(Tuple{X,Y,V})) = [t]
annotations(anns) = error("Expecting a tuple (or vector of tuples) for annotations: ",
"(x, y, annotation)\n got: $(typeof(anns))")
@ -259,6 +260,9 @@ end
function createKWargsList(plt::PlottingObject, x, y; kw...)
xs, xmeta = convertToAnyVector(x; kw...)
ys, ymeta = convertToAnyVector(y; kw...)
# _debugMode.on && dumpcallstack()
mx = length(xs)
my = length(ys)
ret = Any[]
@ -277,7 +281,9 @@ function createKWargsList(plt::PlottingObject, x, y; kw...)
# build the series arg dict
numUncounted = get(d, :numUncounted, 0)
n = plt.n + i + numUncounted
dumpdict(d, "before getSeriesArgs")
d = getSeriesArgs(plt.backend, getinitargs(plt, n), d, i + numUncounted, convertSeriesIndex(plt, n), n)
dumpdict(d, "after getSeriesArgs")
d[:x], d[:y] = computeXandY(xs[mod1(i,mx)], ys[mod1(i,my)])
if haskey(d, :idxfilter)
@ -325,6 +331,16 @@ function createKWargsList(plt::PlottingObject, y; kw...)
createKWargsList(plt, nothing, y; kw...)
end
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, z::AVec; kw...)
error("TODO: contours or surfaces... irregular data")
end
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, z::Function; kw...)
error("TODO: contours or surfaces... function grid")
end
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, z::AMat; kw...)
error("TODO: contours or surfaces... grid")
end
function createKWargsList(plt::PlottingObject, f::FuncOrFuncs; kw...)
error("Can't pass a Function or Vector{Function} for y without also passing x")
end
@ -347,7 +363,7 @@ mapFuncOrFuncs(fs::AVec{Function}, u::AVec) = [map(f, u) for f in fs]
# special handling... xmin/xmax with parametric function(s)
createKWargsList{T<:Real}(plt::PlottingObject, fx::FuncOrFuncs, fy::FuncOrFuncs, u::AVec{T}; kw...) = createKWargsList(plt, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u); kw...)
createKWargsList{T<:Real}(plt::PlottingObject, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs; kw...) = createKWargsList(plt, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u); kw...)
createKWargsList(plt::PlottingObject, fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Real, umax::Real, numPoints::Int = 1000; kw...) = createKWargsList(plt, fx, fy, linspace(umin, umax, numPoints))
createKWargsList(plt::PlottingObject, fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Real, umax::Real, numPoints::Int = 1000; kw...) = createKWargsList(plt, fx, fy, linspace(umin, umax, numPoints); kw...)

View File

@ -51,85 +51,6 @@ immutable Shape
vertices::AVec
end
# const _square = Shape(@compat(Tuple{Float64,Float64})[
# ( 1.0, -1.0),
# ( 1.0, 1.0),
# (-1.0, 1.0),
# (-1.0, -1.0)
# ])
# const _diamond = Shape(@compat(Tuple{Float64,Float64})[
# ( 0.0, -1.0),
# ( 1.0, 0.0),
# ( 0.0, 1.0),
# (-1.0, 0.0)
# ])
# const _cross = Shape(@compat(Tuple{Float64,Float64})[
# (-1.0, -0.4), (-1.0, 0.4), # L edge
# (-0.4, 0.4), # BL inside
# (-0.4, 1.0), ( 0.4, 1.0), # B edge
# ( 0.4, 0.4), # BR inside
# ( 1.0, 0.4), ( 1.0, -0.4), # R edge
# ( 0.4, -0.4), # TR inside
# ( 0.4, -1.0), (-0.4, -1.0), # T edge
# (-0.4, -0.4) # TL inside
# ])
# const _xcross = Shape(@compat(Tuple{Float64,Float64})[
# (x, y - u), (x + u, y - 2u), (x + 2u, y - u),
# (x + u, y), (x + 2u, y + u), (x + u, y + 2u),
# (x, y + u), (x - u, y + 2u), (x - 2u, y + u),
# (x - u, y), (x - 2u, y - u), (x - u, y - 2u)
# ]
# function xcross(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# s = 1/sqrt(5)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = s*r
# polys[i] = [
# (x, y - u), (x + u, y - 2u), (x + 2u, y - u),
# (x + u, y), (x + 2u, y + u), (x + u, y + 2u),
# (x, y + u), (x - u, y + 2u), (x - 2u, y + u),
# (x - u, y), (x - 2u, y - u), (x - u, y - 2u)
# ]
# end
# return Gadfly.polygon(polys)
# end
# const _utriangle = Shape(@compat(Tuple{Float64,Float64})[
# (x - r, y + u),
# (x + r, y + u),
# (x, y - u)
# ]
# function utriangle(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# s = 0.8
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.8 * scalar * r
# polys[i] = [
# (x - r, y + u),
# (x + r, y + u),
# (x, y - u)
# ]
# end
# return Gadfly.polygon(polys)
# end
"get an array of tuples of points on a circle with radius `r`"
function partialcircle(start_θ, end_θ, n = 20, r=1)
@compat(Tuple{Float64,Float64})[(r*cos(u),r*sin(u)) for u in linspace(start_θ, end_θ, n)]
@ -198,62 +119,57 @@ for n in [4,5,6,7,8]
_shapes[symbol("star$n")] = makestar(n)
end
# -----------------------------------------------------------------------
# :ellipse, :rect, :diamond, :utriangle, :dtriangle,
# :cross, :xcross, :star1, :star2, :hexagon, :octagon
"Wrap a string with font info"
immutable PlotText
str::@compat(AbstractString)
family::Symbol
pointsize::Int
halign::Symbol
valign::Symbol
rotation::Float64
color::Colorant
end
function text(str, args...)
# defaults
family = :courier
pointsize = 12
halign = :hcenter
valign = :vcenter
rotation = 0.0
color = colorant"black"
# const _xcross = Shape(@compat(Tuple{Float64,Float64})[
# ]
for arg in args
if arg == :center
halign = :hcenter
valign = :vcenter
elseif arg in (:hcenter, :left, :right)
halign = arg
elseif arg in (:vcenter, :top, :bottom)
valign = arg
elseif typeof(arg) <: Colorant
color = arg
elseif isa(arg, Symbol)
try
color = parse(Colorant, string(arg))
catch
family = arg
end
elseif typeof(arg) <: Integer
pointsize = arg
elseif typeof(arg) <: Real
rotation = convert(Float64, arg)
else
warn("Unused font arg: $arg ($(typeof(arg)))")
end
end
# # function hexagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# # n = max(length(xs), length(ys), length(rs))
# # polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# # for i in 1:n
# # x = Compose.x_measure(xs[mod1(i, length(xs))])
# # y = Compose.y_measure(ys[mod1(i, length(ys))])
# # r = rs[mod1(i, length(rs))]
# # u = 0.6r
# # polys[i] = [
# # (x-r, y-u), (x-r, y+u), # L edge
# # (x, y+r), # B
# # (x+r, y+u), (x+r, y-u), # R edge
# # (x, y-r) # T
# # ]
# # end
# # return Gadfly.polygon(polys)
# # end
# const _xcross = Shape(@compat(Tuple{Float64,Float64})[
# ]
# function octagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
# n = max(length(xs), length(ys), length(rs))
# polys = Array(Vector{@compat(Tuple{Compose.Measure, Compose.Measure})}, n)
# for i in 1:n
# x = Compose.x_measure(xs[mod1(i, length(xs))])
# y = Compose.y_measure(ys[mod1(i, length(ys))])
# r = rs[mod1(i, length(rs))]
# u = 0.4r
# polys[i] = [
# (x-r, y-u), (x-r, y+u), # L edge
# (x-u, y+r), (x+u, y+r), # B edge
# (x+r, y+u), (x+r, y-u), # R edge
# (x+u, y-r), (x-u, y-r), # T edge
# ]
# end
# return Gadfly.polygon(polys)
# end
PlotText(string(str), family, pointsize, halign, valign, rotation, color)
end
# -----------------------------------------------------------------------

View File

@ -200,6 +200,11 @@ function dumpdict(d::Dict, prefix = "")
println()
end
function dumpcallstack()
error() # well... you wanted the stacktrace, didn't you?!?
end
# ---------------------------------------------------------------