Skip to content

Commit

Permalink
Merge branch 'master' into ff/jk-as-polar-axis
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonDanisch authored Jul 14, 2023
2 parents 88e5856 + bd315b4 commit 5f023f4
Show file tree
Hide file tree
Showing 24 changed files with 793 additions and 586 deletions.
43 changes: 33 additions & 10 deletions CairoMakie/src/infrastructure.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ function cairo_draw(screen::Screen, scene::Scene)
Cairo.save(screen.context)
draw_background(screen, scene)

allplots = get_all_plots(scene)
allplots = Makie.collect_atomic_plots(scene; is_atomic_plot = is_cairomakie_atomic_plot)
zvals = Makie.zvalue2d.(allplots)
permute!(allplots, sortperm(zvals))

Expand All @@ -23,10 +23,12 @@ function cairo_draw(screen::Screen, scene::Scene)

Cairo.save(screen.context)
for p in allplots
to_value(get(p, :visible, true)) || continue
check_parent_plots(p) do plot
to_value(get(plot, :visible, true))
end || continue
# only prepare for scene when it changes
# this should reduce the number of unnecessary clipping masks etc.
pparent = p.parent::Scene
pparent = Makie.parent_scene(p)
pparent.visible[] || continue
if pparent != last_scene
Cairo.restore(screen.context)
Expand All @@ -36,8 +38,8 @@ function cairo_draw(screen::Screen, scene::Scene)
end
Cairo.save(screen.context)

# When a plot is too large to save with a reasonable file size on a vector backend,
# the user can choose to rasterize it when plotting to vector backends, by using the
# When a plot is too large to save with a reasonable file size on a vector backend,
# the user can choose to rasterize it when plotting to vector backends, by using the
# `rasterize` keyword argument. This can be set to a Bool or an Int which describes
# the density of rasterization (in terms of a direct scaling factor.)
# TODO: In future, this can also be set to a Tuple{Module, Int} which describes
Expand All @@ -54,12 +56,33 @@ function cairo_draw(screen::Screen, scene::Scene)
return
end

function get_all_plots(scene, plots = AbstractPlot[])
append!(plots, scene.plots)
for c in scene.children
get_all_plots(c, plots)
"""
is_cairomakie_atomic_plot(plot::Combined)::Bool
Returns whether the plot is considered atomic for the CairoMakie backend.
This is overridden for `Poly`, `Band`, and `Tricontourf` so we can apply
CairoMakie can treat them as atomic plots and render them directly.
Plots with children are by default recursed into. This can be overridden
by defining specific dispatches for `is_cairomakie_atomic_plot` for a given plot type.
"""
is_cairomakie_atomic_plot(plot::Combined) = isempty(plot.plots) || to_value(get(plot, :rasterize, false)) != false

"""
check_parent_plots(f, plot::Combined)::Bool
Returns whether the plot's parent tree satisfies the predicate `f`.
`f` must return a `Bool` and take a plot as its only argument.
"""
function check_parent_plots(f, plot::Combined)
if f(plot)
check_parent_plots(f, parent(plot))
else
return false
end
plots
end

function check_parent_plots(f, scene::Scene)
return true
end

function prepare_for_scene(screen::Screen, scene::Scene)
Expand Down
16 changes: 16 additions & 0 deletions CairoMakie/src/overrides.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ function draw_plot(scene::Scene, screen::Screen, poly::Poly)
draw_poly(scene, screen, poly, to_value.(poly.input_args)...)
end

# Override `is_cairomakie_atomic_plot` to allow `poly` to remain a unit,
# instead of auto-decomposing in lines and mesh.
is_cairomakie_atomic_plot(plot::Poly) = true

