Сначала вы должны вычислить, какие сегменты линии разреза принадлежат внутренним частям вашего исходного многоугольника. Это классическая проблема, и ее решение простое. Учитывая, что ваши точки c1, c2, c3 ... c6
расположены вдоль линии именно в этом порядке, сегменты c1-c2
, c3-c4
и т. Д. Всегда будут принадлежать внутренним элементам многоугольника (*).
Теперь мы можем построить простой рекурсивный алгоритм вырезания многоугольников. Учитывая ваш большой входной массив, {a, c1, b, c4, c, c5, d, c6, e, c3, f, c2}, начните с любой точки многоугольника, например, b
; добавить его в массив result
. Пройдите по входному массиву вперед. Если вы столкнетесь
- обычный узел многоугольника, поместите его в массив
result
.
ck
узел, где k
нечетно, найдите c(k+1)
и продолжайте движение с его позиции.
ck
узел, где k
четное, найдите c(k-1)
, перейдите на его позицию и продолжайте движение вперед.
В последних двух случаях добавьте эти узлы в том порядке, в котором они встречались, в массив result
. Добавьте узел ck
в набор cut
и добавьте еще один узел (c(k+1)
или c(k-1)
, в зависимости от того, что у вас есть) в глобальный набор done
.
Если вам нужно выйти за пределы последнего элемента, перейдите к первому элементу входного массива.
Рано или поздно вы встретите начальный узел, от которого переходили. Теперь в массиве result
у вас есть вырезанный многоугольник. Помни это. Повторите процедуру рекурсивно, начиная с позиции каждого узла, который принадлежит набору 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
;
done={c3;c1;c4;c6;c2}
, начиная с c5
(рекурсия с 2). После этого прохода вы получите result=[c5,d,c6]
, cut={c5}
, done+={c6}
; Не возвращайтесь к c5
, так как он установлен done
;
Вуаля - у вас есть 4 нужных полигона.
(*) Обратите внимание, что для этого требуется более «математическое» представление линии. Например, если одна из вершин многоугольника находится на линии, вершина должна быть удвоена, т. Е. Если c
точка была немного ближе к правой стороне и на красной линии, на линии было бы [c1, c2, c3, c, c, c6]
точек, а многоугольник массив будет [a, c1, b, c, c, c, d, c6, e, c3, f, c2]
.
Иногда (не в этом примере) это может привести к вырезанию «пустых» полигонов, например [a, a, a]
. Если они вам не нужны, вы можете устранить их на поздних этапах. Во всяком случае, это вычислительная геометрия с огромным количеством граничных случаев. Я не могу включить их все в один ответ ...
person
P Shved
schedule
21.11.2009