Ответ 1
Сначала вы должны рассчитать, какие сегменты линии разреза принадлежат внутренним элементам вашего оригинального многоугольника. Это классическая проблема, и ее решение прост. Учитывая, что ваши точки c1, c2, c3 ... c6
выложены вдоль линии точно в этом порядке, тогда сегменты c1-c2
, c3-c4
и т.д. Всегда будут принадлежать внутренним многоугольникам (*).
Теперь мы можем построить простой рекурсивный алгоритм для разрезания многоугольников. Учитывая ваш большой входной массив, {a, c1, b, c4, c, c5, d, c6, e, c3, f, c2} начинаются с любой точки полигона, например, b
; добавьте его в массив result
. Переместите входной массив вперед. Если вы столкнулись с
- обычный многоугольник node, нажмите его в массив
result
. -
ck
node, гдеk
нечетно, найдитеc(k+1)
и продолжайте перемещаться от его положения. -
ck
node, гдеk
равно, ищитеc(k-1)
, переходите к его положению и тем не менее продолжайте движение вперед.
Для последних двух случаев добавьте эти узлы в том порядке, в котором вы их встретили, в массив result
. Добавьте ck
node, чтобы установить cut
, и добавьте еще один node (c(k+1)
или c(k-1)
, в зависимости от того, что у вас есть) в глобальный набор done
.
Если вам нужно выйти за последний элемент, подключитесь к первому элементу входного массива.
Рано или поздно вы столкнетесь с начальным node, с которым вы проходили. Теперь в массиве result
у вас есть полигон, который вы разрезали. Запомни. Повторите процедуру рекурсивно, начиная с позиции каждого node, принадлежащего cut
, и не относится к глобальному набору done
.
Это решение, как я его вижу. Но это вычислительная геометрия, поэтому она может оказаться немного сложнее, чем кажется.
В нашем примере начинаем с b
:
-
done={}
, начните сb
. После первого прохода вы получитеresult=[b,c4,c3,f,c2,c1]
,cut={c4,c2}
,done={c3,c1}
; Перезапустите узлыc4
иc2
. -
done={c3;c1}
, начните сc4
(рекурсия из 1). После этого прохода вы получитеresult=[c4,c,c5,c6,e,c3,c4]
,cut={c5,c3}
,done+={c6,c4}
; Перезапуститеc5
. -
done={c3;c1;c4;c6}
, начните сc2
(рекурсия из 1). После этого прохода вы получитеresult=[c2,a,c1]
,cut={c1}
,done+={c2}
; Не возвращайте значениеc1
, так как оно находится вdone
set; -
done={c3;c1;c4;c6;c2}
, начните сc5
(рекурсия из 2). После этого прохода вы получитеresult=[c5,d,c6]
,cut={c5}
,done+={c6}
; Не возвращайтесь кc5
, так как он находится вdone
set;
Voila - вы получаете 4 многоугольника, которые вам нужны.
(*) Обратите внимание, что для этого требуется более "математическое" представление линии. Например, если одна из многоугольных вершин находится на линии, вершина должна быть удвоена, т.е. Если точка c
была немного ближе к правой стороне, а на красной линии линия имела бы [c1, c2, c3, c, c, c6]
точки на ней, а массив многоугольников будет [a, c1, b, c, c, c, d, c6, e, c3, f, c2]
.
Иногда (не в этом примере) это может привести к разрезанию "пустых" полигонов, таких как [a, a, a]
. Если они вам не нужны, вы можете устранить их на поздних этапах. Во всяком случае, это вычислительная геометрия с огромным количеством пограничных случаев. Я не могу включить их всех в один ответ...