ragg anti-aliasing for touching polygons

92 Views Asked by At

I'm rendering a series of touching polygons with grid and saving this to a png file using the ragg package. Whenever I do this with the ragg package, I get a white grid atop my polygons where they touch.

I assume this to be an anti-aliasing artefact, but is there a way to get ragg to render the graphic below as a solid mass of blue? My actual case isn't monochrome, but it shows the artefact better.

library(grid)
library(scales)
library(ragg)

# Center of rectangles
grid <- expand.grid(x = 1:10, y = 1:10)

# Centers to xmin/xmax/ymin/ymax
poly <- cbind(
  c(grid$x - 0.5, grid$x + 0.5, grid$x + 0.5, grid$x - 0.5),
  c(grid$y - 0.5, grid$y - 0.5, grid$y + 0.5, grid$y + 0.5)
)

# Rotate rectangles
angle <- 30 * pi / 180
rot <- matrix(c(cos(angle), sin(angle), -sin(angle), cos(angle)), 2)
poly <- t(tcrossprod(rot, poly))

# Make grob
grob <- polygonGrob(
  x = rescale(poly[, 1]),
  y = rescale(poly[, 2]),
  id = rep(seq_len(nrow(grid)), 4),
  gp = gpar(
    fill = "dodgerblue",
    col = NA
  )
)

# Save with ragg
agg_png("test.png")
grid.newpage(); grid.draw(grob)
dev.off()
#> png 
#>   2

Created on 2021-03-25 by the reprex package (v1.0.0)

enter image description here

Note: The same happens for the cairo png device. The default png() device renders a solid mass of blue but has terrible anti-aliasing on the outermost edges.

1

There are 1 best solutions below

0
On

One possible workaround is to set the colour of polygon borders to the same as the fill, with a thin line width -- as suggested by the author/maintainer of ragg. Here's the example solution from the relevant GitHub issue

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)
#> Mosaicing & Projecting
#> Note: Elevation units are in meters.

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

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

Created on 2023-08-11 with reprex v2.0.2