I have a spatial object (say a Multipolygon
in sf
or a SpatialPolygons
in sp
) and I want to find all the possible permutations of non-overlapping features. Here are some diagrams that illustrate what I am after. Let's say I have the following polygons.
library(sf)
# points
a <- st_as_sf(data.frame(lon = c(1,2,3.5,3,6), lat = c(0,1,0,1.5,-3)), coords = c('lon', 'lat'))
# circles
b <- st_buffer(a, 1)
# colors
cols = c('grey', 'red', 'green', 'yellow', 'blue')
cols = adjustcolor(cols, alpha.f = .5)
# plot
plot(b, col = cols)
I am after a routine that would create the following 3 objects whose plots would look like:
Ideally, the routine would also allow for a threshold on the intersection of polygons.
I think whatever routine I could write myself would take prohibitively long even for moderate-sized objects (say, 150 polygons, yielding lots of possible combinations). I was hoping that someone have already figured this problem out.
M <- st_overlaps(b, sparse = FALSE) * 1
(M <- 1 - M)
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 0 1 1 1
# [2,] 0 1 0 0 1
# [3,] 1 0 1 0 1
# [4,] 1 0 0 1 1
# [5,] 1 1 1 1 1
colnames(M) <- c('grey', 'red', 'green', 'yellow', 'blue')
library(igraph)
A <- graph_from_adjacency_matrix(M)
max_cliques(A)
# [[1]]
# + 2/5 vertices, named, from dae1f9f:
# [1] red blue
#
# [[2]]
# + 3/5 vertices, named, from dae1f9f:
# [1] grey blue yellow
#
# [[3]]
# + 3/5 vertices, named, from dae1f9f:
# [1] grey blue green
cliques(A)
# ...
# Omitted, 13 cliques in total
First we use st_overlaps
to get a kind of adjacency matrix, M
, where two polygons are adjacent in this graph if they overlap in your data. But actually we are going to need 1 - M
, where two polygons are adjacent in this new graph if they don't overlap. That's useful because what you are looking for then corresponds to (maximal) cliques in this graph:
cliques
find all complete subgraphs in the input graph, obeying the size limitations given in the min and max arguments.
max_cliques
finds all maximal cliques in the input graph. A clique in maximal if it cannot be extended to a larger clique. The largest cliques are always maximal, but a maximal clique is not neccessarily the largest.
In this case cliques are sets of polygons where none of the polygons overlap with any of the rest.
Also, as to apply this to sp
objects, you only need to compute a corresponding M
. I believe that over
helps with that.
Bonus
As to add the possibility for thresholds, we just need to recompute M
.
aux <- function(x) if (length(x) == 1) x else 0
M <- matrix(1, nrow(a), nrow(a))
for(i in 1:nrow(a))
for(j in 1:nrow(a))
M[i, j] <- aux(st_area(st_intersection(b[i, 1], b[j, 1])))
diag(M) <- 0
Then, for instance, if we count two polygons as intersecting only if the intersection area is greater than 0.2, we run
M <- 1 * (M > 0.2) # Getting threshold-overlaps
M <- 1 - M # The needed adjacency matrix
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.