--- tags: Geometry title: Convex Hull --- # Special case: 2-Dimensional space ## Graham's Scan * First choose a trivial point $p_0$ that it must be in convex hull (leftmost and lowest). * sort all the other points in polar angle order, getting $\{p_1, \dots,p_n\}$. * let $s=\{p_0,p_1\}=\{s_2,s_1\}$(reversed order). * let $i=2$. * while $i<n$ do the following: If $|s|<2$ or $\angle p_is_1s_2$ is convex, then let $s=s\cup\{p_i\}$, and $i=i+1$. If not, $s=s\setminus\{s_1\}$. * then $s$ is a convex hull ## Implementation Issue: Polar angle sort may cause dividing by $0$, or two points with the same tangent. ## Optimizing: Monotone Chain Divide the question into upper convex hull and lower convex hull, and there are points at infinitely low and infinitely high respectively. Then we don't really need to do polar angle sort, what we need is just sort by coordinate. ## Implementation ```cpp= vector<point> ConvexHull(vector<point>& pts) { int n = pts.size(); // lower monotone chain sort(pts.begin(), pts.end(), [](const point& a, const point& b){ return a.x == b.x ? a.y < b.y : a.x < b.x; }); vector<point> chain(1, pts[0]); for (int i = 1; i < n;) { int bk = chain.size() - 1; if (bk == 0 || (chain[bk] - chain[bk - 1]) ^ (pts[i] - chain[bk]) > 0) chain.push_back(pts[i++]); else chain.pop_back(); } // upper monotone chain vector<point> chain2(1, pts.back()); for (int i = n - 2; i >= 0;) { int bk = chain2.size() - 1; if (bk == 0 || (chain2[bk] - chain2[bk - 1]) ^ (pts[i] - chain2[bk]) > 0) chain2.push_back(pts[i--]); else chain2.pop_back(); } // remove duplicate points chain.pop_back(); chain2.pop_back(); // combine lower chain and upper chain to convex hull chain.insert(chain.end(), chain2.begin(), chain2.end()); return chain; } ```