First off, +1 to @JonSpring—this is just an expansion of the idea at the end of their answer. If you make an sf
object, you can easily get the intersections of polygons. What you end up plotting isn't the circles themselves, but the polygons that come from splitting apart the intersecting pieces.
Starting from your grid, make a point for each row, convert that to a sf
data frame, then take the buffer of the points at the radius given in the column r
. This turns each point into a circle centered at the point's coordinates, and is flexible for different radii. Between the 3 circles are 6 intersecting polygons, as shown in the result.
library(dplyr)
library(sf)
library(ggplot2)
library(ggforce)
grid_df <- data.frame(x = c(1:2, 2.5), y = rep(1,3), r = 1)
grid_sf <- grid_df %>%
mutate(geometry = purrr::map2(x, y, ~st_point(c(.x, .y)))) %>%
st_as_sf() %>%
st_buffer(dist = .$r, nQuadSegs = 60) %>%
st_intersection()
grid_sf
#> Simple feature collection with 6 features and 5 fields
#> geometry type: GEOMETRY
#> dimension: XY
#> bbox: xmin: 0 ymin: 0 xmax: 3.5 ymax: 2
#> epsg (SRID): NA
#> proj4string: NA
#> x y r n.overlaps origins geometry
#> 1 1.0 1 1 1 1 POLYGON ((1.5 0.1339746, 1....
#> 1.1 1.0 1 1 2 1, 2 POLYGON ((1.75 0.3386862, 1...
#> 2 2.0 1 1 1 2 MULTIPOLYGON (((2.258819 0....
#> 1.2 1.0 1 1 3 1, 2, 3 POLYGON ((2 1, 1.999657 0.9...
#> 2.1 2.0 1 1 2 2, 3 POLYGON ((3 1, 2.999657 0.9...
#> 3 2.5 1 1 1 3 MULTIPOLYGON (((3.5 1, 3.49...
Use that n.overlaps
column that comes from st_intersection
to assign alpha. By default, alpha will scale from 0 to 1, but I figure you don't actually want a 0 alpha for the outer, non-overlapped parts of circles, so I scale it to get a minimum alpha.
alpha_range <- range(grid_sf$n.overlaps) / max(grid_sf$n.overlaps)
grid_sf %>%
ggplot() +
geom_sf(aes(alpha = n.overlaps), fill = "black") +
scale_alpha(range = alpha_range)
Just to expand a bit further and make the different polygons a bit more clear, take a look with a discrete fill scale instead of alpha:
grid_sf %>%
ggplot() +
geom_sf(aes(fill = as.factor(n.overlaps))) +
scale_fill_brewer(palette = "YlGnBu")