22#ifndef AFMT_FLAT_GEOMETRY
33#define AFMT_FLAT_GEOMETRY
44
5+ #include < algorithm>
56#include < cmath>
67#include < iostream>
8+ #include < vector>
79
810// Recommended eps is 0.25 * given precision
911template <long double eps>
@@ -53,7 +55,7 @@ struct Double {
5355template <class T >
5456struct Vec {
5557 T x, y;
56- Vec (T _x = 0 , T _y = 0 ) : x(_x), y(_y) {}
58+ constexpr Vec (T _x = 0 , T _y = 0 ) : x(_x), y(_y) {}
5759 constexpr T norm (void ) const { return x * x + y * y; }
5860 constexpr Vec operator +(void ) const noexcept { return *this ; }
5961 constexpr Vec operator -(void ) const noexcept { return Vec (-x, -y); }
@@ -63,16 +65,17 @@ struct Vec {
6365 constexpr Vec &operator -=(const Vec &rhs) noexcept {
6466 return x -= rhs.x , y -= rhs.y , *this ;
6567 }
66- constexpr Vec &operator *=(T d) noexcept {
68+ constexpr Vec &operator *=(const T & d) noexcept {
6769 return x *= d, y *= d, *this ;
6870 }
69- constexpr Vec &operator /=(T d) noexcept {
71+ constexpr Vec &operator /=(const T & d) noexcept {
7072 return x /= d, y /= d, *this ;
7173 }
7274 friend constexpr Vec operator +(Vec l, const Vec &r) noexcept { return l += r; }
7375 friend constexpr Vec operator -(Vec l, const Vec &r) noexcept { return l -= r; }
74- friend constexpr Vec operator *(Vec l, const Vec &r) noexcept { return l *= r; }
75- friend constexpr Vec operator /(Vec l, const Vec &r) noexcept { return l /= r; }
76+ friend constexpr Vec operator *(const T &l, Vec r) noexcept { return r *= l; }
77+ friend constexpr Vec operator *(Vec l, const T &r) noexcept { return l *= r; }
78+ friend constexpr Vec operator /(Vec l, const T &r) noexcept { return l /= r; }
7679 friend constexpr bool operator ==(const Vec &l, const Vec &r) noexcept {
7780 return l.x == r.x && l.y == r.y ;
7881 }
@@ -101,7 +104,41 @@ inline T cross(const Vec<T> &a, const Vec<T> &b) {
101104}
102105
103106template <class T >
104- struct Segment {
107+ struct PolarAngleComparator {
108+ Point<T> o;
109+ Vec<T> base; // vector (x - o), counterclockwise, from base (included).
110+ PolarAngleComparator (
111+ const Point<T> &o = Point<T>(0 , 0 ),
112+ const Vec<T> &base = Vec<T>(1 , 0 )
113+ ) : o(o), base(base) {}
114+
115+ inline int get_half (const Vec<T> &v) {
116+ T crs = cross (base, v);
117+ if (crs > 0 ) return 0 ; // counterclockwise to base
118+ if (crs < 0 ) return 1 ; // clockwise to base
119+ return dot (base, v) < 0 ; // collinear to base, but opposite direction
120+ }
121+
122+ inline bool operator ()(const Point<T> &a, const Point<T> &b) const {
123+ const Vec<T> va (a.x - o.x , a.y - o.y );
124+ const Vec<T> vb (b.x - o.x , b.y - o.y );
125+ int ha = get_half (va), hb = get_half (vb);
126+ return ha != hb ? ha < hb : cross (va, vb) > 0 ;
127+ }
105128};
106129
130+ template <class T >
131+ std::vector<Point<T>> convex_hull (std::vector<Point<T>> P) { // graham scan, O(n log n)
132+ if (P.size () <= 1 ) return P;
133+
134+ std::vector<Point<T>> H;
135+ std::swap (P[0 ], *std::min_element (P.begin (), P.end ()));
136+ std::sort (P.begin () + 1 , P.end (), PolarAngleComparator<T>(P[0 ]));
137+ for (const auto &p : P) {
138+ while (H.size () >= 2 && cross (H.back () - H[H.size () - 2 ], p - H.back ()) <= 0 ) H.pop_back ();
139+ H.push_back (p);
140+ }
141+ return H;
142+ }
143+
107144#endif
0 commit comments