Convex Hulls in 2D ================== Lectures 2 & 3 What is a Convex Hull? ---------------------- Basic A subset S of the plane is called convex if and only if for any pare of points p,q in S the line segment pq is completely contained in S. Intervals Given points (x_1, ..., x_n), all points computed by the sum (a_1 x_1 + ... + a_n x_n) with a_i >= 0 and sum of all a_i = 1 Triangles Union of all triangles between points in S. Halfplanes The intersection of all halfplanes that contain S. Overview -------- Naive I O(n^4) Naive II O(n^3) Complexity as a function of dimensionality Giftwrap O(n^2) O(n k), where k is the number of points on the convex hull Incremental I O(n^2) QuickHull O(n^2) worst case Graham Scan O(n log n) Incremental II O(n log n) Divide and Conquer O(n log n) Lower bound From http://softsurfer.com/Archive/algorithm_0109/algorithm_0109.htm Brute Force O(n^4) [Anon, the dark ages] Gift Wrapping O(nh) [Chand & Kapur, 1970] Graham Scan O(n log n) [Graham, 1972] Jarvis March O(nh) [Jarvis, 1973] QuickHull O(nh) [Eddy, 1977], [Bykat, 1978] Divide-and-Conquer O(n log n) [Preparata & Hong, 1977] Monotone Chain O(n log n) [Andrew, 1979] Incremental O(n log n) [Kallay, 1984] Marriage-before-ConquestO(n log h) [Kirkpatrick & Seidel, 1986] From http://compgeom.cs.uiuc.edu/~jeffe/teaching/497geom/s00/schedule.html Kirkpatrick and Seidel's marriage before conquest O(n log h) Chan, Snoeyink, and Yap's prune and search [csy-pddpo-97] O(n log h) Bhattacharya and Sen's pruned randomized quickhull [bs-spoos-97] O(n log h) Wenger's pruned randomized quickhull [w-rqh-97] O(n log h) New Tools --------- a) Lower bound b) Incremental algorithm c) Amortized cost Naive I: Triangles ------------------ The algorithm aims at eliminating non-extreme points. *Extreme points* are vertices of the convex hull with interior angle < Pi (strictly convex). Assume S contains n vertices Algorithm: for all (n choose 3) triangles v_a, v_b, v_c for all n vertices v_i if v_i is inside triangle v_a, v_b, v_c mark v_i as non-extreme output all extreme points Question: How does the "inside triangle" check work? Runtime: n^3 trianges times n interior checks = O(n^4) Note: here the output is a set of extreme points. What if we would like to have the extreme edges as an output? Naive II: Halfplanes -------------------- The algorithm eliminates all halfplanes defined by two vertices from S that have points on both sides Algorithm: for all (n choose 2) pairs of vertices v_a, v_b for all n vertices v_i if v_i is not to the left of directed edge v_a v_b mark directed edge v_a v_b as nonextreme output all extreme edges Question: How does the "one the left" check work? Runtime: n^2 edes times n vertex checks = O(n^3) Note: what to we have to do, if we want to have the edges in order? Situating the Problem in Terms of Complexity -------------------------------------------- 1 dimension O(n) 2 dimensions O(n log n) 3 dimensions O(n log n) d dimensions O(n^(floor(d/2)+1)) Giftwraping ----------- Chand and Kapur, 1970 Also called Jarvis' March (Jarvis, 1973) R. A. Jarvis, "On the identification of the convex hull of a finite set of points in the plane" Inform. Process. Lett., 2, 1973, 18--21. Idea: Rather than checking for all (n choose 2) edges, as we did in Naive II, let's just check for extreme edges. We know they will be linked, as they end up forming the convex hull. So we march around the convex hull, making sure we find the extreme edge at each step. Algorithm: Find vertex with lowest y coordinate and store it in variable v_current Initialize variable l to be the horizontal line through v_current v_start <- v_current Repeat for all vertices v_i compute counter-clockwise (ccw) angle between l and (v_current v_i) let v_smallest be the point for which the angle was smallest output edge v_i v_smallest v_current <- v_smallest until v_current = v_start Runtime: For all k edges on the convex hull we have to compute n angels O(n k), which is basically O(n^2) Incremental I ------------- Idea: Add points one at a time and update the convex hull to include that point. Each update of inserting a vertex v is performed by finding the lines through v and tangent to the convex hull so far. Test for new vertex v : XOR ( v left of (v_(i-1),v_i) , v on left of (v_i, v_(i+1)) ) Runtime: When the 3rd point is added, we have to look for tangents with 2 other points. When the n-th point is added we have to look for tangents with n-1 points. 1+2+3+...+n = O(n^2) QuickHull --------- Suggested by several researchers in the lates 70s (among them Floyd, 1986 Turing Award Winner) Preparata and Shamos called it QuickHull in 1985 Idea: Eliminate as many points as quickly as possible. Use the trick that the top-, bottom-, left-, right-most points can be found in O(n) without sorting. Those points are guaranteed to be on the convex hull. Algorithm: Step 1) Find quadrilateral abcd by finding the four extremal points along the coordinate axes Find the four sets S_ab, S_bc, S_cd, S_da of points to the right of the four edges of the quadrilateral Step 2) For all of them call QuickHull QuickHull(a,b,S) if S={a,b} return (a,b) else c <- point at max dist from ab A <- points right of (a,c) B <- points right of (c,b) return QuickHull(a c A) concatenated with QuickHull(c b B) Runtime: Step 1): O(n) Step 2): T(n) = O(n) + T(x) + T(y) O(n) to determine point c at max distance from ab |A| = x, |B| = y case i) (best case) x = y = n/2 T(n) = 2T(n/2) + O(n) O(n log n) case ii) (worst case) x = 1, y = n-1 T(n) = T(n-1) + O(n) O(n^2) Graham Scan ----------- Ronald Graham, 1972 R. L. Graham and F. F. Yao, "Finding the convex hull of a simple polygon," J. Algorithms, 4, 1983, p. 324--331. Idea: Do a "radar scan" of all points starting from a point on the convex hull. Note: Original algorithm proposed by Graham did not require the starting point to be on the convex hull, but at the interior of the polyon. The algorithm we will discuss is slightly simpler. Algorithm: Find rightmost lowest point and lable it p_0 Sort all other points angularly about p_0 and label them p_1,...,p_{n-1} Initialize stack S = (p_0,p_1) = (p_{t-1},p_t) (t = top) i = 2 while i < n do if p_i is strictly left of (p_{t-1},p_t) then push (S, i) and increment i else pop (S) Runtime: Finding lowest point O(n) Sorting by angle: O(n log n) Stack operations: at most 2n Overall runtime: O(n log n) -- O(n) after sorting Incremental II -------------- Idea: Insert points from left to right and maintain data structure so that in the end we are left with the convex hull. This is a first allusion to a sweepline algorithm, something we will discuss alter. Sweeplines are an important algorithmic tool in computational geometry. Algorithm: Sort vertices left to right O(n log n) Distinguish between upper and lower hull For upper hull: - insert points left to right - maintain upper convex hull by . appending new points . going backwards and deleting points at which a left turn is made Runtime: Analysis using amortized cost Sorting: O(n log n) How many times do we have to go back/how many times can we delete a point? This algorithm is O(n) after sorting! Divide and Conquer ------------------ Preparata and Hong, 1977 Idea: Divide points into two equal halves for which to compute the convex hulls. When done, merge them. Algorithm: Sort vertices in S by x coordinate Divide S into A and B with A containing ceil(n/2) left points and B the rest Computer convex hulls H(A) and H(B) recursively Merge H(A) and H(B) by computing the H(H(A) union H(B)) How to merge? The key is to find a lower and upper tangent. Idea: The points are sorted. Start with the two points in A and B closest to each other and walk downwards (upwards). If we believe this each merge step is O(n). Solving the recurrence T(n) = 2T(n/2) + O(n) yields O(n log n) We left out some details here. For example: Is walking downwards guaranteed to find a tangent? Does it find the correct tangent, i.e., the one that supports A and B from below? Intuitively, you probably believe this. Can you prove it? Applets ------- For an online demonstration of how these algorithms work, see http://www.cse.unsw.edu.au/~lambert/java/3d/hull.html Lower Bound ----------- What is a lower bound? Omega(f(n)) = { g(n) : Exist x s.t. |g(n)| >= c f(n) infinitely often } compare with: O(f(n)) = { g(n) : Exist c Exist n_0 s.t. |g(n)| <= c f(n) Forall n > n_0 } Can we do better than O(n log n)? Answer: no. Reduce sorting of (x_1, ..., x_n) to computing the convex hull of ((x_1,x_1^2), ...(x_n, x_n^2)). The boundary gives us the sorted points. What if we don't need to compute the boundary, but only extreme points? Turns out still O(n log n). Extendable to Higher Dimensions? -------------------------------- Graham Scan: no Divide and Conquer: yes - with same bound in 3D! Griftwrapping: yes Incremental: yes QuickHull: yes Later we will see more about higher-dimensional convex hulls (lectures 21 & 22)