Список необработанных (непустых) пересечений вместе с индексами полигонов, из которых было создано пересечение, сохраняется. Первоначально он заполнен отдельными полигонами. Всегда пересечение с большинством многоугольников и наименьшим максимальным индексом задействованных многоугольников убирается и пересекается со всеми многоугольниками с более высокими индексами (чтобы не смотреть снова и снова на одно и то же подмножество многоугольников). Это позволяет эффективно обрезать:
- если число полигонов, участвующих в текущем обработанном пересечении, и оставшиеся индексы не превышают наибольшее количество полигонов, чтобы иметь непустое пересечение, нам больше не нужно преследовать это пересечение.
Вот алгоритм в Python-подобных обозначениях:
def findIntersectionFromMostMembers(polygons):
unprocessedIntersections = [(polygon, {i}) for i, polygon in enumerate(polygons)]
unprocessedIntersections.reverse() # make polygon_0 the last element
intersectionFromMostMembers, indicesMost = (polygons[0], {0})
while len(unprocessedIntersections) > 0:
# last element has most involved polygons and least maximal polygon index
# -> highest chance of being extended to best intersection
intersection, indices = unprocessedIntersections.pop() # take out unprocessed intersection from most polygons
if len(indices) + n - max(indices) - 1 <= len(indicesMost):
continue # pruning 1: this intersection cannot beat best found solution so far
for i in range(max(indices)+1, n): # pruning 2: only look at polyong with higher indices
intersection1 = intersection.intersect(polygons[i])
if not intersection1.isEmpty(): # pruning 3: empty intersections do not need to be considered any further
unprocessedIntersections.insertSorted(intersection1, indices.union({i}), key = lambda(t: len(t[1]), -max(t[1])))
if len(indices)+1 > len(indicesMost):
intersectionFromMostMembers, indicesMost = (intersection1, indices.union({i}))
return intersectionFromMostMembers, indicesMost
Производительность сильно зависит от того, сколько полигонов в среднем имеют общую область. Чем меньше (<< n
) многоугольников имеют общие области, тем эффективнее обрезка 3. Чем больше у многоугольников общих областей, тем эффективнее обрезка 1. Обрезка 2 гарантирует, что никакое подмножество многоугольников не рассматривается дважды. Худший сценарий, по-видимому, заключается в том, что постоянная доля n
(например, n/2
) полигонов имеет некоторую общую область. До n=40
этот алгоритм завершается за разумное время (через несколько секунд или самое большее за несколько минут). Если непустое пересечение из большинства многоугольников включает только несколько (любая константа << n
) многоугольников, гораздо большие наборы многоугольников могут быть обработаны за разумное время.