Definition · Events, the status list, and the sweepGiven 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 crossingEvery 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 pairsTake (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.