Это проблема раскраски графа .
Напомним, что раскраска графа - это присвоение цвета вершинам графа таким образом, что никакие две вершины, которые имеют общее ребро, также не будут иметь одинаковый цвет. В частности, (абстрактными) вершинами графа являются многоугольники. Две вершины связаны с (ненаправленным) ребром, когда они пересекаются (как многоугольники). Если мы возьмем какое-либо решение проблемы - которое представляет собой последовательность (скажем, k ) непересекающихся наборов многоугольников - и назначим уникальный цвет каждому набору в последовательности, то мы получим k- раскраску графа. , Желательно найти маленький к .
Эта проблема довольно сложна и остается нерешенной для произвольных графов. Рассмотрим примерное решение, которое просто закодировать. Последовательный алгоритм должен сделать. Алгоритм Уэлша-Пауэлла является жадным решением, основанным на нисходящем упорядочении вершин по степени. В переводе на язык исходных полигонов, сначала отсортируйте полигоны в порядке убывания числа других полигонов, которые они перекрывают. Работая по порядку, дайте первому многоугольнику начальный цвет. На каждом последующем шаге попробуйте закрасить следующий многоугольник существующим цветом: выберите цвет, который не соответствуетуже используется любым из соседей этого многоугольника. (Есть много способов выбрать один из доступных цветов; попробуйте тот, который был наименее использован, или выберите один случайным образом.) Если следующий полигон не может быть окрашен существующим цветом, создайте новый цвет и закрасьте его этим.
Как только вы добились раскраски с небольшим количеством цветов, выполните зональную статистику цвет за цветом: по построению вы гарантируете, что никакие два многоугольника данного цвета не перекрываются.
Вот пример кода в R
. (Код Python не будет сильно отличаться.) Во-первых, мы описываем перекрытия между семью показанными полигонами.
edges <- matrix(c(1,2, 2,3, 3,4, 4,5, 5,1, 2,6, 4,6, 4,7, 5,7, 1,7), ncol=2, byrow=TRUE)
То есть полигоны 1 и 2 перекрываются, как и полигоны 2 и 3, 3 и 4, ..., 1 и 7.
Сортировка вершин по убыванию:
vertices <- unique(as.vector(edges))
neighbors <- function(i) union(edges[edges[, 1]==i,2], edges[edges[, 2]==i,1])
nbrhoods <- sapply(vertices, neighbors)
degrees <- sapply(nbrhoods, length)
v <- vertices[rev(order(degrees))]
Алгоритм последовательной раскраски (грубый) использует самый ранний доступный цвет, еще не использованный ни одним перекрывающимся многоугольником:
color <- function(i) {
n <- neighbors(i)
candidate <- min(setdiff(1:color.next, colors[n]))
if (candidate==color.next) color.next <<- color.next+1
colors[i] <<- candidate
}
Инициализируйте структуры данных ( colors
и color.next
) и примените алгоритм:
colors <- rep(0, length(vertices))
color.next <- 1
temp <- sapply(v, color)
Разделите полигоны на группы по цвету:
split(vertices, colors)
Вывод в этом примере использует четыре цвета:
$`1`
[1] 2 4
$`2`
[1] 3 6 7
$`3`
[1] 5
$`4`
[1] 1
Он разделил полигоны на четыре непересекающиеся группы. В этом случае решение не является оптимальным ({{3,6,5}, {2,4}, {1,7}} является трехцветной для этого графа). В целом, решение, которое оно получает, не должно быть слишком плохим.