Skip to content

Commit

Permalink
Merge branch 'master' into as/streamplot
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonDanisch authored Jul 21, 2023
2 parents 33455cd + e3835c1 commit 96bae2c
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 25 deletions.
9 changes: 7 additions & 2 deletions GLMakie/src/screen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,6 @@ function apply_config!(screen::Screen, config::ScreenConfig; start_renderloop::B
replace_processor!(config.fxaa ? fxaa_postprocessor : empty_postprocessor, 3)
# Set the config
screen.config = config

if start_renderloop
start_renderloop!(screen)
else
Expand Down Expand Up @@ -688,7 +687,13 @@ function Makie.colorbuffer(screen::Screen, format::Makie.ImageStorageFormat = Ma
# GLFW.PollEvents()
# keep current buffer size to allows larger-than-window renders
render_frame(screen, resize_buffers=false) # let it render
glFinish() # block until opengl is done rendering
if screen.config.visible
GLFW.SwapBuffers(to_native(screen))
else
# SwapBuffers blocks as well, but if we don't call that
# We need to call glFinish to wait for all OpenGL changes to finish
glFinish()
end
if size(ctex) != size(screen.framecache)
screen.framecache = Matrix{RGB{N0f8}}(undef, size(ctex))
end
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## master

- Allow arbitrary functions to color `streamplot` lines by passing a `Function` to `color`. This must accept `Point` of the appropriate dimension and return a `Point`, `Vec`, or other arraylike object [#2002](https://github.com/MakieOrg/Makie.jl/pull/2002).
- Exported colorbuffer, and added `colorbuffer(axis::Axis; include_decorations=false, colorbuffer_kws...)`, to get an image of an axis with or without decorations [#3078](https://github.com/MakieOrg/Makie.jl/pull/3078).
- Fixed an issue where the `linestyle` of some polys was not applied to the stroke in CairoMakie. [#2604](https://github.com/MakieOrg/Makie.jl/pull/2604)
- Add `colorscale = identity` to any plotting function using a colormap. This works with any scaling function like `log10`, `sqrt` etc. Consequently, `scale` for `hexbin` is replaced with `colorscale` [#2900](https://github.com/MakieOrg/Makie.jl/pull/2900).
- Add `alpha=1.0` argument to all basic plots, which supports independently adding an alpha component to colormaps and colors. Multiple alphas like in `plot(alpha=0.2, color=RGBAf(1, 0, 0, 0.5))`, will get multiplied [#2900](https://github.com/MakieOrg/Makie.jl/pull/2900).
Expand Down
25 changes: 25 additions & 0 deletions ReferenceTests/src/tests/short_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,31 @@ end
f
end

@reference_test "colorbuffer for axis" begin
fig = Figure()
ax1 = Axis(fig[1, 1])
ax2 = Axis(fig[1, 2])
ax3 = Axis(fig[2, 2])
ax4 = Axis(fig[2, 1])
scatter!(ax1, 1:10, 1:10; markersize=50, color=1:10)
scatter!(ax2, 1:10, 1:10; markersize=50, color=:red)
heatmap!(ax3, -8:0.1:8, 8:0.1:8, (x, y) -> sin(x) + cos(y))
meshscatter!(ax4, 1:10, 1:10; markersize=1, color=:red)
img1 = colorbuffer(ax1; include_decorations=true)
img2 = colorbuffer(ax2; include_decorations=false)
img3 = colorbuffer(ax3; include_decorations=true)
img4 = colorbuffer(ax4; include_decorations=false)
f, ax5, pl = image(rotr90(img1); axis=(; aspect=DataAspect()))
ax6, pl = image(f[1, 2], rotr90(img2); axis=(; aspect=DataAspect()))
ax7, pl = image(f[2, 2], rotr90(img3); axis=(; aspect=DataAspect()))
ax8, pl = image(f[2, 1], rotr90(img4); axis=(; aspect=DataAspect()))
hidedecorations!(ax5)
hidedecorations!(ax6)
hidedecorations!(ax7)
hidedecorations!(ax8)
f
end


# Needs a way to disable autolimits on show
# @reference_test "interactions after close" begin
Expand Down
2 changes: 1 addition & 1 deletion src/Makie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export abline! # until deprecation removal

export Stepper, replay_events, record_events, RecordEvents, record, VideoStream
export VideoStream, recordframe!, record, Record
export save
export save, colorbuffer

# colormap stuff from PlotUtils, and showgradients
export cgrad, available_gradients, showgradients
Expand Down
25 changes: 20 additions & 5 deletions src/display.jl
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,8 @@ function FileIO.save(
# If the scene already got displayed, we get the current screen its displayed on
# Else, we create a new scene and update the state of the fig
update && update_state_before_display!(fig)
screen = getscreen(backend, scene, io, mime; visible=false, screen_config...)
visible = !isnothing(getscreen(scene)) # if already has a screen, don't hide it!
screen = getscreen(backend, scene, io, mime; visible=visible, screen_config...)
backend_show(screen, io, mime, scene)
end
catch e
Expand Down Expand Up @@ -408,9 +409,16 @@ function getscreen(backend::Union{Missing, Module}, scene::Scene, args...; scree
end
end

function get_sub_picture(image, format::ImageStorageFormat, rect)
xmin, ymin = minimum(rect) .- (1, 0)
xmax, ymax = maximum(rect)
start = size(image, 1) - ymax
stop = size(image, 1) - ymin
return image[start:stop, xmin:xmax]
end

"""
colorbuffer(scene, format::ImageStorageFormat = JuliaNative; backend=current_backend(), screen_config...)
colorbuffer(screen, format::ImageStorageFormat = JuliaNative)
colorbuffer(scene, format::ImageStorageFormat = JuliaNative; update=true, backend=current_backend(), screen_config...)
Returns the content of the given scene or screen rasterised to a Matrix of
Colors. The return type is backend-dependent, but will be some form of RGB
Expand All @@ -421,12 +429,19 @@ or RGBA.
- `format = GLNative` : Returns a more efficient format buffer for GLMakie which can be directly
used in FFMPEG without conversion
- `screen_config`: Backend dependend, look up via `?Backend.Screen`/`Base.doc(Backend.Screen)`
- `update=true`: resets/updates limits. Set to false, if you want to preserver camera movements.
"""
function colorbuffer(fig::FigureLike, format::ImageStorageFormat = JuliaNative; update=true, backend = current_backend(), screen_config...)
scene = get_scene(fig)
update && update_state_before_display!(fig)
screen = getscreen(backend, scene, format; start_renderloop=false, visible=false, screen_config...)
return colorbuffer(screen, format)
visible = !isnothing(getscreen(scene)) # if already has a screen, don't hide it!
screen = getscreen(backend, scene; start_renderloop=false, visible=visible, screen_config...)
img = colorbuffer(screen, format)
if !isroot(scene)
return get_sub_picture(img, format, pixelarea(scene)[])
else
return img
end
end

# Fallback for any backend that will just use colorbuffer to write out an image
Expand Down
27 changes: 27 additions & 0 deletions src/makielayout/blocks/axis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1785,3 +1785,30 @@ function attribute_examples(::Type{Axis})
],
)
end

function axis_bounds_with_decoration(axis::Axis)
# Filter out the zoomrect + background plot
lims = Makie.data_limits(axis.blockscene.plots, p -> p isa Mesh || p isa Poly)
return Makie.parent_transform(axis.blockscene) * lims
end

"""
colorbuffer(ax::Axis; include_decorations=true, colorbuffer_kws...)
Gets the colorbuffer of the `Axis` in `JuliaNative` image format.
If `include_decorations=false`, only the inside of the axis is fetched.
"""
function colorbuffer(ax::Axis; include_decorations=true, update=true, colorbuffer_kws...)
if update
update_state_before_display!(ax)
end
bb = if include_decorations
bb = axis_bounds_with_decoration(ax)
Rect2{Int}(round.(Int, minimum(bb)) .+ 1, round.(Int, widths(bb)))
else
pixelarea(ax.scene)[]
end

img = colorbuffer(root(ax.scene); update=false, colorbuffer_kws...)
return get_sub_picture(img, JuliaNative, bb)
end
38 changes: 21 additions & 17 deletions src/makielayout/blocks/axis3d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -477,10 +477,11 @@ function add_ticks_and_ticklabels!(topscene, scene, ax, dim::Int, limits, tickno
map!(ticklabels, ticknode) do (values, labels)
labels
end
ticksize = attr(:ticksize)

tick_segments = lift(topscene, limits, tickvalues, miv, min1, min2,
scene.camera.projectionview, scene.px_area) do lims, ticks, miv, min1, min2,
pview, pxa
scene.camera.projectionview, scene.px_area, ticksize) do lims, ticks, miv, min1, min2,
pview, pxa, tsize
f1 = !min1 ? minimum(lims)[d1] : maximum(lims)[d1]
f2 = min2 ? minimum(lims)[d2] : maximum(lims)[d2]

Expand All @@ -490,23 +491,28 @@ function add_ticks_and_ticklabels!(topscene, scene, ax, dim::Int, limits, tickno
diff_f1 = f1 - f1_oppo
diff_f2 = f2 - f2_oppo

map(ticks) do t
o = pxa.origin

return map(ticks) do t
p1 = dpoint(t, f1, f2)
p2 = if dim == 3
# special case the z axis, here it depends on azimuth in which direction the ticks go
if 45 <= mod1(rad2deg(azimuth[]), 180) <= 135
dpoint(t, f1 + 0.03 * diff_f1, f2)
dpoint(t, f1 + diff_f1, f2)
else
dpoint(t, f1, f2 + 0.03 * diff_f2)
dpoint(t, f1, f2 + diff_f2)
end
else
dpoint(t, f1 + 0.03 * diff_f1, f2)
dpoint(t, f1 + diff_f1, f2)
end

(p1, p2)
end
end
pp1 = Point2f(o + Makie.project(scene, p1))
pp2 = Point2f(o + Makie.project(scene, p2))
diff_pp = Makie.GeometryBasics.normalize(Point2f(pp2 - pp1))

return (pp1, pp1 .+ Float32(tsize) .* diff_pp)
end
end
# we are going to transform the 3d tick segments into 2d of the topscene
# because otherwise they
# be cut when they extend beyond the scene boundary
Expand All @@ -516,10 +522,13 @@ function add_ticks_and_ticklabels!(topscene, scene, ax, dim::Int, limits, tickno
end
end

ticks = linesegments!(topscene, tick_segments_2dz,
ticks = linesegments!(topscene, tick_segments,
xautolimits = false, yautolimits = false, zautolimits = false,
transparency = true, inspectable = false,
color = attr(:tickcolor), linewidth = attr(:tickwidth), visible = attr(:ticksvisible))
# -10000 is an arbitrary weird constant that in preliminary testing didn't seem
# to clip into plot objects anymore
translate!(ticks, 0, 0, -10000)

labels_positions = Observable{Any}()
map!(topscene, labels_positions, scene.px_area, scene.camera.projectionview,
Expand All @@ -528,12 +537,8 @@ function add_ticks_and_ticklabels!(topscene, scene, ax, dim::Int, limits, tickno
o = pxa.origin

points = map(ticksegs) do (tstart, tend)
tstartp = Point2f(o + Makie.project(scene, tstart))
tendp = Point2f(o + Makie.project(scene, tend))

offset = pad * Makie.GeometryBasics.normalize(
Point2f(tendp - tstartp))
tendp + offset
offset = pad * Makie.GeometryBasics.normalize(Point2f(tend - tstart))
tend + offset
end

N = min(length(ticklabs), length(points))
Expand Down Expand Up @@ -609,7 +614,6 @@ function add_ticks_and_ticklabels!(topscene, scene, ax, dim::Int, limits, tickno
if slight_flip
offset_ang_90deg_alwaysup += pi
end
offset_ang_90deg_alwaysup

labelrotation = if lrotation == Makie.automatic
offset_ang_90deg_alwaysup
Expand Down
6 changes: 6 additions & 0 deletions src/makielayout/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,12 @@ end
ytickwidth = 1
"The z tick width"
ztickwidth = 1
"The size of the xtick marks."
xticksize::Float64 = 12f0
"The size of the ytick marks."
yticksize::Float64 = 12f0
"The size of the ztick marks."
zticksize::Float64 = 12f0
"The color of x spine 1 where the ticks are displayed"
xspinecolor_1 = :black
"The color of y spine 1 where the ticks are displayed"
Expand Down

0 comments on commit 96bae2c

Please sign in to comment.