Отсечение отрезков и многоугольников
Алгоритм Цируса-Бека
Алгоритм Цируса-Бека [25] отсекает отрезок P1P2, используя его параметрическое представление:
( 5.1) |
Данный алгоритм применим не только в случае отсечения прямоугольником со сторонами, параллельными осям координат, но и в случае, если отсекаемая область ограничена любым выпуклым многоугольником.
Рассмотрим отдельно ребро Ei отсекающего многоугольника. Нормаль к нему ориентируем во внешнюю сторону отсекающего многоугольника, для этого удобно считать, что точки отсекающего контура обходятся против часовой стрелки; тогда если ребро - это , то нормаль NEi будет пропорциональна (yEi2-yEi1, xEi1- xEi2), см. рис. 5.3.
Тогда область, отсекаемая прямой, на которой лежит ребро (обозначим ее Li ), соответствует точкам P, для которых1Здесь и далее (x, y) - скалярное произведение векторов x и y. (P-PEi),NEi) > 0, где PEi - любая точка на ребре Ei. Точка пересечения прямой, на которой лежит отрезок с отсекающей прямой Li, находится из уравнения
((Ps(t) - PEi),NEi) = 0.
Разрешая его, получаем, что
( 5.2) |
в том случае, если . Если же ((P2 - P1),NEi) = 0 это означает, что отсекаемый отрезок параллелен Li и не существует единственной точки их пересечения. Такие случаи алгоритм игнорирует.
Для алгоритма Цируса-Бека также важно в каком направлении (внутрь отсекающего многоугольника или из него) проходит точка при движении по отрезку от P1 к P2, т.е. при изменении t от 0 до 1. Это определяется знаком ((P2 - P1),NEi). Будем обозначать такие точки пересечения как:
После того как рассчитаны координаты t для всех возможных пересечений с прямыми Li, следует выбрать максимальную координату из потенциально входящих пересечений tВхMax и минимальную из потенциально выходящих tВыхMin. Если прямая, на которой лежит отрезок P1P2, пересекает отсекающий многоугольник, то tВхMax < tВыхMin. В этом случае, если пересечение непусто, то Ps(t1)Ps(t2) будет искомым отсеченным отрезком. В противном случае отрезок полностью лежит вне отсекаемой области.
Вычислить NEi и взять PEi = PEi1 для каждого ребра. Отсечь(отрезок P1P2) { if(P1 == P2) отсечь как точку; else { D = P2 - P1; t_Вх = 0; t_Вых = 1; foreach( ребро Ei из отсекающего многоугольника ) { dp = (D,NEi); if( dp != 0 ) // случай dp == 0 игнорируется {
if( dp < 0 ) { if( t > t_Вх ) t_Вх = t; } else // dp > 0 { if( t < t_Вых ) t_Вых = t; } } } if( t_Вх < t_Вых ) return отрезок Ps(t_Вх)Ps(t_Вых); else return ' } }Листинг 5.3. Алгоритм Цируса-Бека
Алгоритм Цируса-Бека также может быть обобщен до случая отсечения отрезка произвольным выпуклым многогранником в трехмерном пространстве.