Handouts: Handout on Bentley-Ottmann sweep; Handout on Kirkpatrick's
algorithm (on web)
5/5/08: Intersection problems: Bentley-Ottman sweep
Some final remarks on duality/arrangments:
(1) degeneracy testing; (2) connection between arrangements
and Voronoi diagrams
Given n line segments in the plane, we want to DETECT or to REPORT
all intersection points (say, proper crossings, though we can also
handle various degenerate intersesctions).
I showed the situation in 1D: detecting and reporting intersections
among a set of segments (intervals) is done in optimal time
using sorting. We proved a lower bound of Omega(n log n), which
follows from the "Element Uniqueness Problem":
Given n numbers, are the all unique? (yes/no)
(The lower bound is NOT from sorting!)
I went through in detail a plane sweep algorithm (Bentley-Ottmann
sweep), which spends O((k+n) log n) time to REPORT all k
intersections. (It spends O(n log n) time to DETECT if there are any
intersections. The detection version is basically a stream-lined
version of the reporting algorithm of Bentley-Ottmann: it stops when a
crossing is detected and reports that crossing as a "witness".)
The idea is to sweep a horizontal line downwards. Events occur when
the line hits a segment endpoint or encounters a crossing point. (In
the DETECT version, events only take place at the segment endpoints.)
The endpoint events can be sorted in advance (in O(n log n) time) and
put in the Event Queue; however, the crossing events are discovered
"on the fly" and inserted and deleted in the Event Queue during the
algorithm, as they are discovered.
We maintain a Sweep Line Status (SLS), which stores the
segments that are crossed by the sweepline in sorted order,
left to right. Any standard data structure for maintaining a
sorted list will work here (e.g., balanced binary tree).
The important thing is that we can insert, delete, and look up
in the SLS, in time O(log n) (by binary search, essentially).
We specified in detail how to handle each type of event: (1) hit a
top endpoint, a_i; (2) hit a bottom endpoint b_i; (3) hit
a crossing point x_ij, where s_i crosses s_j. (We assume for
simplicity that any two segments are either completely disjoint
or have a proper crossing point, so that we need not worry
about degeneracies.) In each case,
we update the SLS and perform O(1) tests for intersection (between
any newly adjacent segments in the SLS), inserting or deleting
events from the Event Queue as needed.
The method described so far potentially has lots of events in the
Event Queue (at most k+2n, but k can be very large in some
cases).
In the "modified" Bentley-Ottmann sweep (discussed in the next
lecture), we are able to keep the Event Queue "small" (O(n)) by
REMOVING from the EQ any x_ij that does not correspond to adjacent
segments in the SLS any more (such a crossing will be added again
later, when the segments s_i and s_j become adjacent in the SLS
again).
Since there are 2n+k events and each event costs O(log n) time,
the total time is O((n+k) log n), and the memory used is just O(n)
for the modified Bentley-Ottmann sweep.
This is NOT the best that is known.
The best that is known is the optimal time O(k+ n log n), using
only O(n) memory to keep the data structures.