commit
1e6cee2c5d
@ -66,6 +66,7 @@ function _initialize_backend(::GLVisualizeBackend; kw...)
|
|||||||
import GLAbstraction: Style
|
import GLAbstraction: Style
|
||||||
import GLVisualize: visualize
|
import GLVisualize: visualize
|
||||||
import Plots.GL
|
import Plots.GL
|
||||||
|
import UnicodeFun
|
||||||
Plots.slice_arg(img::Images.AbstractImage, idx::Int) = img
|
Plots.slice_arg(img::Images.AbstractImage, idx::Int) = img
|
||||||
is_marker_supported(::GLVisualizeBackend, shape::GLVisualize.AllPrimitives) = true
|
is_marker_supported(::GLVisualizeBackend, shape::GLVisualize.AllPrimitives) = true
|
||||||
is_marker_supported{Img<:Images.AbstractImage}(::GLVisualizeBackend, shape::Union{Vector{Img}, Img}) = true
|
is_marker_supported{Img<:Images.AbstractImage}(::GLVisualizeBackend, shape::Union{Vector{Img}, Img}) = true
|
||||||
@ -108,17 +109,23 @@ function empty_screen!(screen)
|
|||||||
end
|
end
|
||||||
nothing
|
nothing
|
||||||
end
|
end
|
||||||
|
function poll_reactive()
|
||||||
|
# run_till_now blocks when message queue is empty!
|
||||||
|
Base.n_avail(Reactive._messages) > 0 && Reactive.run_till_now()
|
||||||
|
end
|
||||||
function create_window(plt::Plot{GLVisualizeBackend}, visible)
|
function create_window(plt::Plot{GLVisualizeBackend}, visible)
|
||||||
# init a screen
|
# init a screen
|
||||||
if isempty(GLVisualize.get_screens())
|
if isempty(GLVisualize.get_screens())
|
||||||
screen = GLVisualize.glscreen(resolution = plt[:size], visible = visible)
|
screen = GLVisualize.glscreen("Plots.jl", resolution = plt[:size], visible = visible)
|
||||||
Reactive.stop()
|
Reactive.stop()
|
||||||
|
|
||||||
@async begin
|
@async begin
|
||||||
while isopen(screen)
|
while isopen(screen)
|
||||||
tic()
|
tic()
|
||||||
GLWindow.pollevents()
|
GLWindow.pollevents()
|
||||||
if Base.n_avail(Reactive._messages) > 0
|
if Base.n_avail(Reactive._messages) > 0
|
||||||
Reactive.run_till_now()
|
poll_reactive()
|
||||||
|
poll_reactive() # two times for secondary signals
|
||||||
GLWindow.render_frame(screen)
|
GLWindow.render_frame(screen)
|
||||||
GLWindow.swapbuffers(screen)
|
GLWindow.swapbuffers(screen)
|
||||||
end
|
end
|
||||||
@ -130,6 +137,8 @@ function create_window(plt::Plot{GLVisualizeBackend}, visible)
|
|||||||
diff -= toq()
|
diff -= toq()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
# empty message queue
|
||||||
|
poll_reactive()
|
||||||
GLWindow.destroy!(screen)
|
GLWindow.destroy!(screen)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -167,7 +176,12 @@ function gl_marker(shape)
|
|||||||
shape
|
shape
|
||||||
end
|
end
|
||||||
function gl_marker(shape::Shape)
|
function gl_marker(shape::Shape)
|
||||||
points = Point2f0[Vec{2,Float32}(p)*10f0 for p in zip(shape.x, shape.y)]
|
points = Point2f0[Vec{2,Float32}(p) for p in zip(shape.x, shape.y)]
|
||||||
|
bb = GeometryTypes.AABB(points)
|
||||||
|
mini, maxi = minimum(bb), maximum(bb)
|
||||||
|
w3 = maxi-mini
|
||||||
|
origin, width = Point2f0(mini[1], mini[2]), Point2f0(w3[1], w3[2])
|
||||||
|
map!(p -> ((p - origin) ./ width) - 0.5f0, points) # normalize and center
|
||||||
GeometryTypes.GLNormalMesh(points)
|
GeometryTypes.GLNormalMesh(points)
|
||||||
end
|
end
|
||||||
# create a marker/shape type
|
# create a marker/shape type
|
||||||
@ -413,19 +427,18 @@ function hover(to_hover, to_display, window)
|
|||||||
end
|
end
|
||||||
mh = GLWindow.mouse2id(window)
|
mh = GLWindow.mouse2id(window)
|
||||||
popup = GLWindow.Screen(
|
popup = GLWindow.Screen(
|
||||||
window, hidden=true, area=area,
|
window,
|
||||||
stroke=(2f0/100f0, RGBA(0f0, 0f0, 0f0, 0.8f0))
|
hidden = map(mh-> !(mh.id == to_hover.id), mh),
|
||||||
|
area = area,
|
||||||
|
stroke = (2f0, RGBA(0f0, 0f0, 0f0, 0.8f0))
|
||||||
)
|
)
|
||||||
cam = get!(popup.cameras, :perspective) do
|
cam = get!(popup.cameras, :perspective) do
|
||||||
GLAbstraction.PerspectiveCamera(
|
GLAbstraction.PerspectiveCamera(
|
||||||
popup.inputs, Vec3f0(3), Vec3f0(0),
|
popup.inputs, Vec3f0(3), Vec3f0(0),
|
||||||
keep=Signal(false),
|
keep = Signal(false),
|
||||||
theta= Signal(Vec3f0(0)), trans= Signal(Vec3f0(0))
|
theta = Signal(Vec3f0(0)), trans= Signal(Vec3f0(0))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
Reactive.preserve(map(mh) do mh
|
|
||||||
popup.hidden = !(mh.id == to_hover.id)
|
|
||||||
end)
|
|
||||||
|
|
||||||
map(enumerate(to_display)) do id
|
map(enumerate(to_display)) do id
|
||||||
i,d = id
|
i,d = id
|
||||||
@ -461,7 +474,7 @@ end
|
|||||||
|
|
||||||
function extract_font(font, kw_args)
|
function extract_font(font, kw_args)
|
||||||
kw_args[:family] = font.family
|
kw_args[:family] = font.family
|
||||||
kw_args[:relative_scale] = font.pointsize ./ GLVisualize.glyph_scale!('X')
|
kw_args[:relative_scale] = pointsize(font)
|
||||||
kw_args[:color] = gl_color(font.color)
|
kw_args[:color] = gl_color(font.color)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -545,7 +558,7 @@ function draw_grid_lines(sp, grid_segs, thickness, style, model, color)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function align_offset(startpos, lastpos, atlas, rscale, font, align)
|
function align_offset(startpos, lastpos, atlas, rscale, font, align)
|
||||||
xscale, yscale = GLVisualize.glyph_scale!('X').*rscale
|
xscale, yscale = GLVisualize.glyph_scale!('X', rscale)
|
||||||
xmove = (lastpos-startpos)[1]+xscale
|
xmove = (lastpos-startpos)[1]+xscale
|
||||||
if align == :top
|
if align == :top
|
||||||
return -Vec2f0(xmove/2f0, yscale)
|
return -Vec2f0(xmove/2f0, yscale)
|
||||||
@ -556,8 +569,8 @@ function align_offset(startpos, lastpos, atlas, rscale, font, align)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
function align_offset(startpos, lastpos, atlas, rscale, font, align::Vec)
|
function align_offset(startpos, lastpos, atlas, rscale, font, align::Vec)
|
||||||
xscale, yscale = GLVisualize.glyph_scale!('X').*rscale
|
xscale, yscale = GLVisualize.glyph_scale!('X', rscale)
|
||||||
xmove = (lastpos-startpos)[1]+xscale
|
xmove = (lastpos-startpos)[1] + xscale
|
||||||
return -Vec2f0(xmove, yscale) .* align
|
return -Vec2f0(xmove, yscale) .* align
|
||||||
end
|
end
|
||||||
function alignment2num(x::Symbol)
|
function alignment2num(x::Symbol)
|
||||||
@ -569,33 +582,48 @@ end
|
|||||||
function alignment2num(font::Plots.Font)
|
function alignment2num(font::Plots.Font)
|
||||||
Vec2f0(map(alignment2num, (font.halign, font.valign)))
|
Vec2f0(map(alignment2num, (font.halign, font.valign)))
|
||||||
end
|
end
|
||||||
|
pointsize(font) = font.pointsize * 2
|
||||||
|
|
||||||
function draw_ticks(axis, ticks, align, move, isx, lims, model, text = "", positions = Point2f0[], offsets=Vec2f0[])
|
function draw_ticks(
|
||||||
sz = axis[:tickfont].pointsize
|
axis, ticks, isx, lims, m, text = "",
|
||||||
rscale2 = Vec2f0(2.5/sz)
|
positions = Point2f0[], offsets=Vec2f0[]
|
||||||
m = Reactive.value(model)
|
)
|
||||||
xs, ys = m[1,1], m[2,2]
|
sz = pointsize(axis[:tickfont])
|
||||||
rscale = rscale2 ./ Vec2f0(xs, ys)
|
|
||||||
atlas = GLVisualize.get_texture_atlas()
|
atlas = GLVisualize.get_texture_atlas()
|
||||||
font = GLVisualize.defaultfont()
|
font = GLVisualize.defaultfont()
|
||||||
if !(ticks in (nothing, false))
|
|
||||||
# x labels
|
flip = axis[:flip]; mirror = axis[:mirror]
|
||||||
flip = axis[:flip]
|
|
||||||
for (cv, dv) in zip(ticks...)
|
align = if isx
|
||||||
x,y = cv, (flip ? lims[2] : lims[1])
|
mirror ? :bottom : :top
|
||||||
startpos = Point2f0(isx ? (x,y) : (y,x))-move
|
else
|
||||||
# @show cv dv ymin xi yi
|
mirror ? :left : :right
|
||||||
str = string(dv)
|
end
|
||||||
position = GLVisualize.calc_position(str, startpos, rscale, font, atlas)
|
axis_gap = Point2f0(isx ? 0 : sz / 2, isx ? sz / 2 : 0)
|
||||||
offset = GLVisualize.calc_offset(str, rscale2, font, atlas)
|
for (cv, dv) in zip(ticks...)
|
||||||
alignoff = align_offset(startpos, last(position), atlas, rscale, font, align)
|
|
||||||
map!(position) do pos
|
x, y = cv, lims[1]
|
||||||
pos .+ alignoff
|
xy = isx ? (x, y) : (y, x)
|
||||||
end
|
_pos = m * GeometryTypes.Vec4f0(xy[1], xy[2], 0, 1)
|
||||||
append!(positions, position)
|
startpos = Point2f0(_pos[1], _pos[2]) - axis_gap
|
||||||
append!(offsets, offset)
|
str = string(dv)
|
||||||
text *= str
|
# need to tag a new UnicodeFun version for this... also the numbers become
|
||||||
|
# so small that it looks terrible -.-
|
||||||
|
# _str = split(string(dv), "^")
|
||||||
|
# if length(_str) == 2
|
||||||
|
# _str[2] = UnicodeFun.to_superscript(_str[2])
|
||||||
|
# end
|
||||||
|
# str = join(_str, "")
|
||||||
|
position = GLVisualize.calc_position(str, startpos, sz, font, atlas)
|
||||||
|
offset = GLVisualize.calc_offset(str, sz, font, atlas)
|
||||||
|
alignoff = align_offset(startpos, last(position), atlas, sz, font, align)
|
||||||
|
map!(position) do pos
|
||||||
|
pos .+ alignoff
|
||||||
end
|
end
|
||||||
|
append!(positions, position)
|
||||||
|
append!(offsets, offset)
|
||||||
|
text *= str
|
||||||
|
|
||||||
end
|
end
|
||||||
text, positions, offsets
|
text, positions, offsets
|
||||||
end
|
end
|
||||||
@ -646,38 +674,42 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
|
|||||||
|
|
||||||
xlim = Plots.axis_limits(xaxis)
|
xlim = Plots.axis_limits(xaxis)
|
||||||
ylim = Plots.axis_limits(yaxis)
|
ylim = Plots.axis_limits(yaxis)
|
||||||
m = Reactive.value(model)
|
|
||||||
xs, ys = m[1,1], m[2,2]
|
if !(xaxis[:ticks] in (nothing, false, :none))
|
||||||
# TODO: we should make sure we actually need to draw these...
|
ticklabels = map(model) do m
|
||||||
t, positions, offsets = draw_ticks(xaxis, xticks, :top, Point2f0(0, 7/ys), true, ylim, model)
|
mirror = xaxis[:mirror]
|
||||||
t, positions, offsets = draw_ticks(yaxis, yticks, :right, Point2f0(7/xs, 0), false, xlim, model, t, positions, offsets)
|
t, positions, offsets = draw_ticks(xaxis, xticks, true, ylim, m)
|
||||||
sz = xaxis[:tickfont].pointsize
|
mirror = xaxis[:mirror]
|
||||||
kw_args = Dict{Symbol, Any}(
|
t, positions, offsets = draw_ticks(
|
||||||
:position => positions,
|
yaxis, yticks, false, xlim, m,
|
||||||
:offset => offsets,
|
t, positions, offsets
|
||||||
:color => fcolor,
|
)
|
||||||
:relative_scale => Vec2f0(2.5/sz),
|
end
|
||||||
:model => model,
|
kw_args = Dict{Symbol, Any}(
|
||||||
:scale_primitive => false
|
:position => map(x-> x[2], ticklabels),
|
||||||
)
|
:offset => map(last, ticklabels),
|
||||||
if !(xaxis[:ticks] in (nothing,false,:none))
|
:color => fcolor,
|
||||||
push!(axis_vis, visualize(t, Style(:default), kw_args))
|
:relative_scale => pointsize(xaxis[:tickfont]),
|
||||||
|
:scale_primitive => false
|
||||||
|
)
|
||||||
|
push!(axis_vis, visualize(map(first, ticklabels), Style(:default), kw_args))
|
||||||
end
|
end
|
||||||
|
|
||||||
area_w = GeometryTypes.widths(area)
|
area_w = GeometryTypes.widths(area)
|
||||||
if sp[:title] != ""
|
if sp[:title] != ""
|
||||||
tf = sp[:titlefont]; color = gl_color(sp[:foreground_color_title])
|
tf = sp[:titlefont]; color = gl_color(sp[:foreground_color_title])
|
||||||
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, tf.rotation, color)
|
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, tf.rotation, color)
|
||||||
xy = Point2f0(area.w/2, area_w[2])
|
xy = Point2f0(area.w/2, area_w[2] + pointsize(tf)/2)
|
||||||
kw = Dict(:model => text_model(font, xy), :scale_primitive=>true)
|
kw = Dict(:model => text_model(font, xy), :scale_primitive => true)
|
||||||
extract_font(font, kw)
|
extract_font(font, kw)
|
||||||
t = PlotText(sp[:title], font)
|
t = PlotText(sp[:title], font)
|
||||||
push!(axis_vis, text(xy, t, kw))
|
push!(axis_vis, text(xy, t, kw))
|
||||||
end
|
end
|
||||||
if xaxis[:guide] != ""
|
if xaxis[:guide] != ""
|
||||||
tf = xaxis[:guidefont]; color = gl_color(xaxis[:foreground_color_guide])
|
tf = xaxis[:guidefont]; color = gl_color(xaxis[:foreground_color_guide])
|
||||||
xy = Point2f0(area.w/2, 0)
|
xy = Point2f0(area.w/2, - pointsize(tf)/2)
|
||||||
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :bottom, tf.rotation, color)
|
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :bottom, tf.rotation, color)
|
||||||
kw = Dict(:model => text_model(font, xy), :scale_primitive=>true)
|
kw = Dict(:model => text_model(font, xy), :scale_primitive => true)
|
||||||
t = PlotText(xaxis[:guide], font)
|
t = PlotText(xaxis[:guide], font)
|
||||||
extract_font(font, kw)
|
extract_font(font, kw)
|
||||||
push!(axis_vis, text(xy, t, kw))
|
push!(axis_vis, text(xy, t, kw))
|
||||||
@ -686,7 +718,7 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
|
|||||||
if yaxis[:guide] != ""
|
if yaxis[:guide] != ""
|
||||||
tf = yaxis[:guidefont]; color = gl_color(yaxis[:foreground_color_guide])
|
tf = yaxis[:guidefont]; color = gl_color(yaxis[:foreground_color_guide])
|
||||||
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, 90f0, color)
|
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, 90f0, color)
|
||||||
xy = Point2f0(0, area.h/2)
|
xy = Point2f0(-pointsize(tf)/2, area.h/2)
|
||||||
kw = Dict(:model => text_model(font, xy), :scale_primitive=>true)
|
kw = Dict(:model => text_model(font, xy), :scale_primitive=>true)
|
||||||
t = PlotText(yaxis[:guide], font)
|
t = PlotText(yaxis[:guide], font)
|
||||||
extract_font(font, kw)
|
extract_font(font, kw)
|
||||||
@ -881,7 +913,7 @@ end
|
|||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
function _display(plt::Plot{GLVisualizeBackend}, visible=true)
|
function _display(plt::Plot{GLVisualizeBackend}, visible = true)
|
||||||
screen = create_window(plt, visible)
|
screen = create_window(plt, visible)
|
||||||
sw, sh = plt[:size]
|
sw, sh = plt[:size]
|
||||||
sw, sh = sw*px, sh*px
|
sw, sh = sw*px, sh*px
|
||||||
@ -928,7 +960,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible=true)
|
|||||||
Reactive.run_till_now() # make sure Reactive.push! arrives
|
Reactive.run_till_now() # make sure Reactive.push! arrives
|
||||||
GLAbstraction.center!(cam,
|
GLAbstraction.center!(cam,
|
||||||
GeometryTypes.AABB(
|
GeometryTypes.AABB(
|
||||||
Vec3f0(-10), Vec3f0((GeometryTypes.widths(sp_screen)+20f0)..., 1)
|
Vec3f0(-20), Vec3f0((GeometryTypes.widths(sp_screen)+40f0)..., 1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
@ -936,7 +968,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible=true)
|
|||||||
GLVisualize._view(axis, sp_screen, camera=:perspective)
|
GLVisualize._view(axis, sp_screen, camera=:perspective)
|
||||||
push!(cam.projectiontype, GLVisualize.PERSPECTIVE)
|
push!(cam.projectiontype, GLVisualize.PERSPECTIVE)
|
||||||
end
|
end
|
||||||
for series in Plots.series_list(sp)
|
for series in Plots.series_list(sp)
|
||||||
|
|
||||||
d = series.d
|
d = series.d
|
||||||
st = d[:seriestype]; kw_args = KW() # exctract kw
|
st = d[:seriestype]; kw_args = KW() # exctract kw
|
||||||
@ -1135,7 +1167,7 @@ function gl_scatter(points, kw_args)
|
|||||||
kw_args[:scale] = GLAbstraction.const_lift(kw_args[:model], kw_args[:scale], p) do m, sc, p
|
kw_args[:scale] = GLAbstraction.const_lift(kw_args[:model], kw_args[:scale], p) do m, sc, p
|
||||||
s = Vec3f0(m[1,1], m[2,2], m[3,3])
|
s = Vec3f0(m[1,1], m[2,2], m[3,3])
|
||||||
ps = Vec3f0(p[1,1], p[2,2], p[3,3])
|
ps = Vec3f0(p[1,1], p[2,2], p[3,3])
|
||||||
r = 1f0./(s.*ps)
|
r = sc./(s.*ps)
|
||||||
r
|
r
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1355,11 +1387,10 @@ function generate_legend(sp, screen, model_m)
|
|||||||
x,y = round(Int, p[1])+30, round(Int, p[2]-h)-30
|
x,y = round(Int, p[1])+30, round(Int, p[2]-h)-30
|
||||||
GeometryTypes.SimpleRectangle(x, y, w, h)
|
GeometryTypes.SimpleRectangle(x, y, w, h)
|
||||||
end
|
end
|
||||||
px_scale = minimum(GeometryTypes.widths(Reactive.value(area)))
|
|
||||||
sscren = GLWindow.Screen(
|
sscren = GLWindow.Screen(
|
||||||
screen, area=area,
|
screen, area = area,
|
||||||
color=sp[:background_color_legend],
|
color = sp[:background_color_legend],
|
||||||
stroke=(2f0/px_scale, RGBA{Float32}(0.3,0.3,0.3,0.9))
|
stroke = (2f0, RGBA(0.3, 0.3, 0.3, 0.9))
|
||||||
)
|
)
|
||||||
GLAbstraction.translate!(list, Vec3f0(10,10,0))
|
GLAbstraction.translate!(list, Vec3f0(10,10,0))
|
||||||
GLVisualize._view(list, sscren, camera=:fixed_pixel)
|
GLVisualize._view(list, sscren, camera=:fixed_pixel)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user