Неперекрывающиеся невыпуклые многоугольники

Предположим, что на плоскости набор из n случайно распределенных невыпуклых многоугольников P={Pi}, n = |P|, некоторые из них перекрываются (примерно 50% перекрывают друг друга).

1] Переместите полигоны так, чтобы не происходило перекрытие.

2] Допускаются только "небольшие" сдвиги (относительное положение объектов Pi сохраняется в максимально возможной степени).

На мой взгляд, проблема NP-сложная. Я попробовал несколько подходов (стохастическая оптимизация, минимизирующая область перекрытия + сдвиги), перемещение все в одном (случайное встряхивание), добавление вне выпуклой оболочки (хорошо работает для выпуклых многоугольников, но для невыпуклых страдает от больших сдвигов),...

Наиболее перспективным является инкрементальный метод с использованием простой эвристики (движение в 2 направлениях).

0] Compute minimum bounding boxes (MBB) for all Pi. Sort Pi by area.
1] Add a Pi to the solution S and check for overlaps
    1.a] Test intersection  Pi vs. all Pj in S.
    1.b] If MBB(Pj) vs. MBB(Pi) overlap, check the polygons Pi vs. Pj: 
        1.b.1] If Pi, Pj overlap, moving Pi perpendicular to Pj (left, right) by s may help
        1.b.2] Suppose Pi1=Pi(sl), Pi2=Pi(sr) to be shifted Pi, shifts sl=s, sr=-s
        1.b.3] Check, which direction is more perspective:
        1.b.4] While intersections Pi1 vs. Pj exist //Left
           1.b.4.a] Preselect collisions Pi1 vs. all Pj by MBB.
           1.b.4.b] If MBB(Pi1) and MBB(Pj) overlap, check Pi1 vs. Pj
           1.b.4.c] If overlap found sl = sl + s;
           1.b.4.c] Shift Pi1(sl);
        1.b.5] While intersections Pi1 vs. Pj exist //Right
           1.b.5.a] Preselect collisions Pi1 vs.all Pj by MBB.
           1.b.5.b] If MBB(Pi1) and MBB(Pj) overlap, check Pi1 vs. Pj
           1.b.5.c] If overlap found sr = sr + s;
           1.b.5.d] Shift Pi2(sr);
        1.b.6] Assign Pi = Pi1 or Pi = Pi2 (the faster).

К сожалению, для больших n (тысяч) инкрементный метод медленный. Есть ли возможное улучшение скорости или существует лучший метод? Больше всего усилий затрачивается на ненужные смены и проверки...

Тесселяция многоугольников Вороного может помочь с движением многоугольников внутри ячеек... Мы также можем проверить, на какие ячейки Вороного влияют, добавив новую ячейку (генератор представлен многоугольником)... Возможно, движение можно вычислить как средний вектор пироцентриков и центроидов многоугольников в пораженных клетках.

Большое спасибо за Вашу помощь.

1 ответ

Решение

Выберите одну вершину каждого многоугольника, убедившись, что ни одна из выбранных не совпадает. (Если это невозможно, у вас проблемы.) Определите самый плотный ограничивающий квадрат для всех многоугольников и разделите сторону самого большого квадрата на самое короткое расстояние по горизонтали / вертикали между выбранными вершинами.

Умножьте координаты всех выбранных вершин на этот коэффициент и переведите остальные вершины соответствующим образом (без масштабирования). Это разделит все полигоны, оставляя их расположение очень похожим.

Возможно, это решение будет слишком "редким" на ваш вкус; его можно использовать в качестве отправной точки для переупаковки без повторного наложения.

Другие вопросы по тегам