Learn
Lesson · Geometric Algorithms · Segments, and the zero sign

The Sweep Line and the Work It Does Not Save

A sweep line moves left to right over the endpoints, keeping a status list of the segments it currently crosses, and tests a new segment only against that list. On six spread-out segments that is 3 pair tests instead of 15. On four segments that all cross the middle of the picture it is 6 out of 6: the status list holds everything at once, and sorting the endpoints bought nothing at all. Both numbers are measured, and only one of them is what people remember.

events: two per segment, sorted by x; status list = what the line crosses now a start event tests the new segment against the list it joins spread out: 6 segments, 12 events, 3 pair tests against 15 pairs all crossing: 4 segments, 8 events, 6 pair tests against 6 pairs the crossings found are checked against testing every pair, every redraw the saving is in the work and never in the answer
Events, the status list, and the pairs a sweep does not test

Core ideas

What this lesson establishes

The mechanism, the reason it can skip anything, and the input on which it skips nothing.

1

The status list is what makes the skipping legal

Two segments whose x ranges do not overlap are never on the sweep line at the same moment, and two segments that cross are both on the line at the crossing's x. So testing each new segment against the segments currently on the list cannot miss a crossing. That is the correctness argument, and it is completely independent of how much work it saves.

2

The work is the sum of the status-list sizes

Each start event makes as many pair tests as there are segments already on the list. So the total is the sum over start events of the list size at that moment, which is exactly what the event table on the page displays column by column. On six spread-out segments the list never holds more than two, and the total is 3.

3

The saving depends on the input, and can be zero

Put four segments so that all of them span the middle of the picture. The list reaches size four, every start event tests against everything before it, and the sweep makes 6 tests out of 6 possible. It has done every test the brute force would, plus a sort. That is not a flaw in the sweep: it is what its bound says, because the bound is about the output size as well as the input.

The material

What a sweep skips, and the input where it skips nothing

The events, the correctness argument, the two measured counts, and the honest reading of the difference between them.

Definition · Events, the status list, and the sweep

Given k segments, the events are their 2k endpoints sorted by x, each labelled as the start or the end of its segment. The sweep processes events in order, maintaining a status list of the segments whose start has been seen and whose end has not. On a start event the new segment is tested against every segment currently on the list; on an end event its segment is removed.

Theorem · The sweep finds every crossing

Every pair of segments that intersect is tested by the sweep.

Let segments A and B intersect at a point with abscissa x*. Both A and B have their start event at or before x* and their end event at or after it, since an intersection point lies on both segments and therefore inside both x ranges.

Consider whichever of the two has the later start event; say it is B. At the moment B's start event is processed, A has already started and has not yet ended, so A is on the status list. The start event for B therefore tests B against A. (Ties in x are broken so that start events precede end events at the same abscissa, which is what makes this argument hold when two segments share an endpoint.)

□

Notice what the proof does not claim: it does not say the sweep tests FEWER pairs, only that it tests enough of them. Those are separate questions, and the second one has an answer that depends on the input while the first does not. The lab checks the first by re-testing every pair on every redraw and comparing the two crossing sets.

Example · Four segments, six tests, six pairs

Take (0, 0)–(8, 8), (0, 8)–(8, 0), (0, 4)–(8, 4) and (4, 0)–(4, 8): two diagonals, a horizontal and a vertical, all spanning the same square. The lab reports 4 segments, 8 events, 6 pair tests, 6 pairs there are, and 6 crossings found. The status list reaches size 4. The sweep did every test the brute force would do, and paid for a sort on top.

This is the preset that stops the saving being read as a bound, and it is worth dwelling on. Nothing has gone wrong: the algorithm is correct, the answer is right, and the crossing set matches the brute force exactly. What is absent is the improvement. The comparison in the status line reads “the sweep made every test the brute force would”, and it says so in amber rather than hiding it.

The same algorithm on an input it likes

Six segments strung out along the x axis in three separated pairs give a very different picture. The lab reports 6 segments, 12 events, 3 pair tests against 15 pairs, and 3 crossings. Twelve pairs were skipped because their x ranges never overlapped, and no test could have found a crossing between two segments that are never on the line together.

Three tests against fifteen is a real saving and it is a measurement of those six segments. The general claim is different and weaker: the sweep does O((k + I) log k) work for k segments and I intersections, and when I is Θ(k²) — as in the four-segment bundle, where 6 of the 6 pairs cross — that is no better than quadratic. The bound is honest about this and the intuition usually is not.

Shared endpoints are a decision the page states

A staircase of four segments, each ending where the next begins, has three shared endpoints. Do those count as crossings? This kit says yes: “meet” is the relation from the previous two lessons, and a shared endpoint is a shared point. The lab reports 3 crossings on that input and the brute force, using the parametric oracle, agrees. A different convention would be defensible and would have to be stated; what is not defensible is leaving it to the reader to find out.

