Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Patterned bar plots in CairoMakie #1385

Closed
icweaver opened this issue Oct 13, 2021 · 12 comments · Fixed by #2106
Closed

Feature request: Patterned bar plots in CairoMakie #1385

icweaver opened this issue Oct 13, 2021 · 12 comments · Fixed by #2106
Labels
CairoMakie This relates to CairoMakie, the vector backend for Makie based on Cairo.

Comments

@icweaver
Copy link

Following up on the discussion from slack, it would be great if similar functionality to this example in GLMakie from 100daysOfMakie could be brought to CairoMakie as well

using Makie, GLMakie, Random
Random.seed!(3)
# patterns
# `'/'`, `'\\'`, `'-'`, `'|'`, `'x'`, and `'+'`
directions = [Vec2f0(1), Vec2f0(1, -1), Vec2f0(1, 0), Vec2f0(0, 1),
    [Vec2f0(1), Vec2f0(1, -1)], [Vec2f0(1, 0), Vec2f0(0, 1)]]
colors = [:white, :red, (:green, 0.5), :white, (:navy, 0.85),:black]
patterns = [Makie.LinePattern(direction= hatch; width = 5, tilesize=(20,20),
    linecolor = colors[indx], background_color = colors[end-indx+1])
    for (indx, hatch) in enumerate(directions)]
fig = Figure(resolution = (1200,800), fontsize = 32)
ax = Axis(fig[1,1])
for (idx, pattern) in enumerate(patterns)
    barplot!(ax, [idx], [idx*(2rand()+1)], color = pattern, strokewidth = 2)
end
ax.xticks = (1:6, ["/", "\\", "-", "|", "x", "+"])
save("strippedPatterns.png", fig)
fig

strippedPatterns

@SimonDanisch SimonDanisch added the CairoMakie This relates to CairoMakie, the vector backend for Makie based on Cairo. label Nov 2, 2021
@Moelf
Copy link
Contributor

Moelf commented Jun 25, 2022

I'd like to try implementing this, any pointer to a similar PR?

@greimel
Copy link
Contributor

greimel commented Jun 25, 2022

not sure if relevant, but here's the PR that added this to Plots.jl JuliaPlots/Plots.jl#3107

@Moelf
Copy link
Contributor

Moelf commented Jun 25, 2022

don't think so, this is CairoMakie, for the record, I'd like to know at which point I need to add stuff:

julia> using CairoMakie

julia> p = Pattern('/');

