Выпуклая оболочка
Перейти к навигации
Перейти к поиску
- Любая экстремальная точка (например, самая левая из самых нижних) всегда принадлежит выпуклой оболочке. Сортируем точки по координатам, выбираем экстремальную точку O.
- Сортируем остальные почки по полярному углу от O. Точка A должна идти раньше точки B, если поворот от вектора OA к вектору OB происходит против часовой стрелки (косое произведение положительно). Если OA и OB коллинеарны, то раньше идёт точка, ближайшая к O.
- Добавляем точку O в оболочку.
- Рассматриваем остальные точки в порядке сортировки по углу. Пока две последние точки оболочки вместе с новой точкой лежат на одной прямой или дают поворот по часовой стрелке (косое произведение неотрицательно), выкидываем последнюю точку из оболочки. Добавляем следующую точку в оболочку.
struct Point { double x, y; Point() {} Point(const Point &a, const Point &b) : x(b.x - a.x), y(b.y - a.y) {} bool operator < (const Point &that) const { return y < that.y || y == that.y && x < that.x; } double length() const { return hypot(x, y); } double crossProduct(const Point &that) const { return x * that.y - y * that.x; } }; Point o; bool compareByAngle(const Point &a, const Point &b) { Point oa(o, a), ob(o, b); return oa.crossProduct(ob) > 0 || oa.crossProduct(ob) == 0 && oa.length() < ob.length(); } vector<Point> convexHull(vector<Point> &points) { sort(points.begin(), points.end()); o = points[0]; sort(points.begin() + 1, points.end(), compareByAngle); vector<Point> hull; for (int i = 0; i < points.size(); i++) { while (hull.size() >= 2) { Point &a = hull[hull.size() - 2], &b = hull[hull.size() - 1], &c = points[i]; Point ab(a, b), ac(a, c); if (ab.crossProduct(ac) <= 0) hull.pop_back(); else break; } hull.push_back(points[i]); } return hull; }
Ссылки
Теория:
- e-maxx.ru — Построение выпуклой оболочки обходом Грэхэма
- cp-algorithms.com — Convex Hull construction using Graham's Scan
- algorithmica.org — Выпуклая оболочка: 1, 2
- Андреева Е. В., Егоров Ю. Е. Вычислительная геометрия на плоскости
- www.cs.princeton.edu/~cos226/lectures — 2.1 Elementary Sorts
- usaco.guide — Convex Hull
Демонстрация:
Код:
- indy256/codelibrary/cpp/geometry/convex_hull.cpp
- ADJA/algos/Geometry/convex_hull_graham_scan.cpp
- kevin-wayne/algs4/GrahamScan.java
Задачи: