Анализ комбинаторных
алгоритмов
Лекция № 16
Вычислительная геометрия
Аффинные преобразования
 Если на плоскости задана прямоугольная
система координат, над любой точкой
заданной координатами x,y можно
осуществлять следующие преобразования:
 Поворот (на угол ϕ)описывается формулами:
X* = x cos ϕ - y sin ϕ, Y* = x sin ϕ + y cos ϕ.
 Растяжение (сжатие) вдоль координатных осей:
X* = αx, Y* = δy, α>0, δ>0.
 Отражение (относительно оси абсцисс):
X* = x, Y* = -y.
 Перенос:
X* = x + λ, Y* = y + µ.
Аффинные преобразования
М
М*
М
М*
М*
М
М
М*
Аффинные преобразования
Все перечисленные преобразования
можно записать в общем виде:
X* = αx + βy + λ,
Y* = γx + δy + µ.
В матричной записи:
( )










=
1
0
0
*)1(1**
µλ
δβ
γα
yxyx
Аффинные преобразования
[ ]










−=
100
0cossin
0sincos
ϕϕ
ϕϕ
R










=
100
00
00
][ δ
α
D










−=
100
010
001
][M










=
1
010
001
][
µλ
T
Матрица вращения Матрица растяжения
Матрица отражения Матрица переноса
Термины и определения
 Выпуклой комбинацией двух точек p1
(x1,y1), p2(x2,y2) называется любая точка
p3(x3,y3), для которой
x3 = αx1+(1- α)x2, y3 = αy1+(1- α)y2
 Совокупность всех выпуклых комбинаций
для точек p1, p2 называют отрезком p1p2.
 Если порядок точек p1 и p2 имеет значение,
то отрезок направленный.
 Направленный отрезок у которого p1 = (0,0)
(начало координат) называется вектором.
Термины и определения
 Под векторным произведением на
плоскости понимается площадь
параллелограмма, образованного точками
(0,0), p1, p2, p1+p2 = (x1+x2, y1+y2).
1221
21
21
21 det yxyx
yy
xx
pp −=





=×
1221 pppp ×−=×
Направление поворота
 В какую сторону нужно поворачивать вектор
p1,чтобы совместить его с p2 (в смысле
наименьшего угла)?
Если p1 x p2 положительно, то против часовой
стрелки, если отрицательно – то по часовой.
 В какую сторону производится поворот при
движении по ломанной p0p1p2?
Если p1 x p2 положительно, то направо, если
отрицательно – то налево, если равно 0, то либо
не поворачиваем, либо поворачиваем назад.
Пересечение отрезков
 Определение пересечения отрезков
происходит в два этапа.
 На первом этапе производится начальный
тест: если ограничивающие
прямоугольники отрезков не имеют общих
точек, то отрезки не пересекаются.
 Ограничивающим прямоугольником
называется наименьший из прямоугольников
со сторонами параллельными осям
координат, содержащих данную фигуру.
(x2≥x3)Λ(x4≥x1)Λ(y2≥y3)Λ(y4≥y1)
Пересечение отрезков
 Если ограничивающие прямоугольники
имеют общие точки, то на втором этапе
проверяется пересекается ли каждый из
отрезков прямой, содержащей другой
отрезок.
 С помощью векторных произведений это
проверяется следующим образом:
[(p3-p1) x (p2-p1)] * [(p4-p1) x (p2-p1)] ≤ 0
и
[(p1-p3) x (p4-p3)] * [(p2-p3) x (p4-p3)] ≤ 0
Пересечение отрезков
 Метод движущейся прямой состоит в том,
что воображаемая прямая движется слева
направо мимо рассматриваемых объектов.
 Метод движущейся прямой хранит
следующую информацию:
 Состояние дел у прямой задается
упорядоченным множеством объектов,
пересекаемых движущейся прямой.
 Расписание представляет собой
последовательность моментов времени
(критических точек), в которых состояние может
измениться
Пересечение отрезков
 Состояние дел у прямой хранится как
упорядоченное множество отрезков, с
которым можно выполнять следующие
операции:
 Insert(s) – добавить отрезок
 Delete(s) – удалить отрезок
 Above(s) – указать отрезок располагающийся
непосредственно выше s
 Below(s) – указать отрезок располагающийся
непосредственно ниже s
Пересечение отрезков
AnySegmentIntersect(S){
T = ǿ;
Отсортировать концы отрезков в порядке
возрастания абсцисс (если абсциссы равны,
то по возрастанию ординат)
Проверка совпадений среди концов отрезков
for(каждой точки p из S){
if(p – левый конец отрезка){
Insert(s);
if(Above(s) существует и пересекает s)
||(Below(s) существует и пересекает s)
return TRUE; }
if(p – правый конец отрезка){
if(Above(s) существует)
||(Below(s) существует)||(Above(s)
пересекает Below(s)) return TRUE;
Delete(s);}y
}}
Пересечение отрезков
a
b
c
d
e
f
a a
b
a
c
b
c
b
d
c
b
d
b
e
d
b
e
d
b
f
e
d
f
Отыскание пары ближайших точек
 Данную задачу можно решить используя
метод «разделяй и властвуй».
 Входными данными рекурсивного
алгоритма являются множество точек P и
массивы X и Y, содержащие точки из P. X
отсортирован по абсциссам, Y по
ординатам.
 Если в P находятся только 3 или 2 точки
находим расстояния (и сравниваем их
попарно).
Отыскание пары ближайших точек
 Если |P|>3, находим вертикальную прямую
разделяющую P на два подмножества Pl и
Pr половинного размера. Разделяем
массивы X и Y сохраняя порядок
элементов.
 Выполняем два рекурсивных вызова и
находим пару ближайших точек в Pl и Pr и
расстояния между этими точками δl и δr.
Полагаем δ = min(δl, δr)
Отыскание пары ближайших точек
 Для P парой ближайших точек будет либо
одна из найденных пар в подмножествах,
либо некоторая «приграничная» пара точек.
 Для нахождения «приграничной» пары:
 Создаем Y’, сохранив порядок, с точками
попавшими в приграничную полосу толщиной 2δ
 Для каждой точки из Y’ находим расстояние от
нее до каждой из 7 точек следующих за ней.
Находим наименьшее расстояние δ’ между
точками в приграничной зоне.
Отыскание пары ближайших точек
2 δ
δ δ
δ δ
2 точки
Построение выпуклой оболочки
 Выпуклой оболочкой конечного множества
точек Q (CH(Q)) называется наименьший
выпуклый многоугольник, содержащий все
точки из Q.
 Решение задачи нахождения выпуклой
оболочки важно не только само по себе, но
и как промежуточный этап для многих задач
вычислительной геометрии, например,
двумерной задачи о наиболее удаленных
точках.
Построение выпуклой оболочки
void GrahamScan(Q){
Множество Q отсортировано так, что Q[0]-
точка с наименьшей ординатой, а остальные
расположены в порядке возрастания
полярного угла.
Stack S; S->Push(Q[0]);
S->Push(Q[1]); S->Push(Q[2]);
for(i=3;i<=n;i++){
while(при движении по ломанной
S->NextToTop(), S->Top, Q[i] движение
происходит прямо или направо) S->Pop()
S->Push(Q[i])
}}
Построение выпуклой оболочки
p0
p1
p2
p3
p4
p5
p6
p7 p0
p1
p2
p3
p4
p5
p6
p7
p0
p1
p2
p3
p4
p5
p6
p7 p0
p1
p2
p3
p4
p5
p6
p7
Просмотр Грэхема
Построение выпуклой оболочки
void WrappingScan(Q){
//Q[0] - точка с наименьшей ординатой
//Pmax – точка с наибольшей ординатой
Pmax = GetMinPoint(Q); i=1;
while(Q[i]!=Pmax){ minw = maxint;
for(k=1; k<N; k++){
if(k==i) w = maxint;
else w = CalculatePolarLeft(Q[i],Q[k]);
if(minw>w){p = Q[k]}
} Pop(p); i++;}
while(Q[i]!=Pmax){ minw = maxint;
for(k=1; k<N; k++){
if(k==i) w = maxint;
else w = CalculatePolarRight(Q[i],Q[k]);
if(minw>w){p = Q[k]}
} Pop(p); i++;}
}
Построение выпуклой оболочки
p0
p1
p2
p3
p4
p5
p6
Проход Джарвиса

Лекция 16 Вычислительная геометрия

  • 1.
  • 2.
    Аффинные преобразования  Еслина плоскости задана прямоугольная система координат, над любой точкой заданной координатами x,y можно осуществлять следующие преобразования:  Поворот (на угол ϕ)описывается формулами: X* = x cos ϕ - y sin ϕ, Y* = x sin ϕ + y cos ϕ.  Растяжение (сжатие) вдоль координатных осей: X* = αx, Y* = δy, α>0, δ>0.  Отражение (относительно оси абсцисс): X* = x, Y* = -y.  Перенос: X* = x + λ, Y* = y + µ.
  • 3.
  • 4.
    Аффинные преобразования Все перечисленныепреобразования можно записать в общем виде: X* = αx + βy + λ, Y* = γx + δy + µ. В матричной записи: ( )           = 1 0 0 *)1(1** µλ δβ γα yxyx
  • 5.
    Аффинные преобразования [ ]           −= 100 0cossin 0sincos ϕϕ ϕϕ R           = 100 00 00 ][δ α D           −= 100 010 001 ][M           = 1 010 001 ][ µλ T Матрица вращения Матрица растяжения Матрица отражения Матрица переноса
  • 6.
    Термины и определения Выпуклой комбинацией двух точек p1 (x1,y1), p2(x2,y2) называется любая точка p3(x3,y3), для которой x3 = αx1+(1- α)x2, y3 = αy1+(1- α)y2  Совокупность всех выпуклых комбинаций для точек p1, p2 называют отрезком p1p2.  Если порядок точек p1 и p2 имеет значение, то отрезок направленный.  Направленный отрезок у которого p1 = (0,0) (начало координат) называется вектором.
  • 7.
    Термины и определения Под векторным произведением на плоскости понимается площадь параллелограмма, образованного точками (0,0), p1, p2, p1+p2 = (x1+x2, y1+y2). 1221 21 21 21 det yxyx yy xx pp −=      =× 1221 pppp ×−=×
  • 8.
    Направление поворота  Вкакую сторону нужно поворачивать вектор p1,чтобы совместить его с p2 (в смысле наименьшего угла)? Если p1 x p2 положительно, то против часовой стрелки, если отрицательно – то по часовой.  В какую сторону производится поворот при движении по ломанной p0p1p2? Если p1 x p2 положительно, то направо, если отрицательно – то налево, если равно 0, то либо не поворачиваем, либо поворачиваем назад.
  • 9.
    Пересечение отрезков  Определениепересечения отрезков происходит в два этапа.  На первом этапе производится начальный тест: если ограничивающие прямоугольники отрезков не имеют общих точек, то отрезки не пересекаются.  Ограничивающим прямоугольником называется наименьший из прямоугольников со сторонами параллельными осям координат, содержащих данную фигуру. (x2≥x3)Λ(x4≥x1)Λ(y2≥y3)Λ(y4≥y1)
  • 10.
    Пересечение отрезков  Еслиограничивающие прямоугольники имеют общие точки, то на втором этапе проверяется пересекается ли каждый из отрезков прямой, содержащей другой отрезок.  С помощью векторных произведений это проверяется следующим образом: [(p3-p1) x (p2-p1)] * [(p4-p1) x (p2-p1)] ≤ 0 и [(p1-p3) x (p4-p3)] * [(p2-p3) x (p4-p3)] ≤ 0
  • 11.
    Пересечение отрезков  Методдвижущейся прямой состоит в том, что воображаемая прямая движется слева направо мимо рассматриваемых объектов.  Метод движущейся прямой хранит следующую информацию:  Состояние дел у прямой задается упорядоченным множеством объектов, пересекаемых движущейся прямой.  Расписание представляет собой последовательность моментов времени (критических точек), в которых состояние может измениться
  • 12.
    Пересечение отрезков  Состояниедел у прямой хранится как упорядоченное множество отрезков, с которым можно выполнять следующие операции:  Insert(s) – добавить отрезок  Delete(s) – удалить отрезок  Above(s) – указать отрезок располагающийся непосредственно выше s  Below(s) – указать отрезок располагающийся непосредственно ниже s
  • 13.
    Пересечение отрезков AnySegmentIntersect(S){ T =ǿ; Отсортировать концы отрезков в порядке возрастания абсцисс (если абсциссы равны, то по возрастанию ординат) Проверка совпадений среди концов отрезков for(каждой точки p из S){ if(p – левый конец отрезка){ Insert(s); if(Above(s) существует и пересекает s) ||(Below(s) существует и пересекает s) return TRUE; } if(p – правый конец отрезка){ if(Above(s) существует) ||(Below(s) существует)||(Above(s) пересекает Below(s)) return TRUE; Delete(s);}y }}
  • 14.
  • 15.
    Отыскание пары ближайшихточек  Данную задачу можно решить используя метод «разделяй и властвуй».  Входными данными рекурсивного алгоритма являются множество точек P и массивы X и Y, содержащие точки из P. X отсортирован по абсциссам, Y по ординатам.  Если в P находятся только 3 или 2 точки находим расстояния (и сравниваем их попарно).
  • 16.
    Отыскание пары ближайшихточек  Если |P|>3, находим вертикальную прямую разделяющую P на два подмножества Pl и Pr половинного размера. Разделяем массивы X и Y сохраняя порядок элементов.  Выполняем два рекурсивных вызова и находим пару ближайших точек в Pl и Pr и расстояния между этими точками δl и δr. Полагаем δ = min(δl, δr)
  • 17.
    Отыскание пары ближайшихточек  Для P парой ближайших точек будет либо одна из найденных пар в подмножествах, либо некоторая «приграничная» пара точек.  Для нахождения «приграничной» пары:  Создаем Y’, сохранив порядок, с точками попавшими в приграничную полосу толщиной 2δ  Для каждой точки из Y’ находим расстояние от нее до каждой из 7 точек следующих за ней. Находим наименьшее расстояние δ’ между точками в приграничной зоне.
  • 18.
    Отыскание пары ближайшихточек 2 δ δ δ δ δ 2 точки
  • 19.
    Построение выпуклой оболочки Выпуклой оболочкой конечного множества точек Q (CH(Q)) называется наименьший выпуклый многоугольник, содержащий все точки из Q.  Решение задачи нахождения выпуклой оболочки важно не только само по себе, но и как промежуточный этап для многих задач вычислительной геометрии, например, двумерной задачи о наиболее удаленных точках.
  • 20.
    Построение выпуклой оболочки voidGrahamScan(Q){ Множество Q отсортировано так, что Q[0]- точка с наименьшей ординатой, а остальные расположены в порядке возрастания полярного угла. Stack S; S->Push(Q[0]); S->Push(Q[1]); S->Push(Q[2]); for(i=3;i<=n;i++){ while(при движении по ломанной S->NextToTop(), S->Top, Q[i] движение происходит прямо или направо) S->Pop() S->Push(Q[i]) }}
  • 21.
    Построение выпуклой оболочки p0 p1 p2 p3 p4 p5 p6 p7p0 p1 p2 p3 p4 p5 p6 p7 p0 p1 p2 p3 p4 p5 p6 p7 p0 p1 p2 p3 p4 p5 p6 p7 Просмотр Грэхема
  • 22.
    Построение выпуклой оболочки voidWrappingScan(Q){ //Q[0] - точка с наименьшей ординатой //Pmax – точка с наибольшей ординатой Pmax = GetMinPoint(Q); i=1; while(Q[i]!=Pmax){ minw = maxint; for(k=1; k<N; k++){ if(k==i) w = maxint; else w = CalculatePolarLeft(Q[i],Q[k]); if(minw>w){p = Q[k]} } Pop(p); i++;} while(Q[i]!=Pmax){ minw = maxint; for(k=1; k<N; k++){ if(k==i) w = maxint; else w = CalculatePolarRight(Q[i],Q[k]); if(minw>w){p = Q[k]} } Pop(p); i++;} }
  • 23.