Разрезание выпуклого многоугольника прямой
Дан выпуклый многоугольник и прямая
Необходимо найти два многоугольника, которые получаться при пересечении прямой исходного многоугольника.
Найдём точки пересечения прямой с многоугольником. Добавим их в список вершин. Теперь нужныо всего лишь разделить многоугольник на две части вдоль, лежащие с разных сторон от диагонали.
Асимптотика O(n).
Листинг C++
// разрезание выпуклого многоугольника по прямой
// функция возвращает два многоугольника
// первый многоугольник лежит с положительной стороны от прямой
// второй - с отрицательной
void cut_convex_for_line (vector < point > p, line l, vector < point > &v1,
vector < point > &v2, point &p1, point &p2)
{
int n = p.size();
int i, j;
// находим точки пересечение прямой с многоугольником и вставляем их в многоугольник
int c = 0; // счётчик пересечений многоугольника с прямой
list < point > s (p.begin(), p.end()); // представляем многоугольник как список вершин
list < point > :: iterator it, jt; // итераторы обходы
list < point > :: iterator i1, i2; // итераторы вставленных точек
for (it = s.begin(); it != s.end(); ++ it)
{
jt = it;
++ jt;
if (jt == s.end()) jt = s.begin();
// пересекаем прямую со стороной
point t;
int flag = cross_segment_line (*it, *jt, l, t);
// если прямая проходит по стороне
if (flag == 2)
{
if (polygon_for_line (p, l) > 0) v1 = p;
else v2 = p;
return;
}
// если прямая и сторона не пересекаются
if (flag == 0) continue;
// если прямая проходит через вершину многоугольника
if (abs (t.x - (*it).x) <= eps && abs (t.y - (*it).y) <= eps)
{
if (c == 0) i1 = it;
else i2 = it;
++ c;
continue;
}
if (abs (t.x - (*jt).x) <= eps && abs (t.y - (*jt).y) <= eps) continue;
// иначе прямая пересекает сторону, вставляем точку пересечения в многоугольник
++ it;
it = s.insert (it, t);
// увеличиваем счётчик пересечений многоугольника с прямой
if (c == 0) i1 = it;
else i2 = it;
++ c;
}
// если прямая не пересекает многоугольник
if (c != 2)
{
if (polygon_for_line (p, l) > 0) v1 = p;
else v2 = p;
return;
}
// представляем многоугольник массивом точек
n = s.size ();
vector < point > all (s.begin(), s.end());
int j1, j2;
for (it = s.begin(), i = 0; it != s.end(); ++ i, ++ it)
{
if (it == i1) j1 = i;
if (it == i2) j2 = i;
}
// режем многоугольник
p1 = all[j1];
p2 = all[j2];
cut_polygon_for_edge (all, j1, j2, v1, v2);
// если многоугольники имеют не то расположение которое нам требуется - меняем их местами
if (polygon_for_line (v1, l) < 0)
swap (v1, v2);
}
12:49
22.07.2009
По всем вопросам обращаться: rumterg@gmail.com