1
+ // Taken from https://github.com/chemthan/chemthan/blob/master/Computational%20Geometry/ConvexHull.cpp
2
+ #include < bits/stdc++.h>
3
+ using namespace std ;
4
+
5
+ #define RL double
6
+ #define EPS 1e-9
7
+ struct point_t {
8
+ RL x, y;
9
+ point_t () : x(0 ), y(0 ) {}
10
+ point_t (RL x, RL y) : x(x), y(y) {}
11
+ point_t (const point_t & p) : x(p.x), y(p.y) {}
12
+ int operator < (const point_t & rhs) const {return make_pair (y, x) < make_pair (rhs.y , rhs.x );}
13
+ int operator == (const point_t & rhs) const {return make_pair (y, x) == make_pair (rhs.y , rhs.x );}
14
+ point_t operator + (const point_t & p) const {return point_t (x + p.x , y + p.y );}
15
+ point_t operator - (const point_t & p) const {return point_t (x - p.x , y - p.y );}
16
+ point_t operator * (RL c) const {return point_t (x * c, y * c);}
17
+ point_t operator / (RL c) const {return point_t (x / c, y / c);}
18
+ };
19
+ RL cross (point_t p, point_t q) {return p.x * q.y - p.y * q.x ;}
20
+ RL area (point_t a, point_t b, point_t c) {return fabs (cross (a, b) + cross (b, c) + cross (c, a)) / 2 ;}
21
+ // ans > 0 => counterclockwise, ans < 0 => clockwise, ans = 0 => collinear
22
+ RL area2 (point_t a, point_t b, point_t c) {return cross (a, b) + cross (b, c) + cross (c, a);}
23
+ RL dot (point_t p, point_t q) {return p.x * q.x + p.y * q.y ;}
24
+ RL dist (point_t p, point_t q) {return sqrt (dot (p - q, p - q));}
25
+ RL dist2 (point_t p, point_t q) {return dot (p - q, p - q);}
26
+ point_t RotateCCW90 (point_t p) {return point_t (-p.y , p.x );}
27
+ point_t RotateCW90 (point_t p) {return point_t (p.y , -p.x );}
28
+ point_t RotateCCW (point_t p, RL t) {return point_t (p.x * cos (t) - p.y * sin (t), p.x * sin (t) + p.y * cos (t));}
29
+ int sign (RL x) {return x < -EPS ? -1 : x > EPS;}
30
+ int sign (RL x, RL y) {return sign (x - y);}
31
+ ostream& operator << (ostream& os, const point_t & p) {
32
+ os << " (" << p.x << " ," << p.y << " )" ;
33
+ return os;
34
+ }
35
+
36
+ // Returns points of the convex hull in counterclockwise order in O(nlgn)
37
+ void ConvexHull (vector<point_t >& pts) {
38
+ sort (pts.begin (), pts.end ());
39
+ pts.erase (unique (pts.begin (), pts.end ()), pts.end ());
40
+ vector<point_t > up, dn;
41
+ for (int i = 0 ; i < pts.size (); i++) {
42
+ // If we want to include collinear points in the hull (i.e. points lying on the boundary),
43
+ // make the inequality checks strict.
44
+ while (up.size () > 1 && area2 (up[up.size () - 2 ], up.back (), pts[i]) >= 0 ) up.pop_back ();
45
+ while (dn.size () > 1 && area2 (dn[dn.size () - 2 ], dn.back (), pts[i]) <= 0 ) dn.pop_back ();
46
+ up.push_back (pts[i]);
47
+ dn.push_back (pts[i]);
48
+ }
49
+ pts = dn;
50
+ for (int i = up.size () - 2 ; i >= 1 ; i--) pts.push_back (up[i]);
51
+ }
52
+
53
+ int main () {
54
+ int n = 10 ;
55
+ vector<point_t > pts;
56
+ for (int i = 0 ; i < n; i++) {
57
+ pts.push_back (point_t (rand () % 100 , rand () % 100 ));
58
+ }
59
+ cout << " Points:\n " ;
60
+ for (const auto & pt : pts) cout << pt << " " ;
61
+ ConvexHull (pts);
62
+ cout << " \n Hull:\n " ;
63
+ for (const auto & pt : pts) cout << pt << " " ;
64
+ return 0 ;
65
+ }
0 commit comments