r-lib/ragg

Issues with geom_tile()

Closed this issue · 9 comments

Hi,

Lately, I have had issues using ragg (last version) with geom_tile(). I am not sure where it comes from, but using png_cairo on windows doesn't provoke this strange pattern, which I guess come from "colour".

library(elevatr)
library(tidyverse)
library(raster)
library(ragg)

data(lake)

loc_df <- data.frame(x = runif(6,min=sp::bbox(lake)[1,1], 
                               max=sp::bbox(lake)[1,2]),
                     y = runif(6,min=sp::bbox(lake)[2,1], 
                               max=sp::bbox(lake)[2,2]))
# Example for PROJ > 5.2.0
r <- get_elev_raster(locations = loc_df, prj = sp::wkt(lake) , z=10)

r_xy <- as.data.frame(r, xy = TRUE, na.rm = TRUE)
names(r_xy)[3] <- "elev"

# plot
g <- ggplot(r_xy, 
            aes(x, y, fill = elev)) +
      geom_tile() +
      theme_void()

#ragg 
agg_png("tile_ragg.png", 
        width = 5, 
        height = 5, 
        res = 300,
        unit = "in")
print(g)
dev.off()

#png
png("tile_png.png", 
        width = 5, 
        height = 5, 
        res = 300,
        unit = "in",
        type = "cairo-png")
print(g)
dev.off()

RAGG
tile_ragg

PNG
tile_png

My session info is:

> sessionInfo()
R version 4.1.2 (2021-11-01)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 22000)

Matrix products: default

locale:
[1] LC_COLLATE=Spanish_Spain.1252  LC_CTYPE=Spanish_Spain.1252   
[3] LC_MONETARY=Spanish_Spain.1252 LC_NUMERIC=C                  
[5] LC_TIME=Spanish_Spain.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods  
[7] base     

loaded via a namespace (and not attached):
[1] compiler_4.1.2    cli_3.1.1         tools_4.1.2      
[4] sessioninfo_1.2.2

A possible solution could be defining color = after_scale(fill) in aes(), but I am not sure if this is really wanted.

@thomasp85 have you seen this issue? Is this correct? Thank you!

Could this also comes from ragg applying anti-aliasing fill? Have seen similar artefacts being created from many small polygons from geom_stars (linked in issue: r-spatial/stars#573 )

Yes, this is due to anti-aliasing. I acknowledge the issues in these very specific cases that applying AA can have but don't have a fantastic solution for it other than using the default device. Removing AA from fill is def not the right general solution as it degrades the quality in every other situation

But if I understand correctly also cairo-png uses anti-aliasing, right? Also, this issue started with an update on ragg at the end of last year. In the case of cairo I don't get the artefacts.

No, the Cairo devices doesn't apply antialiasing to fill, which is siding with your use case at the expense of plotting quality everywhere else. I'm afraid there is no silver bullet for this at the moment but thankfully you can always use the default device when needing it for these plots

Until that silver bullet appears (?!), and as alternative to switching graphics drivers, could there be a optional setting for ragg that would switch off anti-aliasing for fill for those cases where it is needed, but where you still want access to other ragg advantages?

For example:-

ragg::options(fill_antialias=FALSE)
ggplot() + geom_tile(data=raster,mapping=aes(fill=category),col=NA) 
ragg:options(fill_antialias=TRUE)

Thanks!

While I understand the intent of this idea there is nothing simple about adding this in a way that doesn't impede the performance or quality of the graphic devices in ragg in general. While I won't say that this will never see the light of day you should not wait out for it and rather switch back to using png()

One small tweak you can make to avoid this issue while remaining in ragg is to add a thin border to all tiles with the same color

ggplot(r_xy, 
            aes(x, y, fill = elev, color = elev), linewidth = 0.1) +
    geom_tile() +
    theme_void()

or use geom_raster() which really is the correct way to plot such data:

ggplot(r_xy, 
            aes(x, y, fill = elev)) +
    geom_raster() +
    theme_void()