Лекция 16 Вычислительная геометрия
-
Upload
simplepeople -
Category
Data & Analytics
-
view
100 -
download
4
Transcript of Лекция 16 Вычислительная геометрия
Анализ комбинаторных алгоритмов
Лекция № 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 + .
В матричной записи:
100
*)1 (1 **
yxyx
Аффинные преобразования
1000cossin0sincos
R
1000000
][
D
100010001
][M
1010001
][
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).
122121
2121 det yxyx
yyxx
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
de
f
a ab
acb
cb
dcb
db
edb
edbf
edf
Отыскание пары ближайших точек
Данную задачу можно решить используя метод «разделяй и властвуй».
Входными данными рекурсивного алгоритма являются множество точек 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])}}
Построение выпуклой оболочки
p0p1
p2
p3
p4p5
p6
p7 p0p1
p2
p3
p4p5
p6
p7
p0p1
p2
p3
p4p5
p6
p7 p0p1
p2
p3
p4p5
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++;}}
Построение выпуклой оболочки
p0p1
p2
p3
p4
p5
p6
Проход Джарвиса