Given a set of line segments in general position (neither horizontal nor vertical), return the set of points, if any, of the intersections among the segments.
This module is implemented as a "sweep line" algorithm. That is, the two-dimensional problem is reduced to a one-dimensional problem by considering only those segments which are intersecting our sweep line at any given moment – a series of points on our "sweep line". The sweep line doesn't have to move in 1px increments because the status (the segments and their neighbours that intersect the sweep line) does not change between event points (start, end, intersect). Instead we can simply move the sweep line to the location of the next event and perform our tests there. Those of which are
- Start event
- When a start event in is encountered we add it's associated line description to the status structure
- Find any neighbours and test for intersection. Add these to the event queue.
- End Event
- A line has stopped intersecting the sweep line so we need to remove it. Search for it's desc in the status structure, keeping in mind that line desc used as the key will have a different location to the one associated with the end event so these cannot be simply tested for equality but must be calculated for collinearity.
- Before the line is removed, find it's neighbours and test for intersection, adding any new intersections to the queue.
- Intersection Event
- We've found an intersection to add to our output. But before we do that we also need to process the event because intersection events are another significant time that the status structure changes – namely the lines associated swap as they cross at the intersection so now we have a reordering and we also have to test the swapped lines for any new intersections with their new neighbours.
An event queue (
At any given time the sweep line status (
We can test whether two lines are intersecting by the combination of clockwise (CW) and counter-clockwise (CCW) turns made by three vertices/points of the segments. Given two segments with end points
If just one of those triplets doesn't alternate from it's pair, the segments do not intersect.
In order to determine
Note: Care must be taken to use vectors and not points. Although points and vectors share
First we need to convert the coordinate forms
$$
p = (1-t)a + tb
$$
or this form
$$
p = a + tc
$$
where
We can find the actual
Our lines in parametric form
$$
y = a + t.b \
y = c + u.d \
$$
Both give a y value so we can equate
$$
a + t.b = c + u.d \
$$
We have two unknowns
u = \frac{b_x(c_y - a_y) - b_y(a_x - c_x)}{(d_xb_y - d_yb_x)} \ $$
Then we do the same for
- (using incorrect line desc - not updating
position
property oflineDesc
with the event position but using default/start event position) Not updating the description of the line for the end-event, that means using the desc that's given with the event which is the essentially the start-event data means we're essentially comparing with the y value of the line when the sweep line was at it's$x$ position - giving us inorrect results, and more importantly the incorrect directions when we traverse the status structure, for instance to find the predecessor/successor lines. - Why does reloading the page sometimes result in an intersection and sometimes not?
- Treap keys were not being properly compared. When treap keys were objects (or any non-number), equality was giving the wrong result. Referential equality operator (
==
) was being used with the intention to compare on value, hence returning incorrect values when non identical references were being used.
- Treap keys were not being properly compared. When treap keys were objects (or any non-number), equality was giving the wrong result. Referential equality operator (
- Given the key of the sweep line status (an ordered dictionary implemented as a treap) is represented as data
{ mx,c }
, find a way of providing the current sweep line position to the sweep line status as inserts and comparisons are made.- Instead of
$y = mx + c$ , use$y - y1 = m(x - x1)$ for the LineDesc type
- Instead of
- Structure the program so that rendering has no knowledge of how the data structures are updated – express a clear rendering/logic divide.