CairoMakie stop splitting line into segments when using varying colour along line

When you have a line with varying colour, CairoMakie splits the line up into segments defined by your data points. Is there a way to avoid this?

image

code to produce fig:

using CairoMakie
f = Figure()
ax = Axis(f[1, 1])
x = 0:0.2:2*pi
lines!(ax,x,sin.(x),color=x,linewidth=8)
save("test.pdf", f)

This is a limitation of Cairo’s line drawing, it can’t draw gradients along lines so you have to draw them segment by segment. I guess one could draw polys instead and manually compute the join geometry. That could be a PR for someone motivated, it would be slower though.

Hi thanks very much for your reply!

I assumed it was something like that, but saw the colour changing on a straight segment:

image

I imported the .pdf into inkscape and the coloured segment is one object. Is the issue with curved lines + colour gradients?

I mean not along a line that zigzags across the canvas. It can draw a gradient over the whole line but that’s usually not what you want.

I see, thank you! I implemented your poly idea, and seems to be working well up until applying the colour. There seems to be a bug with CairoMakie and setting the colour of a poly using a vector of numbers. Unless I’m missing something?

 f = Figure()
 ax = Axis(f[1,1])

 x = [-1,-1,1,1,-1]
 y = [-1,1,1,-1,-1]
 c = [0,2,4,6,8]
 poly!(ax,hcat(x,y),color=c)

 save("test.pdf",f)

Error:

ERROR: BoundsError: attempt to access 1-element Vector{Vector{Point{2, Float32}}} at index [2]
Stacktrace:
  [1] getindex
    @ .\essentials.jl:13 [inlined]
  [2] attr_broadcast_getindex
    @ C:\Users\username\.julia\packages\Makie\VRavR\src\utilities\utilities.jl:174 [inlined]
  [3] macro expansion
    @ C:\Users\username\.julia\packages\Makie\VRavR\src\utilities\utilities.jl:213 [inlined]
  [4] broadcast_foreach(::CairoMakie.var"#56#57"{…}, ::Vector{…}, ::Vector{…}, ::ColorTypes.RGBA{…}, ::Nothing, ::Int64, ::Base.RefValue{…})
    @ Makie C:\Users\username\.julia\packages\Makie\VRavR\src\utilities\utilities.jl:199
  [5] draw_poly(scene::Scene, screen::CairoMakie.Screen{CairoMakie.PDF}, poly::Poly{Tuple{…}}, points_list::Vector{Vector{…}})
    @ CairoMakie C:\Users\username\.julia\packages\CairoMakie\W0SZK\src\overrides.jl:76
  [6] draw_plot(scene::Scene, screen::CairoMakie.Screen{CairoMakie.PDF}, poly::Poly{Tuple{Vector{Vector{Point{2, Float32}}}}})
    @ CairoMakie C:\Users\username\.julia\packages\CairoMakie\W0SZK\src\overrides.jl:21
  [7] cairo_draw(screen::CairoMakie.Screen{CairoMakie.PDF}, scene::Scene)
    @ CairoMakie C:\Users\username\.julia\packages\CairoMakie\W0SZK\src\infrastructure.jl:51
  [8] backend_show(screen::CairoMakie.Screen{CairoMakie.PDF}, io::IOStream, ::MIME{Symbol("application/pdf")}, scene::Scene)
    @ CairoMakie C:\Users\username\.julia\packages\CairoMakie\W0SZK\src\display.jl:90
  [9] (::Makie.var"#1279#1280"{Module, Bool, @Kwargs{}, Figure, MIME{Symbol("application/pdf")}, Scene})(io::IOStream)
    @ Makie C:\Users\username\.julia\packages\Makie\VRavR\src\display.jl:344
 [10] open(::Makie.var"#1279#1280"{…}, ::String, ::Vararg{…}; kwargs::@Kwargs{})
    @ Base .\io.jl:396
 [11] open
    @ .\io.jl:393 [inlined]
 [12] save(file::FileIO.File{…}, fig::Figure; size::Tuple{…}, resolution::Nothing, backend::Module, update::Bool, screen_config::@Kwargs{})
    @ Makie C:\Users\username\.julia\packages\Makie\VRavR\src\display.jl:336
 [13] save(file::FileIO.File{FileIO.DataFormat{:PDF}, String}, fig::Figure)
    @ Makie C:\Users\username\.julia\packages\Makie\VRavR\src\display.jl:308
 [14] save(filename::String, fig::Figure; args::@Kwargs{})
    @ Makie C:\Users\username\.julia\packages\Makie\VRavR\src\display.jl:305
 [15] save(filename::String, fig::Figure)
    @ Makie C:\Users\username\.julia\packages\Makie\VRavR\src\display.jl:302
 [16] top-level scope
    @ REPL[3]:10
Some type information was truncated. Use `show(err)` to see complete types.

Fixed the colour issue, but the polygons seem to have some jagged edges which don’t look as nice as lines. I think I will just smooth out my original data around the segment endpoints using interpolations, and then find a way to stretch the individual segments a tiny bit so that they overlap ever so slightly…

edit: any idea where in makie code the line is split up into segments? I’d like to modify how it does that

If you see that you’re hitting the mesh drawing which uses patches that are always rasterized without antialiasing. You probably tried using poly with array colors I guess, that would make sense. You’d have to create the polygons in the CairoMakie backend when line drawing is called here