284 lines
7.7 KiB
Julia
284 lines
7.7 KiB
Julia
|
|
# Compose pseudo-forms for simple symbols, all parameterized by center and size
|
|
|
|
# using Compose: x_measure, y_measure
|
|
|
|
|
|
function createGadflyAnnotation(d::Dict)
|
|
sz = [d[:markersize] * Gadfly.px]
|
|
|
|
x, y = d[:x], d[:y]
|
|
marker = d[:markershape]
|
|
|
|
if d[:linetype] == :ohlc
|
|
shape = ohlcshape(x, y, d[:markersize])
|
|
d[:y] = Float64[z.open for z in y]
|
|
d[:linetype] = :none
|
|
return Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), shape, Gadfly.fill(nothing), Gadfly.stroke(getColor(d[:color],1))))
|
|
|
|
elseif marker == :rect
|
|
shape = square(x, y, sz)
|
|
|
|
elseif marker == :diamond
|
|
shape = diamond(x, y, sz)
|
|
|
|
elseif marker == :utriangle
|
|
shape = utriangle(x, y, sz)
|
|
|
|
elseif marker == :dtriangle
|
|
shape = utriangle(x, y, sz, -1)
|
|
|
|
elseif marker == :cross
|
|
shape = cross(x, y, sz)
|
|
|
|
elseif marker == :xcross
|
|
shape = xcross(x, y, sz)
|
|
|
|
elseif marker == :star1
|
|
shape = star1(x, y, sz)
|
|
|
|
elseif marker == :star2
|
|
shape = star2(x, y, sz)
|
|
|
|
elseif marker == :hexagon
|
|
shape = hexagon(x, y, sz)
|
|
|
|
elseif marker == :octagon
|
|
shape = octagon(x, y, sz)
|
|
|
|
else
|
|
# make circles
|
|
sz = 0.8 * d[:markersize] * Gadfly.px
|
|
xs = collect(float(d[:x]))
|
|
ys = collect(float(d[:y]))
|
|
shape = Gadfly.circle(xs,ys,[sz])
|
|
end
|
|
|
|
Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), shape, Gadfly.fill(getColorVector(d[:markercolor])), Gadfly.stroke(colorant"white")))
|
|
end
|
|
|
|
|
|
function square(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
|
|
n = max(length(xs), length(ys), length(rs))
|
|
rect_xs = Vector{Compose.Measure}(n)
|
|
rect_ys = Vector{Compose.Measure}(n)
|
|
rect_ws = Vector{Compose.Measure}(n)
|
|
s = 1/sqrt(2)
|
|
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))]
|
|
|
|
rect_xs[i] = x - s*r
|
|
rect_ys[i] = y + s*r
|
|
rect_ws[i] = 2*s*r
|
|
end
|
|
|
|
return Gadfly.rectangle(rect_xs, rect_ys, rect_ws, rect_ws)
|
|
end
|
|
|
|
|
|
function diamond(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
|
|
n = max(length(xs), length(ys), length(rs))
|
|
polys = Vector{Vector{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))]
|
|
polys[i] = Tuple{Compose.Measure, Compose.Measure}[(x, y - r), (x + r, y), (x, y + r), (x - r, y)]
|
|
end
|
|
|
|
return Gadfly.polygon(polys)
|
|
end
|
|
|
|
|
|
|
|
function cross(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
|
|
n = max(length(xs), length(ys), length(rs))
|
|
polys = Vector{Vector{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
|
|
|
|
# make a "plus sign"
|
|
polys[i] = Tuple{Compose.Measure, Compose.Measure}[
|
|
(x-r, y-u), (x-r, y+u), # L edge
|
|
(x-u, y+u), # BL inside
|
|
(x-u, y+r), (x+u, y+r), # B edge
|
|
(x+u, y+u), # BR inside
|
|
(x+r, y+u), (x+r, y-u), # R edge
|
|
(x+u, y-u), # TR inside
|
|
(x+u, y-r), (x-u, y-r), # T edge
|
|
(x-u, y-u) # TL inside
|
|
]
|
|
end
|
|
|
|
return Gadfly.polygon(polys)
|
|
end
|
|
|
|
function xcross(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
|
|
n = max(length(xs), length(ys), length(rs))
|
|
polys = Vector{Vector{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] = Tuple{Compose.Measure, Compose.Measure}[
|
|
(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
|
|
|
|
|
|
function utriangle(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
|
|
n = max(length(xs), length(ys), length(rs))
|
|
polys = Vector{Vector{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] = Tuple{Compose.Measure, Compose.Measure}[
|
|
(x - r, y + u),
|
|
(x + r, y + u),
|
|
(x, y - u)
|
|
]
|
|
end
|
|
|
|
return Gadfly.polygon(polys)
|
|
end
|
|
|
|
|
|
|
|
function star1(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
|
|
n = max(length(xs), length(ys), length(rs))
|
|
polys = Vector{Vector{Tuple{Compose.Measure, Compose.Measure}}}(n)
|
|
|
|
# some magic scalars
|
|
sx1, sx2, sx3 = 0.7, 0.4, 0.2
|
|
sy1, sy2, sy3 = 1.2, 0.45, 0.1
|
|
|
|
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))]
|
|
polys[i] = Tuple{Compose.Measure, Compose.Measure}[
|
|
(x-sx1*r, y+ r), # BL
|
|
(x, y+sy2*r),
|
|
(x+sx1*r, y+ r), # BR
|
|
(x+sx2*r, y+sy3*r),
|
|
(x+ r, y-sy2*r), # R
|
|
(x+sx3*r, y-sy2*r),
|
|
(x, y-sy1*r), # T
|
|
(x-sx3*r, y-sy2*r),
|
|
(x- r, y-sy2*r), # L
|
|
(x-sx2*r, y+sy3*r)
|
|
]
|
|
end
|
|
|
|
return Gadfly.polygon(polys)
|
|
end
|
|
|
|
|
|
|
|
function star2(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar = 1)
|
|
n = max(length(xs), length(ys), length(rs))
|
|
polys = Vector{Vector{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] = Tuple{Compose.Measure, Compose.Measure}[
|
|
(x-u, y), (x-r, y-r), # TL
|
|
(x, y-u), (x+r, y-r), # TR
|
|
(x+u, y), (x+r, y+r), # BR
|
|
(x, y+u), (x-r, y+r) # BL
|
|
]
|
|
end
|
|
|
|
return Gadfly.polygon(polys)
|
|
end
|
|
|
|
|
|
|
|
function hexagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
|
|
n = max(length(xs), length(ys), length(rs))
|
|
|
|
polys = Vector{Vector{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] = Tuple{Compose.Measure, Compose.Measure}[
|
|
(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
|
|
|
|
|
|
function octagon(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray)
|
|
n = max(length(xs), length(ys), length(rs))
|
|
|
|
polys = Vector{Vector{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] = Tuple{Compose.Measure, Compose.Measure}[
|
|
(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
|
|
|
|
|
|
# ---------------------------
|
|
|
|
function ohlcshape(xs::AVec, ys::AVec{OHLC}, tickwidth::Real)
|
|
@assert length(xs) == length(ys)
|
|
n = length(xs)
|
|
u = tickwidth * Compose.px
|
|
polys = Vector{Vector{Tuple{Compose.Measure, Compose.Measure}}}(n)
|
|
for i in 1:n
|
|
x = Compose.x_measure(xs[i])
|
|
o = Compose.y_measure(ys[i].open)
|
|
h = Compose.y_measure(ys[i].high)
|
|
l = Compose.y_measure(ys[i].low)
|
|
c = Compose.y_measure(ys[i].close)
|
|
# o,h,l,c = map(Compose.y_measure, ys[i])
|
|
polys[i] = Tuple{Compose.Measure, Compose.Measure}[
|
|
(x, o), (x - u, o), (x, o), # open tick
|
|
(x, l), (x, h), (x, c), # high/low bar
|
|
(x + u, c), (x, c) # close tick
|
|
]
|
|
end
|
|
return Gadfly.polygon(polys)
|
|
end
|
|
|
|
|
|
|