That matters more than it sounds, because the status-list machinery makes it easy to get inconsistent: a sweep that skips the test when one segment's end event and another's start event share an abscissa will silently adopt a different convention from its own brute-force check. The lab's tie-break puts start events before end events at equal x, which is what keeps the two agreeing on the staircase.

Interactive

Sorting the work down, and the input where it sorts nothing down

Pair tests the sweep line made, against every pair there is

The sweep line, and the pairs it never teststests actually made against every pair there is
on the status list right nownot yet, or already gonea crossing pair

Method

Measuring what a sweep actually saved

Count the tests, not the segments, and then look at the status list that produced the count.

1

Count the pair tests, not the events

The event count is always twice the segment count and tells you nothing about the work. What varies is how many segments each start event finds already on the list, and the sum of those is the figure to compare against k(k − 1)/2.

2

Read the maximum status-list size

It is the single best predictor of whether the sweep helped. A list that never exceeds two on six segments means almost everything was skipped; a list that reaches k means nothing was.

3

Check the crossing set against every pair

Correctness and efficiency are separate claims and only one of them is in question here. The lab tests all k(k − 1)/2 pairs on every redraw and compares the two sets, so a sweep that skipped something it should not have would show as a set difference rather than as a smaller count.

4

State your convention on shared endpoints before measuring anything

Whether touching counts as crossing changes the answer on the staircase input and on any layout with abutting segments. Decide, write it down, and make sure the checking route uses the same convention — otherwise a disagreement between them is a disagreement about the question.

Saving, correctness, and what each count means

Score 0 / 0

Two inputs, and the event tables that explain the difference

First the bundle: two diagonals, a horizontal and a vertical, all spanning the same square. Then six segments strung out in three separated pairs.

BUNDLE 4 segments, 8 events segment 1 (0,0)-(8,8) 2 (0,8)-(8,0) 3 (0,4)-(8,4) 4 (4,0)-(4,8) event at kind segment status list after size 1 x = 0 start 3 3 1 2 x = 0 start 2 3, 2 2 3 x = 0 start 1 3, 2, 1 3 4 x = 4 start 4 3, 2, 1, 4 4 5 x = 4 end 4 3, 2, 1 3 6 x = 8 end 1 3, 2 2 7 x = 8 end 2 3 1 8 x = 8 end 3 empty 0 pair tests made 0 + 1 + 2 + 3 = 6 pairs there are 4·3/2 = 6 crossings found 6 by testing every pair 6 SPREAD OUT 6 segments, 12 events status list never exceeds 2 pair tests made 3 pairs there are 6·5/2 = 15 skipped 12 crossings found 3 by testing every pair 3

Read the bundle's size column downwards: 1, 2, 3, 4. The pair tests made at each start event are the size of the list it JOINED, so 0, 1, 2 and 3, and those sum to 6. There are 6 pairs. The arithmetic is not a coincidence — when every segment is on the list when every other one arrives, the sum telescopes to exactly k(k − 1)/2.

The other half of the picture is that the bundle also has 6 crossings. Every pair of those four segments really does cross, so the output is quadratic in the input, and a bound that is linear in the output size cannot be subquadratic here. The sweep is not failing to exploit structure; there is no structure to exploit.

For a faded rehearsal, predict the pair-test count for five segments all spanning the same interval, then for five segments in a diagonal staircase where each overlaps only its neighbour in x. The supplied first move is that the first is the telescoping sum again. Work out both, and then say what maximum status-list size each one reaches.

Common mistakes

1
Quoting the tests-skipped figure as the algorithm's behaviour“3 instead of 15” is a measurement of six particular segments. The same algorithm on four segments in the same lab makes every test there is. Any sentence beginning “the sweep reduces the work to” needs to end with a quantity that mentions the output size, not just the input size.
2
Confusing the event count with the workEvents are always 2k and are sorted once. The pair tests are what vary, and they are the sum of the status-list sizes at start events. A page that reported the event count as the cost would report the same number for the bundle and for a set of four segments that never meet.
3
Leaving the shared-endpoint convention implicitIt changes the answer on any layout with abutting segments, and it has to match between the sweep and whatever is checking it. This kit counts a shared endpoint as a crossing, states it, and orders start events before end events at equal x so that the sweep's own tie-break agrees with that decision.

Check your understanding

✓
Finish when you can predict a sweep's pair-test count from the status-list sizes, and name an input on which it saves nothing.

You should be able to build the event list and trace the status list, prove that no crossing can be skipped, compute the pair tests as a sum over start events, and state the bound in terms of both the input and the output size rather than the input alone.

Note: Segments are done. The last module changes the object: a closed polygon, where the same determinant summed over the edges gives an area and a sign, and where “is this point inside” turns out to have two different definitions that agree only under a hypothesis the page checks.

Kept in this browser only, for you. Nothing is sent anywhere and nothing checks it. Carry it to another device.

Feedback and recommendations

Something to change about this lesson? Write it down, tick it off when it is handled, and export the list when you want to act on it. Kept in this browser only: nothing is sent anywhere, and nobody is notified.

No recommendations yet for this lesson.