Московский государственный университет имени М.В.Ломоносова
Опубликован: 23.04.2007 | Доступ: свободный | Студентов: 3308 / 461 | Оценка: 4.18 / 3.71 | Длительность: 17:54:00
ISBN: 978-5-9556-0098-7
Специальности: Программист
Лекция 5:

Отсечение отрезков и многоугольников

< Лекция 4 || Лекция 5: 1234 || Лекция 6 >

Алгоритм Цируса-Бека

Алгоритм Цируса-Бека [25] отсекает отрезок P1P2, используя его параметрическое представление:

P_s(t) = P_1 + (P_2 - P_1)\cdot t ,   t \in [0, 1]. ( 5.1)

Данный алгоритм применим не только в случае отсечения прямоугольником со сторонами, параллельными осям координат, но и в случае, если отсекаемая область ограничена любым выпуклым многоугольником.

Рассмотрим отдельно ребро Ei отсекающего многоугольника. Нормаль к нему ориентируем во внешнюю сторону отсекающего многоугольника, для этого удобно считать, что точки отсекающего контура обходятся против часовой стрелки; тогда если ребро - это \overrightarrow{P_{Ei1}P_{Ei2}}, то нормаль 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.

Разрешая его, получаем, что

t = -\frac{((P_1 - P_{Ei}),N_{Ei})}{((P_2 - P_1),N_{Ei})} ( 5.2)

в том случае, если (P_2 - P_1,N_{Ei}) \ne 0. Если же ((P2 - P1),NEi) = 0 это означает, что отсекаемый отрезок параллелен Li и не существует единственной точки их пересечения. Такие случаи алгоритм игнорирует.

Пересечение отрезка с ребром.

Рис. 5.3. Пересечение отрезка с ребром.

Для алгоритма Цируса-Бека также важно в каком направлении (внутрь отсекающего многоугольника или из него) проходит точка при движении по отрезку от P1 к P2, т.е. при изменении t от 0 до 1. Это определяется знаком ((P2 - P1),NEi). Будем обозначать такие точки пересечения как:

Потенциально входящие (ПВх): ((P2 - P1),NEi) < 0
Потенциально выходящие (ПВых): ((P2 - P1,NEi) > 0

После того как рассчитаны координаты t для всех возможных пересечений с прямыми Li, следует выбрать максимальную координату из потенциально входящих пересечений tВхMax и минимальную из потенциально выходящих tВыхMin. Если прямая, на которой лежит отрезок P1P2, пересекает отсекающий многоугольник, то tВхMax < tВыхMin. В этом случае, если пересечение [t_1, t_2] = [t_{ВхMax}, t_{ВыхMin}] \cap [0, 1] непусто, то Ps(t1)Ps(t2) будет искомым отсеченным отрезком. В противном случае отрезок полностью лежит вне отсекаемой области.

Возможные случаи пересечений в алгоритме Цируса-Бека.

Рис. 5.4. Возможные случаи пересечений в алгоритме Цируса-Бека.
Вычислить 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 игнорируется
              {
$t = -\frac{((P_1 - P_{Ei}), N_{Ei})}{dp};$
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. Алгоритм Цируса-Бека

Алгоритм Цируса-Бека также может быть обобщен до случая отсечения отрезка произвольным выпуклым многогранником в трехмерном пространстве.

< Лекция 4 || Лекция 5: 1234 || Лекция 6 >