The idea behind the triangulation algorithm is quite simple: Try to triangulate everything you can to the left the current vertex by adding diagonals, and then remove the triangulated region from further consideration.

Figure 28: Triangulating a monotone polygon.

In the example, there is obviously nothing to do until we have at least 3 vertices. With vertex 3, it is possible to add the diagonal to vertex 2, and so we do this. In adding vertex 4, we can add the diagonal to vertex 2. However, vertices 5 and 6 are not visible to any other nonadjacent vertices so no new diagonals can be added. When we get to vertex 7, it can be connected to 4, 5, and 6. The process continues until reaching the final vertex.

The important thing that makes the algorithm efficient is the fact that when we arrive at a vertex the untriangulated region that lies to the left of this vertex always has a very simple structure. This structure allows us to determine in constant time whether it is possible to add another diagonal. And in general we can add each additional diagonal in constant time. Since any triangulation consists of n - 3 diagonals, the process runs in O(n) total time. This structure is described in the lemma below.

We will prove the invariant by induction. As the basis case, consider the case of v(2) . Here u = v(1) , and one chain consists of the single edge v(2) v(1) and the other chain consists of the other edge adjacent to v(1) . To prove the main invariant, we will give a case analysis of how to handle the next event, involving v(i) , assuming that the invariant holds at v(i-1), and see that the invariant is satisfied after each event has been processed. There are the following cases that the algorithm needs to deal with.

Case 1: v(i) lies on the opposite chain from v(i-1) : In this case we add diagonals joining v(i) to all the vertices on the reflex chain, from v(i-1) back to (but not including u). Now u = v(i-1), and the reflex chain consists of the single edge v(i) v(i-1).

Figure 29: Triangulation cases.

Case 2: v is on the same chain as v(i-1) : We walk back along the reflex chain adding diagonals joining v(i) to prior vertices until we find the first that is not visible to v(i) (which may mean that we add no diagonals). As can be seen in the figure, this may involve connecting v(i) to one or more vertices (2a) or it may involve connecting v i to no additional vertices (2b), depending on whether the first angle is less or greater than 180 degrees. In either case the vertices that were cut off by diagonals are no longer in the chain, and v(i) becomes the new endpoint to the chain. Note that when we are done (analogous to Graham's scan) the remaining chain from v(i) to u is a reflex chain.

How is this implemented? The vertices on the reflex chain can be stored in a stack. We keep a flag indicating whether the stack is on the upper chain or lower chain, and assume that with each new vertex we know which chain of the polygon it is on. Note that decisions about visibility can be based simply on orientation tests involving v(i) and the top two entries on the stack. When we connect v(i) by a diagonal, we just pop the stack.

Analysis: We claim that this algorithm runs in O(n) time. As we mentioned earlier, the sorted list of vertices can be constructed in O(n) time through merging. The reflex chain is stored on a stack. In O(1) time per diagonal, we can perform an orientation test to determine whether to add the diagonal and (assuming a DCEL) the diagonal can be added in constant time. Since the number of diagonals is n - 3, the total time is O(n).

Monotone Subdivision: In order to run the above triangulation algorithm, we first need to subdivide an arbitrary simple polygon into monotone polygons. This is also done by a plane sweep approach. We will add a set of nonintersecting diagonals that partition the polygon into monotone pieces. Observe that the absence of x monotonicity occurs only at vertices in which in which the interior angle is greater than 180 degrees and both edges lie either to the left of the vertex or both to the right. Following the book's notation, we call the first type a merge vertex (since as the sweep passes over this vertex the edges seem to be merging) and the latter type a split vertex.

Figure 30: Split vertices, merge vertices, and helpers.

Let's discuss split vertices first (both edges lie to the right of the vertex). When a split vertex is encountered in the sweep, there will be an edge e(j) of the polygon lying above and an edge e k lying below. We might consider attaching the split vertex to left endpoint of one of these two edges, but it might be that neither endpoint is visible to the split vertex. But this would imply that there is a closer vertex lying between e(j) and e(k) . We will attach the split vertex to the closest vertex to the left of the sweep line which lies between e(j) and e(k) . Call this vertex the helper(e(j)). (We could have just as easily associated the helper with e(k) , it doesn't really matter.) If there is no vertex between these edges, then helper(e(j) ) is defined to be the left endpoint of e j or e k that lies closer to the sweep line. See the figure.

Note that helper(e(j) ) is defined with respect to the current location of the sweep line. As the sweep line moves, its value changes. Also, it is only defined when the sweep line intersects e(j). One way to visualize helper(e(j)) is to imagine a trapezoid with vertical sides and bounded above and below by e(j) and e(k) sweeping to the left of the current sweep line. The first vertex this sweeping trapezoid hits is the helper. These trapezoids are illustrated in the figure above. Here are basic elements of the plane sweep algorithm to fix the split vertices. (We consider merge vertices later.)

Events: The endpoints of the edges of the polygon. These are sorted by increasing order of x coordinates. Since no new events are generated, the events may be stored in a simple sorted list (i.e., no priority queue is needed).

Sweep status: The sweep line status consists of the list of edges that intersect the sweep line, sorted from top to bottom. Our book notes that we actually only need to store edges such that the polygon lies just below this edge (since these are the only edges that we evaluate helper() from).

These edges are stored in a dictionary (e.g., a balanced binary tree or a skip list), so that the operations of insert, delete, find, predecessor and successor can be evaluated in O(log n) time each.

Event processing: There are 6 event types based on a case analysis of the local structure of edges around each vertex. Let v be the current vertex encountered by the sweep.

Split vertex: Search the sweep line status to find the edge e lying immediately above v. Add a diagonal connecting v to helper(e). Add the two edges incident to v in the sweep line status, and make v the helper of the lower of these two edges and make v the new helper of e.

Merge vertex: Find the two edges incident to this vertex in the sweep line status (they must be adjacent). Delete them both. Let e be the edge lying immediately above them. Make v the new helper of e.

Start vertex: (Both edges lie to the right of v, but the interior angle is less than 180 degrees.) Insert this vertex and its edges into the sweep line status. Set the helper of the upper edge to v.

End vertex: (Both edges lie to the left of v, but the interior angle is less than 180 degrees.) Delete both edges from the sweep line status.

Upper chain vertex: (One edge is to the left, and one to the right, and the polygon interior is below.) Replace the left edge with the right edge in the sweep line status. Make v the helper of the new edge.

Lower chain vertex: (One edge is to the left, and one to the right, and the polygon interior is above.) Replace the left edge with the right edge in the sweep line status. Let e be the edge lying above here. Make v the helper of e.

Figure 31: Plane sweep cases.

This only inserts diagonals to fix the split vertices. What about the merge vertices? This could be handled by applying essentially the same algorithm using a reverse (right to left) sweep. It can be shown that this will never introduce crossing diagonals, but it might attempt to insert the same diagonal twice. However, the book suggests a simpler approach. Whenever we change a helper vertex, check whether the original helper vertex is a merge vertex. If so, the new helper vertex is then connected to the merge vertex by a new diagonal.

It is not hard to show that this essentially has the same effect as a reverse sweep, and it is easier to detect the possibility of a duplicate insertion (in case the new vertex happens to be a split vertex). There are many special cases (what a pain!), but each one is fairly easy to deal with, so the algorithm is quite efficient. As with previous plane sweep algorithms, it is not hard to show that the running time is O(log n) times the number of events. In this case there is one event per vertex, so the total time is O(n log n). This gives us an O(n log n) algorithm for polygon triangulation.