julia> save("/tmp/f.png", barplot([1],[2], color=p))
ERROR: CanonicalIndexError: getindex not defined for Makie.LinePattern
Stacktrace:
  [1] error_if_canonical_getindex(::IndexCartesian, ::Makie.LinePattern, ::Int64, ::Int64)
    @ Base ./abstractarray.jl:1255
  [2] getindex
    @ ./abstractarray.jl:1235 [inlined]
  [3] _getindex
    @ ./abstractarray.jl:1281 [inlined]
  [4] getindex
    @ ./abstractarray.jl:1236 [inlined]
  [5] attr_broadcast_getindex(x::Makie.LinePattern, i::Int64)
    @ Makie ~/Documents/github/Makie.jl/src/utilities/utilities.jl:164
  [6] macro expansion
    @ ~/Documents/github/Makie.jl/src/utilities/utilities.jl:199 [inlined]
  [7] broadcast_foreach(::CairoMakie.var"#64#65"{CairoMakie.CairoScreen{Cairo.CairoSurfaceBase{UInt32}}}, ::Vector{GeometryBasics.HyperRectangle{2, Float32}}, ::Makie.LinePattern, ::Symbol, ::Int64)
    @ Makie ~/Documents/github/Makie.jl/src/utilities/utilities.jl:185
  [8] draw_poly(scene::Scene, screen::CairoMakie.CairoScreen{Cairo.CairoSurfaceBase{UInt32}}, poly::Combined{Makie.poly, Tuple{Vector{GeometryBasics.HyperRectangle{2, Float32}}}}, rects::Vector{GeometryBasics.HyperRectangle{2, Float32}})
    @ CairoMakie ~/Documents/github/Makie.jl/CairoMakie/src/overrides.jl:84
  [9] draw_plot(scene::Scene, screen::CairoMakie.CairoScreen{Cairo.CairoSurfaceBase{UInt32}}, poly::Combined{Makie.poly, Tuple{Vector{GeometryBasics.HyperRectangle{2, Float32}}}})
    @ CairoMakie ~/Documents/github/Makie.jl/CairoMakie/src/overrides.jl:13
 [10] draw_plot(scene::Scene, screen::CairoMakie.CairoScreen{Cairo.CairoSurfaceBase{UInt32}}, primitive::Combined{Makie.barplot, Tuple{Vector{Point{2, Float32}}}})
    @ CairoMakie ~/Documents/github/Makie.jl/CairoMakie/src/infrastructure.jl:255
 [11] cairo_draw(screen::CairoMakie.CairoScreen{Cairo.CairoSurfaceBase{UInt32}}, scene::Scene)
    @ CairoMakie ~/Documents/github/Makie.jl/CairoMakie/src/infrastructure.jl:192
 [12] backend_show(x::CairoMakie.CairoBackend, io::IOContext{IOStream}, #unused#::MIME{Symbol("image/png")}, scene::Scene)
    @ CairoMakie ~/Documents/github/Makie.jl/CairoMakie/src/infrastructure.jl:396

@ffreyer
Copy link
Collaborator

ffreyer commented Jun 25, 2022

@Moelf
Copy link
Contributor

Moelf commented Jun 25, 2022

right now it doesn't call this function at all, I guess one of the function on the current stack trace needs to be replaced by a specialization?

@Moelf
Copy link
Contributor

Moelf commented Jun 25, 2022

@ffreyer
Copy link
Collaborator

ffreyer commented Jun 26, 2022

Ah right, poly has it's own backend code.

I don't know Cairo well enough to know how these patterns should be implemented, but I don't think you need to worry about that branch. I assume you either need to make a new branch that transforms the pattern into an image and uses it as a repeated texture like opengl, or that Cairo has some version of hatching/patterns natively that you could use

@Moelf
Copy link
Contributor

Moelf commented Jun 26, 2022

that branch takes a Matrix (image) pattern as color, I thought it would tile the color for the entire surface, but it's not (as the comment says).

If this branch were to work correctly, I can use it to draw the inside of the bar plot? or I guess this is not the correct way to go about it.


I also didn't find anything in Cairo.jl, but maybe something like https://stackoverflow.com/questions/28755265/cairo-fill-a-polygon-with-a-hatch-pattern

@Moelf
Copy link
Contributor

Moelf commented Jun 26, 2022

@asinghvi17
Copy link
Member

asinghvi17 commented Jun 26, 2022

We could also draw patterns onto a CairoRecordingSurface using Cairo intrinsics (set_line_width, move_to, line_to) and then set those surfaces as the pattern, and simply clip everything which is not within the area by using e.g. cairo_clip with cairo_path_to. That would make the approach somewhat more flexible and probably render at better resolution in small or vector graphics.

If you can get the patterns onto a recording surface I would be more than happy to help with the second part.

@Moelf
Copy link
Contributor

Moelf commented Jun 26, 2022

What's the difference between imagesurface and recordingsurface?

@Moelf
Copy link
Contributor

Moelf commented Jul 2, 2022

@asinghvi17 I can't find any use of CairoRecordingSurface inside Makie, but I think it's much easier if we use pattern_set_extend(pattern, Cario.EXTEND_REPEAT):
https://gist.github.com/Moelf/e380d20b307901a6947881dc163a6c62

image

here we're clipping with arc(), I think if we clip it to a poly, it's basically what you wanted?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CairoMakie This relates to CairoMakie, the vector backend for Makie based on Cairo.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants