Всем доброго дня, необходимо было написать программу разрезания многоугольника прямой, дело сделано. Правда использовал библиотеку шаблонов stl, а это оказывается недопустимо в данном задании, как максимально просто перевести это дело на rtl? Код прикладываю:
class point
{
public:
double x, y;
int i;
point(double _x, double _y)
{
x = _x;
y = _y;
}
point()
{
point(0, 0);
}
};
// Прямая
class line
{
public:
double a, b, c;
//ax + by + c = 0
line(double _a = 0, double _b = 0, double _c = 0)
{
a = _a;
b = _b;
c = _c;
}
};
class polygon
{
public:
size_t size_polygon;
vector<point> polygon_;
//сам многоугольник, и его размер ( вершины )
polygon(vector<point> _polygon_, size_t size_polygon_)
{
polygon_ = _polygon_;
size_polygon = size_polygon_;
}
};
// лежит ли точка в прямоугольнике, который образуют заданные точки
bool point_in_box(point t, point p1, point p2)
{
return (abs(t.x - min(p1.x, p2.x)) <= eps || min(p1.x, p2.x) <= t.x) &&
(abs(max(p1.x, p2.x) - t.x) <= eps || max(p1.x, p2.x) >= t.x) &&
(abs(t.y - min(p1.y, p2.y)) <= eps || min(p1.y, p2.y) <= t.y) &&
(abs(max(p1.y, p2.y) - t.y) <= eps || max(p1.y, p2.y) >= t.y);
}
// уравнение прямой, проходящей через две точки
line toline(point p1, point p2)
{
double a = p2.y - p1.y;
double b = p1.x - p2.x;
return line(a, b, -a * p1.x - b * p1.y);
}
// знак точки при подставлении в уравнение прямой
int point_in_line(line l, point p)
{
double s = l.a * p.x + l.b * p.y + l.c;
return s < -eps ? -1 : s > eps ? 1 : 0;
}
// параллельны ли прямые?
bool is_parallel_line(line l1, line l2)
{
return abs(l1.a * l2.b - l2.a * l1.b) <= eps;
}
// совпадают ли прямые?
bool is_equal_line(line l1, line l2)
{
return (abs(l1.a * l2.b - l2.a * l1.b) <= eps &&abs(l1.a * l2.c - l2.a * l1.c) <= eps && abs(l1.b * l2.c - l2.b * l1.c) <= eps);
}
// пересечение двух прямых
int cross_line(line l1, line l2, point &p)
{
if (is_equal_line(l1, l2)) return 2;
if (is_parallel_line(l1, l2)) return 0;
p.x = (l2.b * l1.c - l1.b * l2.c) / (l2.a * l1.b - l1.a * l2.b);
p.y = (l1.b != 0 ? (-l1.c - l1.a * p.x) / l1.b : (-l2.c - l2.a * p.x) / l2.b);
return 1;
}
// пересекаются ли отрезки?
bool is_cross_segment(point p1, point p2, point p3, point p4)
{
line l1 = toline(p1, p2);
line l2 = toline(p3, p4);
int sign1 = point_in_line(l1, p3) * point_in_line(l1, p4);
int sign2 = point_in_line(l2, p1) * point_in_line(l2, p2);
if (abs(sign1) <= eps && abs(sign2) <= eps)
return point_in_box(p1, p3, p4) || point_in_box(p2, p3, p4) ||
point_in_box(p3, p1, p2) || point_in_box(p4, p1, p2);
return sign1 <= eps && sign2 <= eps;
}
// пересечение отрезков
bool cross_segment(point p1, point p2, point p3, point p4, point &t)
{
// Строим прямые проходящие через эти отрезки и пересекаем их
line l1 = toline(p1, p2);
line l2 = toline(p3, p4);
int flag = cross_line(l1, l2, t);
if (flag == 0) return false;
// Если прямые совпадают, проверяем каждый конец отрезка на принадлежность другому отрезку
if (flag == 2)
{
if (point_in_box(p1, p3, p4)) { t = p1; return true; }
if (point_in_box(p2, p3, p4)) { t = p2; return true; }
if (point_in_box(p3, p1, p2)) { t = p3; return true; }
if (point_in_box(p4, p1, p2)) { t = p4; return true; }
return false;
}
// Если прямые пересекаются, проверяем принадлежит ли точка пересечения обоим отрезкам
return point_in_box(t, p1, p2) && point_in_box(t, p3, p4);
}
// пересечение отрезка с прямой
int cross_segment_line(point p1, point p2, line l, point &p)
{
line t = toline(p1, p2);
int flag = cross_line(l, t, p);
if (flag == 0) return 0;
if (flag == 2) return 2;
if (point_in_box(p, p1, p2)) return 1;
return 0;
}
double area_triangle(point a, point b, point c)
{
return 0.5 * (a.x * b.y + b.x * c.y + c.x * a.y - a.y * b.x - b.y * c.x - c.y * a.x);
}
//Лежит ли точка справа от отрезка в обходе против часовой стрелки?
bool ccw(point a, point b, point c)
{
return area_triangle(a, b, c) > eps;
}
// выпуклый ли многоугольник?
bool is_convex(vector < point > p)
{
int l, i, r;
int n = p.size();
bool isccw = ccw(p[n - 1], p[0], p[1]);
for (i = 1; i < n; ++i)
{
l = (i - 1 + n) % n;
r = (i + 1) % n;
if (ccw(p[l], p[i], p[r]) != isccw)
return false;
}
return true;
}
// расположение многоугольника отосительно прямой
// 1 - находится с положительной стороны
// - 1 - находится с отрицательной стороны
// 0 - прямая пересекает одну из сторон многоугольника (сторону а не вершину)
int polygon_for_line(vector < point > p, line l)
{
int i, j;
int s = -2; // знак
for (i = 0; i < p.size(); ++i)
{
int t = point_in_line(l, p[i]); // положение вершины относительно прямой
if (t != 0) // если точка не принадлежить прямой
if (s != -2) // если s мы вычислили
if (t != s) // если знаки различны, то прямая пересекает сторону многоугольника
return 0;
else
{
}
else
s = t; // если s мы ещё не вычислили, присваиваем ему вычисленное значение
}
if (s == -2) return 0;
return s;
}
// разрезание многоугольника по диагонали
void cut_polygon_for_edge(vector < point > p, int i1, int i2, vector < point > &p1, vector < point > &p2)
{
int i;
int n = p.size();
for (i = i1; i != (i2 + 1) % n; i = (i + 1) % n)
p1.push_back(p[i]);
for (i = i2; i != (i1 + 1) % n; i = (i + 1) % n)
p2.push_back(p[i]);
}
// разрезание выпуклого многоугольника по прямой
// функция возвращает два многоугольника
// первый многоугольник лежит с положительной стороны от прямой
// второй - с отрицательной
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);
}
P.S. Видимо стоит переделывать все использованные вектора под дин. массивы? Если переделываю, то придется использовать их и на месте list
?
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Есть двумерный массив чиселInt mass[15][20] Нужно передать его в функцию так, чтобы изменение его в функции отражалось в main
Доброго времени сутокЕсть код, который нужно изменить под статичный массив