Convex Hull

#include<bits/stdc++.h>
#define ll long long

// Usage:
//      ConvexHull hull;
//      hull.addPoint(x, y);
//      convexhull = hull.getConvexHull();
struct ConvexHull
{   
    struct Point {
        
        double x, y;
        
        Point(){}
        
        Point(double _1, double _2) : x(_1), y(_2) {}
        
        bool operator < (Point b) const {
            if (x != b.x)
                return x < b.x;
            return y < b.y;
        }
    };
    
    vector<Point> a;
    set<Point> bag;
    
    ConvexHull () {
        a.clear();
        bag.clear();
    }

    void clear() {
        a.clear();
        bag.clear();
    }
    
    bool cw(Point a, Point b, Point c) {
        return a.x*(b.y-c.y) + b.x*(c.y-a.y) + c.x*(a.y-b.y) < 0;
    }

    bool ccw(Point a, Point b, Point c) {
        return a.x*(b.y-c.y) + b.x*(c.y-a.y) + c.x*(a.y-b.y) > 0;
    }
    
    void addPoint(double x, double y) {
        bag.insert(Point(x, y));
    }

    vector< pair<double, double> > getConvexHull() {
        
        // take all points from set to vector, sorted by increasing order
        for (auto it = bag.begin(); it != bag.end(); ++it)
            a.push_back(*it);
        
        vector< pair<double, double> > hull;
        
        if (a.size() <= 1) {
            for (auto p : a)
                hull.push_back({p.x, p.y});
            return hull;
        }
                
        Point p1 = a[0], p2 = a.back();
        vector<Point> up, down;
        up.push_back(p1);
        down.push_back(p1);
        
        for (int i = 1; i < a.size(); i++) {
            if (i == a.size() - 1 || cw(p1, a[i], p2)) {
                while (up.size() >= 2 && !cw(up[up.size()-2], up[up.size()-1], a[i]))
                    up.pop_back();
                up.push_back(a[i]);
            }
            if (i == a.size() - 1 || ccw(p1, a[i], p2)) {
                while(down.size() >= 2 && !ccw(down[down.size()-2], down[down.size()-1], a[i]))
                    down.pop_back();
                down.push_back(a[i]);
            }
        }

        for (int i = 0; i < up.size(); i++)
            hull.push_back({up[i].x, up[i].y});
        for (int i = down.size() - 2; i > 0; i--)
            hull.push_back({down[i].x, down[i].y});
        
        return hull;
    }   
        
};

Leave a Reply