"""
Fallback method for args without special treatment.
"""
Expand Down Expand Up @@ -182,6 +186,12 @@ function draw_plot(scene::Scene, screen::Screen,
nothing
end

# Override `is_cairomakie_atomic_plot` to allow this dispatch of `band` to remain a unit,
# instead of auto-decomposing in lines and mesh.
function is_cairomakie_atomic_plot(plot::Band{<:Tuple{<:AbstractVector{<:Point2},<:AbstractVector{<:Point2}}})
return true
end

#################################################################################
# Tricontourf #
# Tricontourf creates many disjoint polygons that are adjacent and form contour #
Expand Down Expand Up @@ -214,3 +224,9 @@ function draw_plot(scene::Scene, screen::Screen, tric::Tricontourf)

return
end

# Override `is_cairomakie_atomic_plot` to allow `Tricontourf` to remain a unit,
# instead of auto-decomposing in lines and mesh.
function is_cairomakie_atomic_plot(plot::Tricontourf)
return true
end
23 changes: 18 additions & 5 deletions GLMakie/assets/shader/lines.geom
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,21 @@ vec3 screen_space(vec4 vertex)
// Manual uv calculation
// - position in screen space (double resolution as generally used)
// - uv with uv.u normalized (0..1), uv.v unnormalized (0..pattern_length)
void emit_vertex(vec3 position, vec2 uv, int index)
void emit_vertex(vec3 position, vec2 uv, int index, float thickness)
{
f_uv = uv;
f_color = g_color[index];
gl_Position = vec4((position.xy / resolution), position.z, 1.0);
f_id = g_id[index];
// linewidth scaling may shrink the effective linewidth
f_thickness = abs(uv.y) - AA_THICKNESS;
f_thickness = thickness;
EmitVertex();
}
// default for miter joins
void emit_vertex(vec3 position, vec2 uv, int index)
{
emit_vertex(position, uv, index, g_thickness[index]);
}

// For center point
void emit_vertex(vec3 position, vec2 uv)
Expand All @@ -72,15 +77,20 @@ void emit_vertex(vec3 position, vec2 uv)
}

// Debug
void emit_vertex(vec3 position, vec2 uv, int index, vec4 color)
void emit_vertex(vec3 position, vec2 uv, int index, vec4 color, float thickness)
{
f_uv = uv;
f_color = color;
gl_Position = vec4((position.xy / resolution), position.z, 1.0);
f_id = g_id[index];
f_thickness = abs(uv.y) - AA_THICKNESS;
f_thickness = thickness;
EmitVertex();
}
// default for miter joins
void emit_vertex(vec3 position, vec2 uv , int index, vec4 color)
{
emit_vertex(position, uv , index, color, g_thickness[index]);
}
void emit_vertex(vec3 position, vec2 uv, vec4 color)
{
f_uv = uv;
Expand All @@ -98,8 +108,11 @@ void emit_vertex(vec3 position, vec2 offset, vec2 line_dir, vec2 uv, int index)
emit_vertex(
position + vec3(offset, 0),
vec2(uv.x + px2uv * dot(line_dir, offset), uv.y),
index
index,
abs(uv.y) - AA_THICKNESS
);
// `abs(uv.y) - AA_THICKNESS` corrects for enlarged AA padding between
// segments of different linewidth, see #2953
}

void emit_vertex(vec3 position, vec2 offset, vec2 line_dir, vec2 uv)
Expand Down
6 changes: 3 additions & 3 deletions GLMakie/src/screen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ mutable struct ScreenConfig
end
end

const LAST_INLINE = Ref{Union{Makie.Automatic, Bool}}(Makie.automatic)
const LAST_INLINE = Ref{Union{Makie.Automatic, Bool}}(false)

"""
GLMakie.activate!(; screen_config...)
Expand Down Expand Up @@ -518,7 +518,7 @@ end
function Base.delete!(screen::Screen, scene::Scene, plot::AbstractPlot)
if !isempty(plot.plots)
# this plot consists of children, so we flatten it and delete the children instead
for cplot in Makie.flatten_plots(plot)
for cplot in Makie.collect_atomic_plots(plot)
delete!(screen, scene, cplot)
end
else
Expand Down Expand Up @@ -919,7 +919,7 @@ function renderloop(screen)
end

function plot2robjs(screen::Screen, plot)
plots = Makie.flatten_plots(plot)
plots = Makie.collect_atomic_plots(plot)
return map(x-> screen.cache[objectid(x)], plots)
end

Expand Down
6 changes: 6 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
- Added a new Axis type, `PolarAxis`, which is an axis with a polar projection. Input is in `(r, theta)` coordinates and is transformed to `(x, y)` coordinates using the standard polar-to-cartesian transformation. Generally, its attributes are very similar to the usual `Axis` attributes, but `x` is replaced by `r` and `y` by `θ`. It also inherits from the theme of `Axis` in this manner, so should work seamlessly with Makie themes. [#2990](https://github.com/MakieOrg/Makie.jl/pull/2990)
- `inherit` now has a new signature `inherit(scene, attrs::NTuple{N, Symbol}, default_value)`, allowing recipe authors to access nested attributes when trying to inherit from the parent Scene. For example, one could inherit from `scene.Axis.yticks` by `inherit(scene, (:Axis, :yticks), $default_value)`. [#2990](https://github.com/MakieOrg/Makie.jl/pull/2990)
- Fix broken AA for lines with strongly varying linewidth [#2953](https://github.com/MakieOrg/Makie.jl/pull/2953)
- Deprecated `flatten_plots` in favor of `collect_atomic_plots`. Using the new `collect_atomic_plots` fixed a bug in CairoMakie where the z-level of plots within recipes was not respected. [#2793](https://github.com/MakieOrg/Makie.jl/pull/2793)
- Fixed incorrect line depth in GLMakie [#2843](https://github.com/MakieOrg/Makie.jl/pull/2843)
- Fixed incorrect line alpha in dense lines in GLMakie [#2843](https://github.com/MakieOrg/Makie.jl/pull/2843)
- Fixed DataInspector interaction with transformations [#3002](https://github.com/MakieOrg/Makie.jl/pull/3002)
- Added option `WGLMakie.activate!(resize_to_body=true)`, to make plots resize to the VSCode plotpane. Resizes to the HTML body element, so may work outside VSCode [#3044](https://github.com/MakieOrg/Makie.jl/pull/3044), [#3042](https://github.com/MakieOrg/Makie.jl/pull/3042).
- Fixed DataInspector interaction with transformations [#3002](https://github.com/MakieOrg/Makie.jl/pull/3002).
- Fix incomplete stroke with some Bezier markers in CairoMakie and blurry strokes in GLMakie [#2961](https://github.com/MakieOrg/Makie.jl/pull/2961)
- Added the ability to use custom triangulations from DelaunayTriangulation.jl [#2896](https://github.com/MakieOrg/Makie.jl/pull/2896).
- Adjusted scaling of scatter/text stroke, glow and anti-aliasing width under non-uniform 2D scaling (Vec2f markersize/fontsize) in GLMakie [#2950](https://github.com/MakieOrg/Makie.jl/pull/2950).
- Scaled `errorbar` whiskers and `bracket` correctly with transformations [#3012](https://github.com/MakieOrg/Makie.jl/pull/3012).
- Updated `bracket` when the screen is resized or transformations change [#3012](https://github.com/MakieOrg/Makie.jl/pull/3012).
- Added auto-resizing functionality to WGLMakie plot figures [#3042](https://github.com/MakieOrg/Makie.jl/pull/3042)

## v0.19.6

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<source media="(prefers-color-scheme: dark)"
srcset="/assets/makie_logo_canvas_dark.svg" >
<img alt="Makie.jl logo"
src="/assets/makie_logo_canvas.svg" >
src="/assets/makie_logo_canvas.svg" width="400">
</picture>
</div>

Expand Down
25 changes: 25 additions & 0 deletions ReferenceTests/src/tests/examples2d.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1019,3 +1019,28 @@ end
end
f
end

@reference_test "Z-translation within a recipe" begin
# This is testing whether backends respect the
# z-level of plots within recipes in 2d.
# Ideally, the output of this test
# would be a blue line with red scatter markers.
# However, if a backend does not correctly pick up on translations,
# then this will be drawn in the drawing order, and blue
# will completely obscure red.

# It seems like we can't define recipes in `@reference_test` yet,
# so we'll have to fake a recipe's structure.

fig = Figure(resolution = (600, 600))
# Create a recipe plot
ax, plot_top = heatmap(fig[1, 1], randn(10, 10))
# Plot some recipes at the level below the contour
scatterlineplot_1 = scatterlines!(plot_top, 1:10, 1:10; linewidth = 20, markersize = 20, color = :red)
scatterlineplot_2 = scatterlines!(plot_top, 1:10, 1:10; linewidth = 20, markersize = 30, color = :blue)
# Translate the lowest level plots (scatters)
translate!(scatterlineplot_1.plots[2], 0, 0, 1)
translate!(scatterlineplot_2.plots[2], 0, 0, -1)
# Display
fig
end
15 changes: 15 additions & 0 deletions ReferenceTests/src/tests/figures_and_makielayout.jl
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,18 @@ end
f
end
end

@reference_test "LaTeXStrings in Axis3 plots" begin
xs = LinRange(-10, 10, 100)
ys = LinRange(0, 15, 100)
zs = [cos(x) * sin(y) for x in xs, y in ys]


fig = Figure()
ax = Axis3(fig[1, 1]; xtickformat = xs -> [L"%$x" for x in xs])
# check that switching to latex later also works
ax.ytickformat = xs -> [L"%$x" for x in xs]

surface!(ax, xs, ys, zs)
fig
end
11 changes: 5 additions & 6 deletions WGLMakie/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
WGLMakie is a WebGL backend for the [Makie.jl](https://www.github.com/MakieOrg/Makie.jl) plotting package, implemented using Three.js.

Read the docs for Makie and it's backends [here](http://docs.makie.org/dev)
Read the docs for Makie and it's backends [here](http://docs.makie.org)

# Usage

Now, it should just work like Makie:

```julia
using WGLMakie
scatter(rand(4))
Expand All @@ -16,7 +14,8 @@ In VSCode, this should open in the plotpane.
You can also embed plots in a JSServe webpage:

```julia
function dom_handler(session, request)
using JSServe
app = App(session, request)
return DOM.div(
DOM.h1("Some Makie Plots:"),
meshscatter(1:4, color=1:4),
Expand All @@ -27,8 +26,8 @@ function dom_handler(session, request)
meshscatter(rand(Point3f, 10), marker=Pyramid(Point3f(0), 1f0, 1f0)),
)
end
isdefined(Main, :app) && close(app)
app = JSServe.Server(dom_handler, "127.0.0.1", 8082)
isdefined(Main, :server) && close(server)
server = JSServe.Server(app, "127.0.0.1", 8082)
```

## Sponsors
Expand Down
12 changes: 7 additions & 5 deletions WGLMakie/src/Camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,23 @@ export function attach_3d_camera(canvas, makie_camera, cam3d, scene) {
camera.up = new THREE.Vector3(...cam3d.upvector);
camera.position.set(...cam3d.eyeposition);
camera.lookAt(center);

function update() {
camera.updateProjectionMatrix();
camera.updateWorldMatrix();
const view = camera.matrixWorldInverse;
const projection = camera.projectionMatrix;
const [width, height] = makie_camera.resolution.value;
const [width, height] = cam3d.resolution.value;
const [x, y, z] = camera.position;
camera.aspect = width / height;
camera.updateProjectionMatrix();
camera.updateWorldMatrix();

makie_camera.update_matrices(
view.elements,
projection.elements,
[width, height],
[x, y, z]
);
);
}
cam3d.resolution.on(update);

function addMouseHandler(domObject, drag, zoomIn, zoomOut) {
let startDragX = null;
Expand Down
5 changes: 3 additions & 2 deletions WGLMakie/src/display.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const WEB_MIMES = (
"""
struct ScreenConfig
framerate::Float64 # =30.0
resize_to_body::Bool # false
end

