Convex Hulls (2D)
Total Page:16
File Type:pdf, Size:1020Kb
Convex Hulls (2D) O’Rourke, Chapter 3 Announcements • We are live on Piazza: http://piazza.com/jhu/spring2016/600459 • Code-base was updated last Wednesday (Fixes a bug where 푦-values are read in as zero) Outline • Convex Hulls • Algorithms Naïve Implementation(s) Gift Wrapping Quick Hull Graham’s Algorithm Lower bound complexity Convexity A set 푆 is convex if for any two points 푝, 푞 ∈ 푆 the line segment 푝푞 ⊂ 푆. S S p q Not convex Convex? Convexity A set 푆 is convex if it is the intersection of (possibly infinitely many) half-spaces. S S p q Not convex Convex? Convexity 푑 푑 Given points 푝1, … , 푝푛 ⊂ ℝ , a point 푞 ∈ ℝ is a convex combination of the points if 푞 can be expressed as the linear sum: 푛 푞 = 훼푖 ⋅ 푝푖 푖=1 with 훼푖 ≥ 0 and 훼1 + ⋯ + 훼푛 = 1. Convex Hull The convex hull of a set of points 푆 ⊂ ℝ푑, denoted ℋ(푆), is the: set of all convex combinations of points in 푆, set of all convex combinations of 푑 + 1 points in 푆, intersection of all convex sets 퐶 w/ 푆 ⊂ 퐶, intersection of all half-spaces 퐻 w/ 푆 ⊂ 퐻, smallest convex polygon containing 푆. ℋ(푆) 푝1 푝푛 Convex Hull Note: If 푝 ∈ 푆 ⊂ ℝ2 and 푝 is a vertex of the convex hull then 푝 must be a convex vertex. Otherwise, we could create a line segment with vertices inside of the hull but which 푝 isn’t strictly interior. Convex Hull Claim: If 푃 ⊂ ℝ2 is a polygon whose vertices are all convex, then 푃 is convex. Convex Hull Proof (by induction): Otherwise, we could add a diagonal. ⇒ By induction, each half is convex. Convex Hull Proof (by induction): Otherwise, we could add a diagonal. ⇒ If 푃 is not convex there must be a segment between the two parts that exits 푃. Choose 푝1 and 푝2 above/below the diagonal. Evolve the segment to 푝1푝2. Since 푝1 and 푝2 are above/below, 푝1푝2 crosses the diagonal and is entirely inside 푃. 푝1 푝2 Convex Hull Proof (by induction): Otherwise, we could add a diagonal. ⇒ If 푃 is not convex there must be a segment between the two parts that exits 푃. Choose 푝1 and 푝2 above/below the diagonal. Evolve the segment to 푝1푝2. Since 푝1 and 푝2 are above/below, 푝1푝2 crosses the diagonal and is entirely inside 푃. 푝1 The last point at which the 푝 evolving segment is not fully 2 inside must be a reflex vertex. Convex Hull The extreme points of a set of points 푆 ⊂ ℝ2 are the points which are on the convex hull and have interior angle strictly less than 휋. ℋ(푆) 푝1 푝푛 Convex Hull Goal: 푑 Given a set of points S = 푝1, … , 푝푛 ⊂ ℝ , compute the convex hull ℋ(푆) efficiently. • Do we want all points on the hull or just the extreme ones? ℋ(푆) 푝 • Do the output vertices need 1 to be sorted or is the set of (extreme) vertices sufficient? 푝푛 Convex Hull Goal: 푑 Given a set of points S = 푝1, … , 푝푛 ⊂ ℝ , compute the convex hull ℋ(푆) efficiently. • Do we want all points on the hull or just the extreme ones? ℋ(푆) 푝 • Do the output vertices need 1 to be sorted or is the set of (extreme) vertices sufficient? 푝푛 We will focus on the ordered output of the extreme points on the hull. Convex Hull (2D) Note: We can find a hull vertex in linear time by finding the vertex that is extremal w.r.t. to some direction. Outline • Convex Hulls • Algorithms Naïve Implementation(s) Gift Wrapping Quick Hull Graham’s Algorithm Lower bound complexity Convex Hull (2D) Naïve Algorithm: For each directed edge 푒 ∈ 푆 × 푆, check if the half-space to the right of 푒 is empty of points (and there are no points on the line outside the segment). Otherwise the segment is not on the hull If the rest of the points are on one side, the segment is on the hull Convex Hull (2D) Naïve Algorithm 푂(푛3): For each directed edge 푒 ∈ 푆 × 푆, check if half-space to the right of 푒 is empty of points (and there are no points on the line outside the segment). Note: The output is the set of (unordered) extreme points on the hull. Convex Hull (2D) Naïve Algorithm 푂(푛3): For each directed edge 푒 ∈ 푆 × 푆, check if half-space to the right of 푒 is empty of points (and there are no points on the line outside the segment). Note: The output is the set of (unordered) extreme pointsIf we want on thethe ordered hull. points, we can stitch the edges together in ≤ 푂(푛2) time in a post-processing step. Convex Hull (2D) Naïve Algorithm++: Grow the hull by starting at a hull vertex and searching for the next edge on the hull by trying all possible edges and testing if they are on the hull. Convex Hull (2D) Naïve Algorithm++ 푂(푛2ℎ)*: Grow the hull by starting at a hull vertex and searching for the next edge on the hull by trying all possible edges and testing if they are on the hull. Note: By explicitly forcing the output to be sorted, we end up with a faster algorithm. *ℎ is the number of points on the hull. Convex Hull (2D) Naïve Algorithm++ 푂(푛2ℎ)*: Grow the hull by starting at a hull vertex and searching for the next edge on the hull by trying all possible edges and testing if they are on the hull. Note: By explicitly forcing the output to be sorted, we end up with a faster algorithm.This implementation is output sensitive. *ℎ is the number of points on the hull. Outline • Convex Hulls • Algorithms Naïve Implementation(s) Gift Wrapping Quick Hull Graham’s Algorithm Lower bound complexity Convex Hull (2D) Note: The next edge on the hull is the one making the largest angle. (If two points make the same angle, ignore the closer one.) Gift Wrapping: Grow by finding the edge making the largest angle. Convex Hull (2D) Note: The next edge on the hull is the one making the largest angle. (If two points make the same angle, ignore the closer one.) Gift Wrapping 푂(푛ℎ): Grow by finding the edge making the largest angle. Convex Hull (2D) Note: The next edge on the hull is the one making the largest angle. (If two points make the same angle, ignore the closer one.) Gift Wrapping 푂(푛ℎ): Grow by finding the edge makingA similar the largest approach angle. makes it possible to find a hull edge in linear time. Outline • Convex Hulls • Algorithms Naïve Implementation(s) Gift Wrapping Quick Hull Graham’s Algorithm Lower bound complexity Convex Hull (2D) Observation: Given a hull edge (푎, 푏), we can find the point 푐 furthest from the edge in linear time. 1. The point 푐 is on the hull. 푐 2. The triangle Δ푎푏푐 partitions the input into three regions: I. Points inside Δ푎푏푐. 푏 II. Points to the right of 푏푐. 푎 III. Points to the right of 푐푎. Convex Hull (2D) Observation: Given a hull edge (푎, 푏), we can find the point 푐 furthest from the edge in linear time. ⇒ Divide-and-conquer: Discard points inside Δ푎푏푐 푐 Separately compute the half-hulls to the right of 푏푐 and the right of 푐푎. Merge the two hulls. 푏 푎 Convex Hull (2D) Observation: Given aWe hull don’t edge require (푎, 푎푏푏),to we be acan hull find edge. the point 푐 furthestAs long from as it’s the a hull edge diagonal in linear merging time. is easy. ⇒ Divide-and-conquer: Discard points inside Δ푎푏푐 푐 Separately compute the half-hulls to the right of 푏푐 and the right of 푐푎. Merge the two hulls. 푏 푎 Convex Hull (2D) QuickHull( 푆 ⊂ ℝ2 ) (푎, 푏) ← HorizontalExtrema( 푆 ) 퐴 ← RightOf( 푆 , 푎푏 ) 퐵 ← RightOf( 푆 , 푏푎 ) 푄퐴 ← QuickHalfHull( 퐴 , 푎푏 ) 푄퐵 ← QuickHalfHull( 퐵 , 푏푎 ) return 푎 ∪ 푄퐴 ∪ 푏 ∪ 푄퐵 Convex Hull (2D) QuickHull( 푆 ⊂ ℝ2 ) (풂, 풃) ← HorizontalExtrema( 푺 ) 퐴 ← RightOf( 푆 , 푎푏 ) 퐵 ← RightOf( 푆 , 푏푎 ) 푄퐴 ← QuickHalfHull( 퐴 , 푎푏 ) 푏 푎 푄퐵 ← QuickHalfHull( 퐵 , 푏푎 ) return 푎 ∪ 푄퐴 ∪ 푏 ∪ 푄퐵 Convex Hull (2D) QuickHull( 푆 ⊂ ℝ2 ) (푎, 푏) ← HorizontalExtrema( 푆 ) 푨 ← RightOf( 푺 , 풂풃 ) 퐵 푩 ← RightOf( 푺 , 풃풂 ) 푄퐴 ← QuickHalfHull( 퐴 , 푎푏 ) 푏 푎 푄퐵 ← QuickHalfHull( 퐵 , 푏푎 ) 퐴 return 푎 ∪ 푄퐴 ∪ 푏 ∪ 푄퐵 Convex Hull (2D) QuickHull( 푆 ⊂ ℝ2 ) (푎, 푏) ← HorizontalExtrema( 푆 ) 퐴 ← RightOf( 푆 , 푎푏 ) 푄퐵 퐵 ← RightOf( 푆 , 푏푎 ) 푸푨 ← QuickHalfHull( 푨 , 풂풃 ) 푏 푎 푸푩 ← QuickHalfHull( 푩 , 풃풂 ) return 푎 ∪ 푄퐴 ∪ 푏 ∪ 푄퐵 푄퐴 Convex Hull (2D) QuickHull( 푆 ⊂ ℝ2 ) (푎, 푏) ← HorizontalExtrema( 푆 ) 퐴 ← RightOf( 푆 , 푎푏 ) 퐵 ← RightOf( 푆 , 푏푎 ) 푄퐴 ← QuickHalfHull( 퐴 , 푎푏 ) 푄퐵 ← QuickHalfHull( 퐵 , 푏푎 ) return 풂 ∪ 푸푨 ∪ 풃 ∪ 푸푩 Convex Hull (2D) (Recursion Level 0) QuickHalfHull( 푆 ⊂ ℝ2, 푎푏 ∈ 푆 × 푆 ) if( 푆 == ∅ ) return ∅ else » 푐 ← 푆 푎푏 Furthest( , ) 푏 » 퐴 ← RightOf( 푆 , 푎푐 ) 푎 » 퐵 ← RightOf( 푆 , 푐푏 ) » 푄퐴 ← QuickHalfHull( 퐴 , 푎푐 ) » 푄퐵 ← QuickHalfHull( 퐵 , 푐푏 ) » return 푄퐴 ∪ 푐 ∪ 푄퐵 Convex Hull (2D) (Recursion Level 0) QuickHalfHull( 푆 ⊂ ℝ2, 푎푏 ∈ 푆 × 푆 ) if( 푆 == ∅ ) return ∅ else » 풄 ← Furthest( 푺 , 풂풃 ) 푏 » 퐴 ← RightOf( 푆 , 푎푐 ) 푎 » 퐵 ← RightOf( 푆 , 푐푏 ) » 푄퐴 ← QuickHalfHull( 퐴 , 푎푐 ) 푐 » 푄퐵 ← QuickHalfHull( 퐵 , 푐푏 ) » return 푄퐴 ∪ 푐 ∪ 푄퐵 Convex Hull (2D) (Recursion Level 0) QuickHalfHull( 푆 ⊂ ℝ2, 푎푏 ∈ 푆 × 푆 ) if( 푆 == ∅ ) return ∅ else » 푐 ← 푆 푎푏 Furthest( , ) 푏 » 푨 ← RightOf( 푺 , 풂풄 ) 푎 » 푩 ← RightOf( 푺 , 풄풃 ) 퐴 » 푄퐴 ← QuickHalfHull( 퐴 , 푎푐 ) 퐵 푐 » 푄퐵 ← QuickHalfHull( 퐵 , 푐푏 ) » return 푄퐴 ∪ 푐 ∪ 푄퐵 Convex Hull (2D) (Recursion Level 0) QuickHalfHull( 푆 ⊂ ℝ2, 푎푏 ∈ 푆 × 푆 ) if( 푆 == ∅ ) return ∅ else » 푐 ← 푆 푎푏 Furthest( , ) 푏 » 퐴 ← RightOf( 푆 , 푎푐 ) 푎 » 퐵 ← RightOf( 푆 , 푐푏 ) 퐴 » 푸푨 ← QuickHalfHull( 푨 , 풂풄 ) 푐 » 푄퐵 ← QuickHalfHull( 퐵 , 푐푏 ) » return 푄퐴 ∪ 푐 ∪ 푄퐵 Convex Hull (2D) (Recursion Level 1) QuickHalfHull( 푆 ⊂ ℝ2, 푎푏 ∈ 푆 × 푆 ) if( 푺 == ∅ ) return ∅ else » 푐 ← Furthest( 푆 , 푎푏 ) » 퐴 ← RightOf( 푆 , 푎푐 ) 푎 » 퐵 ← RightOf( 푆 , 푐푏 ) » 푄퐴 ← QuickHalfHull( 퐴 , 푎푐 ) 푏 » 푄퐵 ← QuickHalfHull( 퐵 , 푐푏 ) » return 푄퐴 ∪ 푐 ∪ 푄퐵 Convex Hull (2D) (Recursion Level 0) QuickHalfHull( 푆 ⊂ ℝ2, 푎푏 ∈ 푆 × 푆 ) if( 푆 == ∅ ) return ∅ else » 푐 ← 푆 푎푏 Furthest( , ) 푏 » 퐴 ← RightOf( 푆 , 푎푐 ) 푎 » 퐵 ← RightOf( 푆 , 푐푏 ) 푄퐴 » 푄퐴 ← QuickHalfHull( 퐴 , 푎푐 ) 퐵 푐 » 푸푩 ← QuickHalfHull( 푩 , 풄풃 ) » return 푄퐴 ∪ 푐 ∪ 푄퐵 Convex Hull (2D) (Recursion Level