Purpose: Decide whether any two of line segments intersect, in — without finding all the intersections. The original sweep-line algorithm (1976).

The Idea

Bentley-Ottmann reports all intersections in , which is when everything crosses everything. But if you only need a yes/no answer, you can stop at the first crossing — and the first crossing always involves two segments that are adjacent in the sweep-line status at some moment.

Algorithm

  1. Create events: the left and right endpoint of each segment. Sort by (ties: left endpoints first, then by ).
  2. Maintain a status structure — a balanced BST of the segments currently crossing the sweep line, ordered by their at the sweep position.
  3. Process events left to right:
    • Left endpoint of : insert . Test against its immediate predecessor and successor in the status. If either intersects, report yes and stop.
    • Right endpoint of : before erasing , test its predecessor against its successor (they become adjacent). If they intersect, report yes and stop.
  4. If the sweep finishes, report no.

Code sketch

struct Seg { Point l, r; };
// comparator orders segments by their y at the current sweep x
set<Seg, SweepCmp> status;
 
bool anyIntersection(vector<Seg> segs) {
    vector<Event> ev = makeEvents(segs);
    sort(ev.begin(), ev.end());
    for (auto& e : ev) {
        if (e.isLeft) {
            auto it = status.insert(e.seg).first;
            auto nxt = next(it), prv = (it == status.begin() ? status.end() : prev(it));
            if (nxt != status.end() && intersect(*it, *nxt)) return true;
            if (prv != status.end() && intersect(*prv, *it))  return true;
        } else {
            auto it = status.find(e.seg);
            auto nxt = next(it), prv = (it == status.begin() ? status.end() : prev(it));
            if (nxt != status.end() && prv != status.end() && intersect(*prv, *nxt)) return true;
            status.erase(it);
        }
    }
    return false;
}

Complexity

  • Time: events, each BST work and intersection tests
  • Space:

Why adjacency suffices

Claim: if two segments and intersect, then at some sweep position before their leftmost intersection they are adjacent in the status order.

Consider the sweep just to the left of their first crossing point. There, and have a definite order, say below ; just after the crossing the order flips. The order can only change at events, so immediately before the crossing they must be neighbours — any segment strictly between them would itself have to cross one of them earlier, contradicting “first” crossing. Hence testing only adjacent pairs at every event catches the leftmost intersection. ∎

Shamos-Hoey vs Bentley-Ottmann

Shamos-HoeyBentley-Ottmann
Answersdoes any intersection existall intersections
Time
Eventsendpoints onlyendpoints and intersection points
Status changesinsert/eraseinsert/erase and swap
Code length~50 lines~120 lines

Variants / Use Cases

  • Simple polygon testing — is a polygon self-intersecting? Feed its edges (excluding shared endpoints) to Shamos-Hoey
  • Planarity of a drawing — does a given straight-line drawing have crossings?
  • Validating geometric input — GIS and CAD systems run this constantly
  • Sweep Line — the topic page for the general technique
  • Segment Intersection — the primitive predicate