"""
Expand Down Expand Up @@ -205,7 +206,7 @@ function session2image(session::Session, scene::Scene)
to_data = js"""function (){
return $(scene).then(scene => {
const {renderer} = scene.screen
WGLMakie.render_scene(scene)
WGL.render_scene(scene)
const img = renderer.domElement.toDataURL()
return img
})
Expand Down Expand Up @@ -342,7 +343,7 @@ const DISABLE_JS_FINALZING = Base.RefValue(false)
const DELETE_QUEUE = LockfreeQueue{Tuple{Screen,String,Vector{String}}}(delete_plot!)

function Base.delete!(screen::Screen, scene::Scene, plot::Combined)
atomics = Makie.flatten_plots(plot) # delete all atomics
atomics = Makie.collect_atomic_plots(plot) # delete all atomics
# only queue atomics to actually delete on js
if !DISABLE_JS_FINALZING[]
push!(DELETE_QUEUE, (screen, js_uuid(scene), js_uuid.(atomics)))
Expand Down
3 changes: 3 additions & 0 deletions WGLMakie/src/events.jl
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ function connect_scene_events!(scene::Scene, comm::Observable)
e.keyboardbutton[] = KeyEvent(code_to_keyboard(keyup), Keyboard.release)
end
end
@handle msg.resize begin
resize!(scene, tuple(resize...))
end
catch err
@warn "Error in window event callback" exception=(err, Base.catch_backtrace())
end
Expand Down
Loading

0 comments on commit 5f023f4

Please sign in to comment.