Merge pull request #559 from tbreloff/sd/dev
fix mesh particle size bug and better window creation
This commit is contained in:
commit
c9835a53e3
@ -29,7 +29,7 @@ export
|
|||||||
|
|
||||||
plot,
|
plot,
|
||||||
plot!,
|
plot!,
|
||||||
update!,
|
attr!,
|
||||||
|
|
||||||
current,
|
current,
|
||||||
default,
|
default,
|
||||||
|
|||||||
@ -1094,7 +1094,7 @@ function _update_axis(axis::Axis, d_in::KW, letter::Symbol, subplot_index::Int)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# update the axis
|
# update the axis
|
||||||
update!(axis, args...; kw...)
|
attr!(axis, args...; kw...)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ function Axis(sp::Subplot, letter::Symbol, args...; kw...)
|
|||||||
d[:discrete_values] = []
|
d[:discrete_values] = []
|
||||||
|
|
||||||
# update the defaults
|
# update the defaults
|
||||||
update!(Axis([sp], d), args...; kw...)
|
attr!(Axis([sp], d), args...; kw...)
|
||||||
end
|
end
|
||||||
|
|
||||||
function get_axis(sp::Subplot, letter::Symbol)
|
function get_axis(sp::Subplot, letter::Symbol)
|
||||||
@ -83,7 +83,7 @@ function process_axis_arg!(d::KW, arg, letter = "")
|
|||||||
end
|
end
|
||||||
|
|
||||||
# update an Axis object with magic args and keywords
|
# update an Axis object with magic args and keywords
|
||||||
function update!(axis::Axis, args...; kw...)
|
function attr!(axis::Axis, args...; kw...)
|
||||||
# first process args
|
# first process args
|
||||||
d = axis.d
|
d = axis.d
|
||||||
for arg in args
|
for arg in args
|
||||||
|
|||||||
@ -58,6 +58,7 @@ function tick_padding(axis::Axis)
|
|||||||
0mm
|
0mm
|
||||||
else
|
else
|
||||||
vals, labs = ticks
|
vals, labs = ticks
|
||||||
|
isempty(labs) && return 0mm
|
||||||
ptsz = axis[:tickfont].pointsize * pt
|
ptsz = axis[:tickfont].pointsize * pt
|
||||||
|
|
||||||
# we need to compute the size of the ticks generically
|
# we need to compute the size of the ticks generically
|
||||||
|
|||||||
@ -99,11 +99,7 @@ end
|
|||||||
const _glplot_deletes = []
|
const _glplot_deletes = []
|
||||||
function empty_screen!(screen)
|
function empty_screen!(screen)
|
||||||
if isempty(_glplot_deletes)
|
if isempty(_glplot_deletes)
|
||||||
screen.renderlist = ()
|
empty!(screen)
|
||||||
for c in screen.children
|
|
||||||
empty!(c)
|
|
||||||
end
|
|
||||||
empty!(screen.children)
|
|
||||||
else
|
else
|
||||||
for del_signal in _glplot_deletes
|
for del_signal in _glplot_deletes
|
||||||
push!(del_signal, true) # trigger delete
|
push!(del_signal, true) # trigger delete
|
||||||
@ -112,19 +108,19 @@ function empty_screen!(screen)
|
|||||||
end
|
end
|
||||||
nothing
|
nothing
|
||||||
end
|
end
|
||||||
function _create_backend_figure(plt::Plot{GLVisualizeBackend})
|
function create_window(plt::Plot{GLVisualizeBackend}, visible)
|
||||||
# init a screen
|
# init a screen
|
||||||
if isempty(GLVisualize.get_screens())
|
if isempty(GLVisualize.get_screens())
|
||||||
s = GLVisualize.glscreen()
|
screen = GLVisualize.glscreen(resolution = plt[:size], visible = visible)
|
||||||
Reactive.stop()
|
Reactive.stop()
|
||||||
@async begin
|
@async begin
|
||||||
while isopen(s)
|
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()
|
Reactive.run_till_now()
|
||||||
GLWindow.render_frame(s)
|
GLWindow.render_frame(screen)
|
||||||
GLWindow.swapbuffers(s)
|
GLWindow.swapbuffers(screen)
|
||||||
end
|
end
|
||||||
yield()
|
yield()
|
||||||
diff = (1/60) - toq()
|
diff = (1/60) - toq()
|
||||||
@ -134,14 +130,16 @@ function _create_backend_figure(plt::Plot{GLVisualizeBackend})
|
|||||||
diff -= toq()
|
diff -= toq()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
GLWindow.destroy!(s)
|
GLWindow.destroy!(screen)
|
||||||
GLVisualize.cleanup_old_screens()
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
s = GLVisualize.current_screen()
|
screen = GLVisualize.current_screen()
|
||||||
empty_screen!(s)
|
empty_screen!(screen)
|
||||||
end
|
end
|
||||||
s
|
plt.o = screen
|
||||||
|
GLWindow.set_visibility!(screen, visible)
|
||||||
|
resize!(screen, plt[:size]...)
|
||||||
|
screen
|
||||||
end
|
end
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -165,24 +163,23 @@ const _gl_marker_map = KW(
|
|||||||
:x => 'x',
|
:x => 'x',
|
||||||
)
|
)
|
||||||
|
|
||||||
function gl_marker(shape, size)
|
function gl_marker(shape)
|
||||||
shape
|
shape
|
||||||
end
|
end
|
||||||
function gl_marker(shape::Shape, size::FixedSizeArrays.Vec{2,Float32})
|
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)*10f0 for p in zip(shape.x, shape.y)]
|
||||||
GeometryTypes.GLNormalMesh(points)
|
GeometryTypes.GLNormalMesh(points)
|
||||||
end
|
end
|
||||||
# create a marker/shape type
|
# create a marker/shape type
|
||||||
function gl_marker(shape::Symbol, msize)
|
function gl_marker(shape::Symbol)
|
||||||
isa(msize, Array) && (msize = first(msize)) # size doesn't really matter now
|
|
||||||
if shape == :rect
|
if shape == :rect
|
||||||
GeometryTypes.HyperRectangle(Vec{2, Float32}(0), msize)
|
GeometryTypes.HyperRectangle(Vec2f0(0), Vec2f0(1))
|
||||||
elseif shape == :circle || shape == :none
|
elseif shape == :circle || shape == :none
|
||||||
GeometryTypes.HyperSphere(Point{2, Float32}(0), maximum(msize))
|
GeometryTypes.HyperSphere(Point2f0(0), 1f0)
|
||||||
elseif haskey(_gl_marker_map, shape)
|
elseif haskey(_gl_marker_map, shape)
|
||||||
_gl_marker_map[shape]
|
_gl_marker_map[shape]
|
||||||
elseif haskey(_shapes, shape)
|
elseif haskey(_shapes, shape)
|
||||||
gl_marker(_shapes[shape], msize)
|
gl_marker(_shapes[shape])
|
||||||
else
|
else
|
||||||
error("Shape $shape not supported by GLVisualize")
|
error("Shape $shape not supported by GLVisualize")
|
||||||
end
|
end
|
||||||
@ -201,6 +198,14 @@ end
|
|||||||
function extract_marker(d, kw_args)
|
function extract_marker(d, kw_args)
|
||||||
dim = Plots.is3d(d) ? 3 : 2
|
dim = Plots.is3d(d) ? 3 : 2
|
||||||
scaling = dim == 3 ? 0.003 : 2
|
scaling = dim == 3 ? 0.003 : 2
|
||||||
|
if haskey(d, :markershape)
|
||||||
|
shape = d[:markershape]
|
||||||
|
shape = gl_marker(shape)
|
||||||
|
if shape != :none
|
||||||
|
kw_args[:primitive] = shape
|
||||||
|
end
|
||||||
|
end
|
||||||
|
dim = isa(kw_args[:primitive], GLVisualize.Sprites) ? 2 : 3
|
||||||
if haskey(d, :markersize)
|
if haskey(d, :markersize)
|
||||||
msize = d[:markersize]
|
msize = d[:markersize]
|
||||||
if isa(msize, AbstractArray)
|
if isa(msize, AbstractArray)
|
||||||
@ -209,13 +214,7 @@ function extract_marker(d, kw_args)
|
|||||||
kw_args[:scale] = GeometryTypes.Vec{dim, Float32}(msize*scaling)
|
kw_args[:scale] = GeometryTypes.Vec{dim, Float32}(msize*scaling)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if haskey(d, :markershape)
|
|
||||||
shape = d[:markershape]
|
|
||||||
shape = gl_marker(shape, kw_args[:scale])
|
|
||||||
if shape != :none
|
|
||||||
kw_args[:primitive] = shape
|
|
||||||
end
|
|
||||||
end
|
|
||||||
# get the color
|
# get the color
|
||||||
key = :markercolor
|
key = :markercolor
|
||||||
haskey(d, key) || return
|
haskey(d, key) || return
|
||||||
@ -412,13 +411,11 @@ function hover(to_hover, to_display, window)
|
|||||||
area = map(window.inputs[:mouseposition]) do mp
|
area = map(window.inputs[:mouseposition]) do mp
|
||||||
SimpleRectangle{Int}(round(Int, mp+10)..., 100, 70)
|
SimpleRectangle{Int}(round(Int, mp+10)..., 100, 70)
|
||||||
end
|
end
|
||||||
background = visualize((GLVisualize.ROUNDED_RECTANGLE, Point2f0[0]),
|
|
||||||
color=RGBA{Float32}(0,0,0,0), scale=Vec2f0(100, 70), offset=Vec2f0(0),
|
|
||||||
stroke_color=RGBA{Float32}(0,0,0,0.4),
|
|
||||||
stroke_width=-1.0f0
|
|
||||||
)
|
|
||||||
mh = GLWindow.mouse2id(window)
|
mh = GLWindow.mouse2id(window)
|
||||||
popup = GLWindow.Screen(window, area=area, hidden=true)
|
popup = GLWindow.Screen(
|
||||||
|
window, hidden=true, area=area,
|
||||||
|
stroke=(2f0/100f0, 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),
|
||||||
@ -444,7 +441,6 @@ function hover(to_hover, to_display, window)
|
|||||||
cam.projectiontype.value = GLVisualize.ORTHOGRAPHIC
|
cam.projectiontype.value = GLVisualize.ORTHOGRAPHIC
|
||||||
end
|
end
|
||||||
GLVisualize._view(robj, popup, camera=cam)
|
GLVisualize._view(robj, popup, camera=cam)
|
||||||
GLVisualize._view(background, popup, camera=:fixed_pixel)
|
|
||||||
bb = GLAbstraction.boundingbox(robj).value
|
bb = GLAbstraction.boundingbox(robj).value
|
||||||
mini = minimum(bb)
|
mini = minimum(bb)
|
||||||
w = GeometryTypes.widths(bb)
|
w = GeometryTypes.widths(bb)
|
||||||
@ -465,7 +461,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*1.5 ./ GLVisualize.glyph_scale!('X')
|
kw_args[:relative_scale] = font.pointsize ./ GLVisualize.glyph_scale!('X')
|
||||||
kw_args[:color] = gl_color(font.color)
|
kw_args[:color] = gl_color(font.color)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -505,7 +501,11 @@ function extract_c(d, kw_args, sym)
|
|||||||
kw_args[:color] = nothing
|
kw_args[:color] = nothing
|
||||||
kw_args[:color_map] = nothing
|
kw_args[:color_map] = nothing
|
||||||
kw_args[:color_norm] = nothing
|
kw_args[:color_norm] = nothing
|
||||||
if isa(c, AbstractVector)
|
if (
|
||||||
|
isa(c, AbstractVector) &&
|
||||||
|
((haskey(d, :marker_z) && d[:marker_z] != nothing) ||
|
||||||
|
(haskey(d, :line_z) && d[:line_z] != nothing))
|
||||||
|
)
|
||||||
extract_colornorm(d, kw_args)
|
extract_colornorm(d, kw_args)
|
||||||
kw_args[:color_map] = c
|
kw_args[:color_map] = c
|
||||||
else
|
else
|
||||||
@ -572,12 +572,12 @@ end
|
|||||||
|
|
||||||
function draw_ticks(axis, ticks, align, move, isx, lims, model, text = "", positions = Point2f0[], offsets=Vec2f0[])
|
function draw_ticks(axis, ticks, align, move, isx, lims, model, text = "", positions = Point2f0[], offsets=Vec2f0[])
|
||||||
sz = axis[:tickfont].pointsize
|
sz = axis[:tickfont].pointsize
|
||||||
rscale2 = Vec2f0(3/sz)
|
rscale2 = Vec2f0(2.5/sz)
|
||||||
m = Reactive.value(model)
|
m = Reactive.value(model)
|
||||||
xs, ys = m[1,1], m[2,2]
|
xs, ys = m[1,1], m[2,2]
|
||||||
rscale = rscale2 ./ Vec2f0(xs, ys)
|
rscale = rscale2 ./ Vec2f0(xs, ys)
|
||||||
atlas = GLVisualize.get_texture_atlas()
|
atlas = GLVisualize.get_texture_atlas()
|
||||||
font = GLVisualize.DEFAULT_FONT_FACE
|
font = GLVisualize.defaultfont()
|
||||||
if !(ticks in (nothing, false))
|
if !(ticks in (nothing, false))
|
||||||
# x labels
|
# x labels
|
||||||
flip = axis[:flip]
|
flip = axis[:flip]
|
||||||
@ -603,7 +603,7 @@ function text(position, text, kw_args)
|
|||||||
text_align = alignment2num(text.font)
|
text_align = alignment2num(text.font)
|
||||||
startpos = Vec2f0(position)
|
startpos = Vec2f0(position)
|
||||||
atlas = GLVisualize.get_texture_atlas()
|
atlas = GLVisualize.get_texture_atlas()
|
||||||
font = GLVisualize.DEFAULT_FONT_FACE
|
font = GLVisualize.defaultfont()
|
||||||
rscale = kw_args[:relative_scale]
|
rscale = kw_args[:relative_scale]
|
||||||
m = Reactive.value(kw_args[:model])
|
m = Reactive.value(kw_args[:model])
|
||||||
position = GLVisualize.calc_position(text.str, startpos, rscale, font, atlas)
|
position = GLVisualize.calc_position(text.str, startpos, rscale, font, atlas)
|
||||||
@ -656,7 +656,7 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
|
|||||||
:position => positions,
|
:position => positions,
|
||||||
:offset => offsets,
|
:offset => offsets,
|
||||||
:color => fcolor,
|
:color => fcolor,
|
||||||
:relative_scale => Vec2f0(3/sz),
|
:relative_scale => Vec2f0(2.5/sz),
|
||||||
:model => model,
|
:model => model,
|
||||||
:scale_primitive => false
|
:scale_primitive => false
|
||||||
)
|
)
|
||||||
@ -854,8 +854,8 @@ function gl_viewport(bb, rect)
|
|||||||
l, b, bw, bh = bb
|
l, b, bw, bh = bb
|
||||||
rw, rh = rect.w, rect.h
|
rw, rh = rect.w, rect.h
|
||||||
GLVisualize.SimpleRectangle(
|
GLVisualize.SimpleRectangle(
|
||||||
round(Int, rect.x + rw * l),
|
round(Int, rw * l),
|
||||||
round(Int, rect.y + rh * b),
|
round(Int, rh * b),
|
||||||
round(Int, rw * bw),
|
round(Int, rw * bw),
|
||||||
round(Int, rh * bh)
|
round(Int, rh * bh)
|
||||||
)
|
)
|
||||||
@ -881,27 +881,26 @@ end
|
|||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
function _display(plt::Plot{GLVisualizeBackend})
|
function _display(plt::Plot{GLVisualizeBackend}, visible=true)
|
||||||
screen = plt.o
|
screen = create_window(plt, visible)
|
||||||
empty_screen!(screen)
|
|
||||||
sw, sh = plt[:size]
|
sw, sh = plt[:size]
|
||||||
sw, sh = sw*px, sh*px
|
sw, sh = sw*px, sh*px
|
||||||
|
|
||||||
# TODO: use plt.subplots... plt.spmap can't be trusted
|
# TODO: use plt.subplots... plt.spmap can't be trusted
|
||||||
for (name, sp) in plt.spmap
|
for sp in plt.subplots
|
||||||
_3d = Plots.is3d(sp)
|
_3d = Plots.is3d(sp)
|
||||||
# camera = :perspective
|
# camera = :perspective
|
||||||
# initialize the sub-screen for this subplot
|
# initialize the sub-screen for this subplot
|
||||||
# note: we create a lift function to update the size on resize
|
|
||||||
|
|
||||||
rel_bbox = Plots.bbox_to_pcts(bbox(sp), sw, sh)
|
rel_bbox = Plots.bbox_to_pcts(bbox(sp), sw, sh)
|
||||||
sub_area = map(screen.area) do rect
|
sub_area = map(screen.area) do rect
|
||||||
Plots.gl_viewport(rel_bbox, rect)
|
Plots.gl_viewport(rel_bbox, rect)
|
||||||
end
|
end
|
||||||
c = plt[:background_color_outside]
|
c = plt[:background_color_outside]
|
||||||
sp_screen = GLVisualize.Screen(
|
sp_screen = GLVisualize.Screen(
|
||||||
screen, name = name, color = c,
|
screen, color = c,
|
||||||
area = sub_area
|
area = sub_area
|
||||||
)
|
)
|
||||||
|
sp.o = sp_screen
|
||||||
cam = get!(sp_screen.cameras, :perspective) do
|
cam = get!(sp_screen.cameras, :perspective) do
|
||||||
inside = sp_screen.inputs[:mouseinside]
|
inside = sp_screen.inputs[:mouseinside]
|
||||||
theta = _3d ? nothing : Signal(Vec3f0(0)) # surpress rotation for 2D (nothing will get usual rotation controle)
|
theta = _3d ? nothing : Signal(Vec3f0(0)) # surpress rotation for 2D (nothing will get usual rotation controle)
|
||||||
@ -911,7 +910,6 @@ function _display(plt::Plot{GLVisualizeBackend})
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
sp.o = sp_screen
|
|
||||||
rel_plotarea = Plots.bbox_to_pcts(plotarea(sp), sw, sh)
|
rel_plotarea = Plots.bbox_to_pcts(plotarea(sp), sw, sh)
|
||||||
model_m = map(Plots.to_modelmatrix, screen.area, sub_area, Signal(rel_plotarea), Signal(sp))
|
model_m = map(Plots.to_modelmatrix, screen.area, sub_area, Signal(rel_plotarea), Signal(sp))
|
||||||
for ann in sp[:annotations]
|
for ann in sp[:annotations]
|
||||||
@ -920,12 +918,12 @@ function _display(plt::Plot{GLVisualizeBackend})
|
|||||||
x, y, _1, _1 = Reactive.value(model_m) * Vec{4,Float32}(x, y, 0, 1)
|
x, y, _1, _1 = Reactive.value(model_m) * Vec{4,Float32}(x, y, 0, 1)
|
||||||
extract_font(plot_text.font, txt_args)
|
extract_font(plot_text.font, txt_args)
|
||||||
t = text(Point2f0(x, y), plot_text, txt_args)
|
t = text(Point2f0(x, y), plot_text, txt_args)
|
||||||
GLVisualize._view(t, sp_screen, camera=cam)
|
GLVisualize._view(t, sp_screen, camera=:perspective)
|
||||||
end
|
end
|
||||||
# loop over the series and add them to the subplot
|
# loop over the series and add them to the subplot
|
||||||
if !_3d
|
if !_3d
|
||||||
axis = gl_draw_axes_2d(sp, model_m, Reactive.value(sub_area))
|
axis = gl_draw_axes_2d(sp, model_m, Reactive.value(sub_area))
|
||||||
GLVisualize._view(axis, sp_screen, camera=cam)
|
GLVisualize._view(axis, sp_screen, camera=:perspective)
|
||||||
cam.projectiontype.value = GLVisualize.ORTHOGRAPHIC
|
cam.projectiontype.value = GLVisualize.ORTHOGRAPHIC
|
||||||
Reactive.run_till_now() # make sure Reactive.push! arrives
|
Reactive.run_till_now() # make sure Reactive.push! arrives
|
||||||
GLAbstraction.center!(cam,
|
GLAbstraction.center!(cam,
|
||||||
@ -935,12 +933,14 @@ function _display(plt::Plot{GLVisualizeBackend})
|
|||||||
)
|
)
|
||||||
else
|
else
|
||||||
axis = gl_draw_axes_3d(sp, model_m)
|
axis = gl_draw_axes_3d(sp, model_m)
|
||||||
GLVisualize._view(axis, sp_screen, camera=cam)
|
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
|
||||||
|
|
||||||
kw_args[:model] = model_m # add transformation
|
kw_args[:model] = model_m # add transformation
|
||||||
if !_3d # 3D is treated differently, since we need boundingboxes for camera
|
if !_3d # 3D is treated differently, since we need boundingboxes for camera
|
||||||
kw_args[:boundingbox] = nothing # don't calculate bb, we dont need it
|
kw_args[:boundingbox] = nothing # don't calculate bb, we dont need it
|
||||||
@ -1026,18 +1026,18 @@ function _display(plt::Plot{GLVisualizeBackend})
|
|||||||
else
|
else
|
||||||
error("failed to display plot type $st")
|
error("failed to display plot type $st")
|
||||||
end
|
end
|
||||||
if isa(vis, Array) && isempty(vis)
|
isa(vis, Array) && isempty(vis) && continue # nothing to see here
|
||||||
continue # nothing to see here
|
|
||||||
end
|
GLVisualize._view(vis, sp_screen, camera=:perspective)
|
||||||
GLVisualize._view(vis, sp_screen, camera=cam)
|
|
||||||
if haskey(d, :hover) && !(d[:hover] in (false, :none, nothing))
|
if haskey(d, :hover) && !(d[:hover] in (false, :none, nothing))
|
||||||
hover(vis, d[:hover], sp_screen)
|
hover(vis, d[:hover], sp_screen)
|
||||||
end
|
end
|
||||||
if isdefined(:GLPlot) && isdefined(Main.GLPlot, :(register_plot!))
|
if isdefined(:GLPlot) && isdefined(Main.GLPlot, :(register_plot!))
|
||||||
del_signal = Main.GLPlot.register_plot!(vis, sp_screen)
|
del_signal = Main.GLPlot.register_plot!(vis, sp_screen, create_gizmo=false)
|
||||||
append!(_glplot_deletes, del_signal)
|
append!(_glplot_deletes, del_signal)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
generate_legend(sp, sp_screen, model_m)
|
||||||
if _3d
|
if _3d
|
||||||
GLAbstraction.center!(sp_screen)
|
GLAbstraction.center!(sp_screen)
|
||||||
end
|
end
|
||||||
@ -1047,16 +1047,16 @@ function _display(plt::Plot{GLVisualizeBackend})
|
|||||||
end
|
end
|
||||||
|
|
||||||
function _show(io::IO, ::MIME"image/png", plt::Plot{GLVisualizeBackend})
|
function _show(io::IO, ::MIME"image/png", plt::Plot{GLVisualizeBackend})
|
||||||
_display(plt)
|
_display(plt, false)
|
||||||
GLWindow.pollevents()
|
GLWindow.pollevents()
|
||||||
yield()
|
|
||||||
if Base.n_avail(Reactive._messages) > 0
|
if Base.n_avail(Reactive._messages) > 0
|
||||||
Reactive.run_till_now()
|
Reactive.run_till_now()
|
||||||
end
|
end
|
||||||
GLWindow.render_frame(plt.o)
|
yield()
|
||||||
|
GLWindow.render_frame(GLWindow.rootscreen(plt.o))
|
||||||
GLWindow.swapbuffers(plt.o)
|
GLWindow.swapbuffers(plt.o)
|
||||||
buff = GLWindow.screenbuffer(plt.o)
|
buff = GLWindow.screenbuffer(plt.o)
|
||||||
png = Images.Image(buff,
|
png = Images.Image(map(RGB{U8}, buff),
|
||||||
colorspace = "sRGB",
|
colorspace = "sRGB",
|
||||||
spatialorder = ["y", "x"]
|
spatialorder = ["y", "x"]
|
||||||
)
|
)
|
||||||
@ -1106,6 +1106,7 @@ function gl_lines(points, kw_args)
|
|||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
function gl_shape(d, kw_args)
|
function gl_shape(d, kw_args)
|
||||||
points = Plots.extract_points(d)
|
points = Plots.extract_points(d)
|
||||||
result = []
|
result = []
|
||||||
@ -1116,17 +1117,27 @@ function gl_shape(d, kw_args)
|
|||||||
end
|
end
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
tovec2(x::FixedSizeArrays.Vec{2, Float32}) = x
|
tovec2(x::FixedSizeArrays.Vec{2, Float32}) = x
|
||||||
tovec2(x::AbstractVector) = map(tovec2, x)
|
tovec2(x::AbstractVector) = map(tovec2, x)
|
||||||
tovec2(x::FixedSizeArrays.Vec) = Vec2f0(x[1], x[2])
|
tovec2(x::FixedSizeArrays.Vec) = Vec2f0(x[1], x[2])
|
||||||
|
|
||||||
|
tovec3(x) = x
|
||||||
|
tovec3(x::FixedSizeArrays.Vec{3}) = Vec3f0(x)
|
||||||
|
tovec3(x::AbstractVector) = map(tovec3, x)
|
||||||
|
tovec3(x::FixedSizeArrays.Vec{2}) = Vec3f0(x[1], x[2], 1)
|
||||||
|
|
||||||
function gl_scatter(points, kw_args)
|
function gl_scatter(points, kw_args)
|
||||||
prim = get(kw_args, :primitive, GeometryTypes.Circle)
|
prim = get(kw_args, :primitive, GeometryTypes.Circle)
|
||||||
if isa(prim, GLNormalMesh)
|
if isa(prim, GLNormalMesh)
|
||||||
kw_args[:scale] = map(kw_args[:model]) do m
|
if haskey(kw_args, :model)
|
||||||
s = m[1,1], m[2,2], m[3,3]
|
p = get(kw_args, :perspective, eye(GeometryTypes.Mat4f0))
|
||||||
1f0./Vec3f0(s)
|
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])
|
||||||
|
ps = Vec3f0(p[1,1], p[2,2], p[3,3])
|
||||||
|
r = 1f0./(s.*ps)
|
||||||
|
r
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else # 2D prim
|
else # 2D prim
|
||||||
kw_args[:scale] = tovec2(kw_args[:scale])
|
kw_args[:scale] = tovec2(kw_args[:scale])
|
||||||
@ -1218,6 +1229,7 @@ function gl_contour(x,y,z, kw_args)
|
|||||||
kw_args[:color] = colors
|
kw_args[:color] = colors
|
||||||
kw_args[:color_map] = nothing
|
kw_args[:color_map] = nothing
|
||||||
kw_args[:color_norm] = nothing
|
kw_args[:color_norm] = nothing
|
||||||
|
kw_args[:intensity] = nothing
|
||||||
return visualize(result, Style(:lines),kw_args)
|
return visualize(result, Style(:lines),kw_args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1238,20 +1250,119 @@ end
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
function text_plot(text, alignment, kw_args)
|
"""
|
||||||
transmat = kw_args[:model]
|
Ugh, so much special casing (╯°□°)╯︵ ┻━┻
|
||||||
obj = visualize(text, Style(:default), kw_args)
|
"""
|
||||||
bb = value(GLAbstraction.boundingbox(obj))
|
function label_scatter(d, w, ho)
|
||||||
w,h,_ = widths(bb)
|
kw = KW()
|
||||||
x,y,_ = minimum(bb)
|
extract_stroke(d, kw)
|
||||||
pivot = origin(alignment)
|
extract_marker(d, kw)
|
||||||
pos = pivot - (Point2f0(x, y) .* widths(alignment))
|
kw[:scale] = Vec2f0(w/2)
|
||||||
if kw_args[:rotation] != 0.0
|
kw[:offset] = Vec2f0(-w/4)
|
||||||
rot = GLAbstraction.rotationmatrix_z(Float32(font.rotation))
|
if haskey(kw, :intensity)
|
||||||
transmat *= translationmatrix(pivot)*rot*translationmatrix(-pivot)
|
cmap = kw[:color_map]
|
||||||
|
norm = kw[:color_norm]
|
||||||
|
kw[:color] = GLVisualize.color_lookup(cmap, kw[:intensity][1], norm)
|
||||||
|
delete!(kw, :intensity)
|
||||||
|
delete!(kw, :color_map)
|
||||||
|
delete!(kw, :color_norm)
|
||||||
|
else
|
||||||
|
color = get(kw, :color, nothing)
|
||||||
|
kw[:color] = isa(color, Array) ? first(color) : color
|
||||||
|
end
|
||||||
|
p = get(kw, :primitive, GeometryTypes.Circle)
|
||||||
|
if isa(p, GLNormalMesh)
|
||||||
|
bb = GeometryTypes.AABB{Float32}(GeometryTypes.vertices(p))
|
||||||
|
bbw = GeometryTypes.widths(bb)
|
||||||
|
mini = minimum(bb)
|
||||||
|
m = GLAbstraction.translationmatrix(-mini)
|
||||||
|
m *= GLAbstraction.scalematrix(1f0./bbw)
|
||||||
|
kw[:primitive] = m * p
|
||||||
|
kw[:scale] = Vec3f0(w/2)
|
||||||
|
delete!(kw, :offset)
|
||||||
|
end
|
||||||
|
GL.gl_scatter(Point2f0[(w/2, ho)], kw)
|
||||||
end
|
end
|
||||||
|
|
||||||
transmat *= GLAbstraction.translationmatrix(Vec3f0(pos..., 0))
|
|
||||||
GLAbstraction.transformation(obj, transmat)
|
function make_label(sp, series, i)
|
||||||
view(obj, img.screen, camera=:orthographic_pixel)
|
GL = Plots
|
||||||
|
w, gap, ho = 20f0, 5f0, 5
|
||||||
|
result = []
|
||||||
|
d = series.d
|
||||||
|
st = d[:seriestype]
|
||||||
|
kw_args = KW()
|
||||||
|
if (st in (:path, :path3d)) && d[:linewidth] > 0
|
||||||
|
points = Point2f0[(0, ho), (w, ho)]
|
||||||
|
kw = KW()
|
||||||
|
extract_linestyle(d, kw)
|
||||||
|
kw[:thickness] = 15f0
|
||||||
|
append!(result, GL.gl_lines(points, kw))
|
||||||
|
if d[:markershape] != :none
|
||||||
|
push!(result, label_scatter(d, w, ho))
|
||||||
|
end
|
||||||
|
elseif st in (:scatter, :scatter3d) #|| d[:markershape] != :none
|
||||||
|
push!(result, label_scatter(d, w, ho))
|
||||||
|
else
|
||||||
|
extract_c(d, kw_args, :fill)
|
||||||
|
if isa(kw_args[:color], AbstractVector)
|
||||||
|
kw_args[:color] = first(kw_args[:color])
|
||||||
|
end
|
||||||
|
push!(result, visualize(
|
||||||
|
GeometryTypes.SimpleRectangle(-w/2, ho-w/4, w/2, w/2),
|
||||||
|
Style(:default), kw_args
|
||||||
|
))
|
||||||
|
end
|
||||||
|
labeltext = if isa(series[:label], Array)
|
||||||
|
i += 1
|
||||||
|
series[:label][i]
|
||||||
|
else
|
||||||
|
series[:label]
|
||||||
|
end
|
||||||
|
color = sp[:foreground_color_legend]
|
||||||
|
ft = sp[:legendfont]
|
||||||
|
font = Plots.Font(ft.family, ft.pointsize, :left, :bottom, 0.0, color)
|
||||||
|
xy = Point2f0(w+gap, 0.0)
|
||||||
|
kw = Dict(:model => text_model(font, xy), :scale_primitive=>false)
|
||||||
|
extract_font(font, kw)
|
||||||
|
t = PlotText(labeltext, font)
|
||||||
|
push!(result, text(xy, t, kw))
|
||||||
|
GLAbstraction.Context(result...), i
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function generate_legend(sp, screen, model_m)
|
||||||
|
legend = GLAbstraction.Context[]
|
||||||
|
if sp[:legend] != :none
|
||||||
|
i = 0
|
||||||
|
for series in series_list(sp)
|
||||||
|
should_add_to_legend(series) || continue
|
||||||
|
result, i = make_label(sp, series, i)
|
||||||
|
push!(legend, result)
|
||||||
|
end
|
||||||
|
if isempty(legend)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
list = visualize(legend, gap=Vec3f0(0,5,0))
|
||||||
|
bb = GLAbstraction._boundingbox(list)
|
||||||
|
wx,wy,_ = GeometryTypes.widths(bb)
|
||||||
|
xmin, _ = Plots.axis_limits(sp[:xaxis])
|
||||||
|
_, ymax = Plots.axis_limits(sp[:yaxis])
|
||||||
|
area = map(model_m) do m
|
||||||
|
p = m * GeometryTypes.Vec4f0(xmin, ymax, 0, 1)
|
||||||
|
h = round(Int, wy)+20
|
||||||
|
w = round(Int, wx)+20
|
||||||
|
x,y = round(Int, p[1])+30, round(Int, p[2]-h)-30
|
||||||
|
GeometryTypes.SimpleRectangle(x, y, w, h)
|
||||||
|
end
|
||||||
|
px_scale = minimum(GeometryTypes.widths(Reactive.value(area)))
|
||||||
|
sscren = GLWindow.Screen(
|
||||||
|
screen, area=area,
|
||||||
|
color=sp[:background_color_legend],
|
||||||
|
stroke=(2f0/px_scale, RGBA{Float32}(0.3,0.3,0.3,0.9))
|
||||||
|
)
|
||||||
|
GLAbstraction.translate!(list, Vec3f0(10,10,0))
|
||||||
|
GLVisualize._view(list, sscren, camera=:fixed_pixel)
|
||||||
|
end
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|||||||
@ -714,28 +714,28 @@ Base.push!(series::Series, xi, yi, zi) = (push_x!(series,xi); push_y!(series,yi)
|
|||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
|
|
||||||
function update!(series::Series; kw...)
|
function attr!(series::Series; kw...)
|
||||||
d = KW(kw)
|
d = KW(kw)
|
||||||
preprocessArgs!(d)
|
preprocessArgs!(d)
|
||||||
for (k,v) in d
|
for (k,v) in d
|
||||||
if haskey(_series_defaults, k)
|
if haskey(_series_defaults, k)
|
||||||
series[k] = v
|
series[k] = v
|
||||||
else
|
else
|
||||||
warn("unused key $k in series update")
|
warn("unused key $k in series attr")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
_series_updated(series[:subplot].plt, series)
|
_series_updated(series[:subplot].plt, series)
|
||||||
series
|
series
|
||||||
end
|
end
|
||||||
|
|
||||||
function update!(sp::Subplot; kw...)
|
function attr!(sp::Subplot; kw...)
|
||||||
d = KW(kw)
|
d = KW(kw)
|
||||||
preprocessArgs!(d)
|
preprocessArgs!(d)
|
||||||
for (k,v) in d
|
for (k,v) in d
|
||||||
if haskey(_subplot_defaults, k)
|
if haskey(_subplot_defaults, k)
|
||||||
sp[k] = v
|
sp[k] = v
|
||||||
else
|
else
|
||||||
warn("unused key $k in subplot update")
|
warn("unused key $k in subplot attr")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
sp
|
sp
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user