From 874e94218c632e92a8608f98f19ee279544e8b7f Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 23 Sep 2016 12:42:38 +0200 Subject: [PATCH 1/6] add labels --- src/backends/glvisualize.jl | 112 ++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index a3e6f9f6..0003dd6e 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -949,6 +949,7 @@ function _display(plt::Plot{GLVisualizeBackend}) GLVisualize._view(axis, sp_screen, camera=cam) push!(cam.projectiontype, GLVisualize.PERSPECTIVE) end + for series in Plots.series_list(sp) d = series.d st = d[:seriestype]; kw_args = KW() # exctract kw @@ -1049,6 +1050,8 @@ function _display(plt::Plot{GLVisualizeBackend}) append!(_glplot_deletes, del_signal) end end + #@show model_m + generate_legend(sp, sp_screen, model_m) if _3d GLAbstraction.center!(sp_screen) end @@ -1266,3 +1269,112 @@ function text_plot(text, alignment, kw_args) GLAbstraction.transformation(obj, transmat) view(obj, img.screen, camera=:orthographic_pixel) end + + + +function make_label(sp, series, i) + 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 + kw = KW() + extract_stroke(d, kw) + extract_marker(d, kw) + kw[:scale] = Vec2f0(w/2) + kw[:offset] = Vec2f0(-w/4) + if haskey(kw, :intensity) + 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 + push!(result, GL.gl_scatter(Point2f0[(w/2, ho)], kw)) + end + elseif st in (:scatter, :scatter3d) #|| d[:markershape] != :none + kw = KW() + extract_stroke(d, kw) + extract_marker(d, kw) + kw[:scale] = Vec2f0(w/2) + kw[:offset] = Vec2f0(-w/4) + if haskey(kw, :intensity) + 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 + push!(result, GL.gl_scatter(Point2f0[(w/2, ho)], kw)) + else + extract_c(d, kw_args, :fill) + 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=>true) + 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) + bb = Reactive.value(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 + @show m + p = m * GeometryTypes.Vec4f0(xmin, ymax, 0, 1) + + w = round(Int, 2*wy) + x,y = round(Int, p[1]) + 20, round(Int, p[2]-w)-40 + GeometryTypes.SimpleRectangle(x, y, round(Int, wx)+20, w+20) + end + sscren = GLWindow.Screen(screen, area=area) + GLAbstraction._translate!(list, Vec3f0(10,10,0)) + GLVisualize._view(list, sscren, camera=:fixed_pixel) + end + return +end From 456602b79f23a7ef3269126f082dbe0dea373431 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 14 Oct 2016 00:39:54 +0200 Subject: [PATCH 2/6] various fixes --- src/backends/glvisualize.jl | 162 ++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 72 deletions(-) diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index dc807d7b..f3b01dbd 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -178,24 +178,23 @@ const _gl_marker_map = KW( :x => 'x', ) -function gl_marker(shape, size) +function gl_marker(shape) shape 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)] GeometryTypes.GLNormalMesh(points) end # create a marker/shape type -function gl_marker(shape::Symbol, msize) - isa(msize, Array) && (msize = first(msize)) # size doesn't really matter now +function gl_marker(shape::Symbol) if shape == :rect - GeometryTypes.HyperRectangle(Vec{2, Float32}(0), msize) + GeometryTypes.HyperRectangle(Vec2f0(0), Vec2f0(1)) elseif shape == :circle || shape == :none - GeometryTypes.HyperSphere(Point{2, Float32}(0), maximum(msize)) + GeometryTypes.HyperSphere(Point2f0(0), 1f0) elseif haskey(_gl_marker_map, shape) _gl_marker_map[shape] elseif haskey(_shapes, shape) - gl_marker(_shapes[shape], msize) + gl_marker(_shapes[shape]) else error("Shape $shape not supported by GLVisualize") end @@ -214,6 +213,14 @@ end function extract_marker(d, kw_args) dim = Plots.is3d(d) ? 3 : 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) msize = d[:markersize] if isa(msize, AbstractArray) @@ -222,13 +229,7 @@ function extract_marker(d, kw_args) kw_args[:scale] = GeometryTypes.Vec{dim, Float32}(msize*scaling) 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 key = :markercolor haskey(d, key) || return @@ -425,7 +426,7 @@ function hover(to_hover, to_display, window) area = map(window.inputs[:mouseposition]) do mp SimpleRectangle{Int}(round(Int, mp+10)..., 100, 70) end - background = visualize((GLVisualize.ROUNDED_RECTANGLE, Point2f0[0]), + background = visualize((GLVisualize.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 @@ -478,7 +479,7 @@ end function extract_font(font, kw_args) 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) end @@ -518,7 +519,11 @@ function extract_c(d, kw_args, sym) kw_args[:color] = nothing kw_args[:color_map] = 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) kw_args[:color_map] = c else @@ -590,7 +595,7 @@ function draw_ticks(axis, ticks, align, move, isx, lims, model, text = "", posit xs, ys = m[1,1], m[2,2] rscale = rscale2 ./ Vec2f0(xs, ys) atlas = GLVisualize.get_texture_atlas() - font = GLVisualize.DEFAULT_FONT_FACE + font = GLVisualize.defaultfont() if !(ticks in (nothing, false)) # x labels flip = axis[:flip] @@ -616,7 +621,7 @@ function text(position, text, kw_args) text_align = alignment2num(text.font) startpos = Vec2f0(position) atlas = GLVisualize.get_texture_atlas() - font = GLVisualize.DEFAULT_FONT_FACE + font = GLVisualize.defaultfont() rscale = kw_args[:relative_scale] m = Reactive.value(kw_args[:model]) position = GLVisualize.calc_position(text.str, startpos, rscale, font, atlas) @@ -899,8 +904,9 @@ function _display(plt::Plot{GLVisualizeBackend}) empty_screen!(screen) sw, sh = plt[:size] sw, sh = sw*px, sh*px + resize!(screen, plt[:size]...) # 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) # camera = :perspective # initialize the sub-screen for this subplot @@ -912,7 +918,7 @@ function _display(plt::Plot{GLVisualizeBackend}) end c = plt[:background_color_outside] sp_screen = GLVisualize.Screen( - screen, name = name, color = c, + screen, color = c, area = sub_area ) cam = get!(sp_screen.cameras, :perspective) do @@ -1048,7 +1054,7 @@ function _display(plt::Plot{GLVisualizeBackend}) hover(vis, d[:hover], sp_screen) end 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) end end @@ -1072,7 +1078,7 @@ function _show(io::IO, ::MIME"image/png", plt::Plot{GLVisualizeBackend}) GLWindow.render_frame(plt.o) GLWindow.swapbuffers(plt.o) buff = GLWindow.screenbuffer(plt.o) - png = Images.Image(buff, + png = Images.Image(map(RGB{U8}, buff), colorspace = "sRGB", spatialorder = ["y", "x"] ) @@ -1136,13 +1142,19 @@ tovec2(x::FixedSizeArrays.Vec{2, Float32}) = x tovec2(x::AbstractVector) = map(tovec2, x) 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) prim = get(kw_args, :primitive, GeometryTypes.Circle) if isa(prim, GLNormalMesh) - kw_args[:scale] = map(kw_args[:model]) do m - s = m[1,1], m[2,2], m[3,3] - 1f0./Vec3f0(s) + if haskey(kw_args, :model) + kw_args[:scale] = GLAbstraction.const_lift(kw_args[:model], kw_args[:scale]) do m, sc + s = m[1,1], m[2,2], m[3,3] + tovec3(sc).*(1f0./Vec3f0(s)) + end end else # 2D prim kw_args[:scale] = tovec2(kw_args[:scale]) @@ -1234,6 +1246,7 @@ function gl_contour(x,y,z, kw_args) kw_args[:color] = colors kw_args[:color_map] = nothing kw_args[:color_norm] = nothing + kw_args[:intensity] = nothing return visualize(result, Style(:lines),kw_args) end end @@ -1272,8 +1285,40 @@ function text_plot(text, alignment, kw_args) view(obj, img.screen, camera=:orthographic_pixel) end - - +""" +Ugh, so much special casing (╯°□°)╯︵ ┻━┻ +""" +function label_scatter(d, w, ho) + kw = KW() + extract_stroke(d, kw) + extract_marker(d, kw) + kw[:scale] = Vec2f0(w/2) + kw[:offset] = Vec2f0(-w/4) + if haskey(kw, :intensity) + 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) + #m *= GLAbstraction.translationmatrix(-Vec3f0(0.5)) + kw[:primitive] = m * p + kw[:scale] = Vec3f0(w/2) + delete!(kw, :offset) + end + GL.gl_scatter(Point2f0[(w/2, ho)], kw) +end function make_label(sp, series, i) GL = Plots w, gap, ho = 20f0, 5f0, 5 @@ -1288,44 +1333,15 @@ function make_label(sp, series, i) kw[:thickness] = 15f0 append!(result, GL.gl_lines(points, kw)) if d[:markershape] != :none - kw = KW() - extract_stroke(d, kw) - extract_marker(d, kw) - kw[:scale] = Vec2f0(w/2) - kw[:offset] = Vec2f0(-w/4) - if haskey(kw, :intensity) - 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 - push!(result, GL.gl_scatter(Point2f0[(w/2, ho)], kw)) + push!(result, label_scatter(d, w, ho)) end elseif st in (:scatter, :scatter3d) #|| d[:markershape] != :none - kw = KW() - extract_stroke(d, kw) - extract_marker(d, kw) - kw[:scale] = Vec2f0(w/2) - kw[:offset] = Vec2f0(-w/4) - if haskey(kw, :intensity) - 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 - push!(result, GL.gl_scatter(Point2f0[(w/2, ho)], kw)) + 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 @@ -1341,7 +1357,7 @@ function make_label(sp, series, i) 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=>true) + kw = Dict(:model => text_model(font, xy), :scale_primitive=>false) extract_font(font, kw) t = PlotText(labeltext, font) push!(result, text(xy, t, kw)) @@ -1361,21 +1377,23 @@ function generate_legend(sp, screen, model_m) if isempty(legend) return end - list = visualize(legend) - bb = Reactive.value(GLAbstraction.boundingbox(list)) + 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 - @show m p = m * GeometryTypes.Vec4f0(xmin, ymax, 0, 1) - - w = round(Int, 2*wy) - x,y = round(Int, p[1]) + 20, round(Int, p[2]-w)-40 - GeometryTypes.SimpleRectangle(x, y, round(Int, wx)+20, w+20) + 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 - sscren = GLWindow.Screen(screen, area=area) - GLAbstraction._translate!(list, Vec3f0(10,10,0)) + sscren = GLWindow.Screen( + screen, area=area, + color=sp[:background_color_legend] + ) + GLAbstraction.translate!(list, Vec3f0(10,10,0)) GLVisualize._view(list, sscren, camera=:fixed_pixel) end return From aa6814a6d310594693678e907538a16c23be8564 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Tue, 18 Oct 2016 20:45:56 -0400 Subject: [PATCH 3/6] rename update! to attr! --- src/Plots.jl | 2 +- src/args.jl | 2 +- src/axes.jl | 4 ++-- src/utils.jl | 8 ++++---- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index b5f09597..60a885cc 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -31,7 +31,7 @@ export plot, plot!, - update!, + attr!, current, default, diff --git a/src/args.jl b/src/args.jl index ea07cbae..490eaddc 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1094,7 +1094,7 @@ function _update_axis(axis::Axis, d_in::KW, letter::Symbol, subplot_index::Int) end # update the axis - update!(axis, args...; kw...) + attr!(axis, args...; kw...) return end diff --git a/src/axes.jl b/src/axes.jl index 9938591d..b9840e7a 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -29,7 +29,7 @@ function Axis(sp::Subplot, letter::Symbol, args...; kw...) d[:discrete_values] = [] # update the defaults - update!(Axis([sp], d), args...; kw...) + attr!(Axis([sp], d), args...; kw...) end function get_axis(sp::Subplot, letter::Symbol) @@ -83,7 +83,7 @@ function process_axis_arg!(d::KW, arg, letter = "") end # update an Axis object with magic args and keywords -function update!(axis::Axis, args...; kw...) +function attr!(axis::Axis, args...; kw...) # first process args d = axis.d for arg in args diff --git a/src/utils.jl b/src/utils.jl index 379a89cc..7483d0a8 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -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) preprocessArgs!(d) for (k,v) in d if haskey(_series_defaults, k) series[k] = v else - warn("unused key $k in series update") + warn("unused key $k in series attr") end end _series_updated(series[:subplot].plt, series) series end -function update!(sp::Subplot; kw...) +function attr!(sp::Subplot; kw...) d = KW(kw) preprocessArgs!(d) for (k,v) in d if haskey(_subplot_defaults, k) sp[k] = v else - warn("unused key $k in subplot update") + warn("unused key $k in subplot attr") end end sp From 3aac2b28955f549b750304e398c2633b4e0cf156 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Tue, 25 Oct 2016 22:33:53 -0400 Subject: [PATCH 4/6] check for empty labs --- src/backends.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backends.jl b/src/backends.jl index 46b23dcb..2118d732 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -58,6 +58,7 @@ function tick_padding(axis::Axis) 0mm else vals, labs = ticks + isempty(labs) && return 0mm ptsz = axis[:tickfont].pointsize * pt # we need to compute the size of the ticks generically From 9bed393210e07a2955c1dcc3d1e30b442b610eca Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 28 Oct 2016 11:39:10 +0200 Subject: [PATCH 5/6] changes for new GLVisualize --- src/backends/glvisualize.jl | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index f3b01dbd..2b29286a 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -112,11 +112,7 @@ end const _glplot_deletes = [] function empty_screen!(screen) if isempty(_glplot_deletes) - screen.renderlist = () - for c in screen.children - empty!(c) - end - empty!(screen.children) + empty!(screen) else for del_signal in _glplot_deletes push!(del_signal, true) # trigger delete @@ -426,13 +422,11 @@ function hover(to_hover, to_display, window) area = map(window.inputs[:mouseposition]) do mp SimpleRectangle{Int}(round(Int, mp+10)..., 100, 70) end - background = visualize((GLVisualize.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) - 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 GLAbstraction.PerspectiveCamera( popup.inputs, Vec3f0(3), Vec3f0(0), @@ -458,7 +452,6 @@ function hover(to_hover, to_display, window) cam.projectiontype.value = GLVisualize.ORTHOGRAPHIC end GLVisualize._view(robj, popup, camera=cam) - GLVisualize._view(background, popup, camera=:fixed_pixel) bb = GLAbstraction.boundingbox(robj).value mini = minimum(bb) w = GeometryTypes.widths(bb) @@ -872,8 +865,8 @@ function gl_viewport(bb, rect) l, b, bw, bh = bb rw, rh = rect.w, rect.h GLVisualize.SimpleRectangle( - round(Int, rect.x + rw * l), - round(Int, rect.y + rh * b), + round(Int, rw * l), + round(Int, rh * b), round(Int, rw * bw), round(Int, rh * bh) ) @@ -1071,10 +1064,10 @@ end function _show(io::IO, ::MIME"image/png", plt::Plot{GLVisualizeBackend}) _display(plt) GLWindow.pollevents() - yield() if Base.n_avail(Reactive._messages) > 0 Reactive.run_till_now() end + yield() GLWindow.render_frame(plt.o) GLWindow.swapbuffers(plt.o) buff = GLWindow.screenbuffer(plt.o) @@ -1389,9 +1382,11 @@ function generate_legend(sp, screen, model_m) 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] + 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) From 8110fec4ef199fdec92204d9dd1aeaff767954e0 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Tue, 1 Nov 2016 12:28:37 +0100 Subject: [PATCH 6/6] fix mesh particle + better window creation --- src/backends/glvisualize.jl | 90 ++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 52 deletions(-) diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index 0d3b65de..398b34c4 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -108,19 +108,19 @@ function empty_screen!(screen) end nothing end -function _create_backend_figure(plt::Plot{GLVisualizeBackend}) +function create_window(plt::Plot{GLVisualizeBackend}, visible) # init a screen if isempty(GLVisualize.get_screens()) - s = GLVisualize.glscreen() + screen = GLVisualize.glscreen(resolution = plt[:size], visible = visible) Reactive.stop() @async begin - while isopen(s) + while isopen(screen) tic() GLWindow.pollevents() if Base.n_avail(Reactive._messages) > 0 Reactive.run_till_now() - GLWindow.render_frame(s) - GLWindow.swapbuffers(s) + GLWindow.render_frame(screen) + GLWindow.swapbuffers(screen) end yield() diff = (1/60) - toq() @@ -130,14 +130,16 @@ function _create_backend_figure(plt::Plot{GLVisualizeBackend}) diff -= toq() end end - GLWindow.destroy!(s) - GLVisualize.cleanup_old_screens() + GLWindow.destroy!(screen) end else - s = GLVisualize.current_screen() - empty_screen!(s) + screen = GLVisualize.current_screen() + empty_screen!(screen) end - s + plt.o = screen + GLWindow.set_visibility!(screen, visible) + resize!(screen, plt[:size]...) + screen end # --------------------------------------------------------------------------- @@ -570,7 +572,7 @@ end function draw_ticks(axis, ticks, align, move, isx, lims, model, text = "", positions = Point2f0[], offsets=Vec2f0[]) sz = axis[:tickfont].pointsize - rscale2 = Vec2f0(3/sz) + rscale2 = Vec2f0(2.5/sz) m = Reactive.value(model) xs, ys = m[1,1], m[2,2] rscale = rscale2 ./ Vec2f0(xs, ys) @@ -654,7 +656,7 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are :position => positions, :offset => offsets, :color => fcolor, - :relative_scale => Vec2f0(3/sz), + :relative_scale => Vec2f0(2.5/sz), :model => model, :scale_primitive => false ) @@ -879,19 +881,16 @@ end # ---------------------------------------------------------------- -function _display(plt::Plot{GLVisualizeBackend}) - screen = plt.o - empty_screen!(screen) +function _display(plt::Plot{GLVisualizeBackend}, visible=true) + screen = create_window(plt, visible) sw, sh = plt[:size] sw, sh = sw*px, sh*px - resize!(screen, plt[:size]...) + # TODO: use plt.subplots... plt.spmap can't be trusted for sp in plt.subplots _3d = Plots.is3d(sp) # camera = :perspective # 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) sub_area = map(screen.area) do rect Plots.gl_viewport(rel_bbox, rect) @@ -901,6 +900,7 @@ function _display(plt::Plot{GLVisualizeBackend}) screen, color = c, area = sub_area ) + sp.o = sp_screen cam = get!(sp_screen.cameras, :perspective) do inside = sp_screen.inputs[:mouseinside] theta = _3d ? nothing : Signal(Vec3f0(0)) # surpress rotation for 2D (nothing will get usual rotation controle) @@ -910,7 +910,6 @@ function _display(plt::Plot{GLVisualizeBackend}) ) end - sp.o = sp_screen 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)) for ann in sp[:annotations] @@ -919,12 +918,12 @@ function _display(plt::Plot{GLVisualizeBackend}) x, y, _1, _1 = Reactive.value(model_m) * Vec{4,Float32}(x, y, 0, 1) extract_font(plot_text.font, 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 # loop over the series and add them to the subplot if !_3d 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 Reactive.run_till_now() # make sure Reactive.push! arrives GLAbstraction.center!(cam, @@ -934,13 +933,14 @@ function _display(plt::Plot{GLVisualizeBackend}) ) else 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) end - for series in Plots.series_list(sp) + d = series.d st = d[:seriestype]; kw_args = KW() # exctract kw + kw_args[:model] = model_m # add transformation if !_3d # 3D is treated differently, since we need boundingboxes for camera kw_args[:boundingbox] = nothing # don't calculate bb, we dont need it @@ -1026,10 +1026,9 @@ function _display(plt::Plot{GLVisualizeBackend}) else error("failed to display plot type $st") end - if isa(vis, Array) && isempty(vis) - continue # nothing to see here - end - GLVisualize._view(vis, sp_screen, camera=cam) + isa(vis, Array) && isempty(vis) && continue # nothing to see here + + GLVisualize._view(vis, sp_screen, camera=:perspective) if haskey(d, :hover) && !(d[:hover] in (false, :none, nothing)) hover(vis, d[:hover], sp_screen) end @@ -1038,7 +1037,6 @@ function _display(plt::Plot{GLVisualizeBackend}) append!(_glplot_deletes, del_signal) end end - #@show model_m generate_legend(sp, sp_screen, model_m) if _3d GLAbstraction.center!(sp_screen) @@ -1049,13 +1047,13 @@ function _display(plt::Plot{GLVisualizeBackend}) end function _show(io::IO, ::MIME"image/png", plt::Plot{GLVisualizeBackend}) - _display(plt) + _display(plt, false) GLWindow.pollevents() if Base.n_avail(Reactive._messages) > 0 Reactive.run_till_now() end yield() - GLWindow.render_frame(plt.o) + GLWindow.render_frame(GLWindow.rootscreen(plt.o)) GLWindow.swapbuffers(plt.o) buff = GLWindow.screenbuffer(plt.o) png = Images.Image(map(RGB{U8}, buff), @@ -1108,6 +1106,7 @@ function gl_lines(points, kw_args) end return result end + function gl_shape(d, kw_args) points = Plots.extract_points(d) result = [] @@ -1118,6 +1117,7 @@ function gl_shape(d, kw_args) end result end + tovec2(x::FixedSizeArrays.Vec{2, Float32}) = x tovec2(x::AbstractVector) = map(tovec2, x) tovec2(x::FixedSizeArrays.Vec) = Vec2f0(x[1], x[2]) @@ -1131,9 +1131,12 @@ function gl_scatter(points, kw_args) prim = get(kw_args, :primitive, GeometryTypes.Circle) if isa(prim, GLNormalMesh) if haskey(kw_args, :model) - kw_args[:scale] = GLAbstraction.const_lift(kw_args[:model], kw_args[:scale]) do m, sc - s = m[1,1], m[2,2], m[3,3] - tovec3(sc).*(1f0./Vec3f0(s)) + p = get(kw_args, :perspective, eye(GeometryTypes.Mat4f0)) + 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 else # 2D prim @@ -1247,24 +1250,6 @@ end -function text_plot(text, alignment, kw_args) - transmat = kw_args[:model] - obj = visualize(text, Style(:default), kw_args) - bb = value(GLAbstraction.boundingbox(obj)) - w,h,_ = widths(bb) - x,y,_ = minimum(bb) - pivot = origin(alignment) - pos = pivot - (Point2f0(x, y) .* widths(alignment)) - if kw_args[:rotation] != 0.0 - rot = GLAbstraction.rotationmatrix_z(Float32(font.rotation)) - transmat *= translationmatrix(pivot)*rot*translationmatrix(-pivot) - end - - transmat *= GLAbstraction.translationmatrix(Vec3f0(pos..., 0)) - GLAbstraction.transformation(obj, transmat) - view(obj, img.screen, camera=:orthographic_pixel) -end - """ Ugh, so much special casing (╯°□°)╯︵ ┻━┻ """ @@ -1292,13 +1277,14 @@ function label_scatter(d, w, ho) mini = minimum(bb) m = GLAbstraction.translationmatrix(-mini) m *= GLAbstraction.scalematrix(1f0./bbw) - #m *= GLAbstraction.translationmatrix(-Vec3f0(0.5)) kw[:primitive] = m * p kw[:scale] = Vec3f0(w/2) delete!(kw, :offset) end GL.gl_scatter(Point2f0[(w/2, ho)], kw) end + + function make_label(sp, series, i) GL = Plots w, gap, ho = 20f0, 5f0, 5