I struggle to understand (and control) the blending of alphas - unfortunately, alpha values don't simply "add up" (0.5 + 0.5 is not 1). But how could I achieve that?
The aim is to define the (absolute) grey value of overlapping areas relative to the total number of observations. See example below.
I tried to set scale_alpha(range = c(0,1))
to no avail, maybe I did not use it correctly.
library(ggplot2)
library(ggforce)
grid_df = data.frame(x = c(1:2, 2.5), y = rep(1,3), r = 1)
ggplot()+
geom_circle(data = grid_df, mapping = aes(x0 = x, y0 = y, r = r), alpha = 0.33, fill = 'black') +
coord_fixed()
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 columnr
. 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.Use that
n.overlaps
column that comes fromst_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.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:
Alpha can be added using the following approach (https://en.wikipedia.org/wiki/Alpha_compositing#Alpha_blending)
The alpha of two merged shapes is calculated as follows:
A(out) = A(src) + A(dst) * 1-A(src)
Hence, for A(src) = A(dst) = 0.33, we get:
And if we have three shapes, with A = 0.33, we induce:
I could go on about which values will result in 1 when adding 2 or 3 shapes together, but the most useful comment is that alphas are not combined in an additive way.
Adding to @MKBakker's answer, one could use a function to predict the resulting alpha from any number of layers and alpha values:
This makes it easier to see that alpha asymptotically approaches 1 with more layers.
If one presumes that 0.99 is "close enough," you need to use 0.8 to get there with three layers
EDIT: Added chart of results
We can see what results we'd get from a range of alphas and layers:
And we can also see how much alpha we need to pass a threshold of combined opacity, given each number of layers. For instance, here's how much alpha you need to reach 0.99 total opacity for a given number of layers. For 5 layers, you need
alpha = 0.61
, for instance.All this to say that I don't think there is a simple implementation to get what you're looking for. If you want 100% dark in the overlapped area, you might try these approaches:
image manipulation after the fact (perhaps doable using
imagemagick
) to apply a brightness curve to make the dark areas 100% black and make the others scale to the darkness levels you expect.convert the graph to an
sf
object and analyze the shapes to somehow count how many shapes are overlapping at any given point. You could then manually map those to the darkness levels you want.