17.3 Line and Segment Intersection

Given two lines or two line segments, determine whether they intersect and, if they do, compute the intersection point.

17.3 Line and Segment Intersection

Problem

Given two lines or two line segments, determine whether they intersect and, if they do, compute the intersection point.

This problem appears throughout computational geometry. Computer graphics uses intersection tests during rendering. Geographic information systems use them when processing roads, rivers, and administrative boundaries. Robotics uses them for collision detection and motion planning. Polygon clipping, sweep-line algorithms, and triangulation all rely heavily on robust intersection predicates.

The challenge is handling every possible configuration correctly, including parallel lines, overlapping segments, endpoint touching, and collinear cases.

Solution

Use orientation tests to determine the relative positions of endpoints.

Given two segments:

AB
CD

The general intersection condition is:

orientation(A,B,C) and orientation(A,B,D)
have opposite signs

AND

orientation(C,D,A) and orientation(C,D,B)
have opposite signs

This means each segment crosses the line containing the other segment.

Let:

o1 = orientation(A, B, C)
o2 = orientation(A, B, D)

o3 = orientation(C, D, A)
o4 = orientation(C, D, B)

The general case intersection test becomes:

if o1 * o2 < 0 and o3 * o4 < 0:
    return True

This handles all proper crossings.

Understanding the Geometry

Consider:

A------B
    /
   /
  /
 C------D

Point C and point D lie on opposite sides of line AB.

Similarly, A and B lie on opposite sides of line CD.

Both conditions hold simultaneously.

The segments intersect.

Orientation provides exactly the information needed to detect this situation.

Implementing the General Test

First define orientation:

def orientation(a, b, c):
    return (
        (b.x - a.x) * (c.y - a.y)
        - (b.y - a.y) * (c.x - a.x)
    )

Then:

def intersects_proper(a, b, c, d):
    o1 = orientation(a, b, c)
    o2 = orientation(a, b, d)

    o3 = orientation(c, d, a)
    o4 = orientation(c, d, b)

    return o1 * o2 < 0 and o3 * o4 < 0

This detects interior crossings but does not handle collinear cases.

Endpoint Touching

Consider:

A------B------C

Segment:

AB

touches segment:

BC

at endpoint B.

Some applications consider this an intersection.

Others consider it a special case.

To support endpoint touching, comparisons must include zero:

o1 * o2 <= 0
o3 * o4 <= 0

However, this alone is insufficient because collinear segments require additional handling.

Detecting Collinear Points on a Segment

Suppose:

A---------B
      C

and:

orientation(A,B,C) = 0

Point C lies somewhere on the line AB.

To determine whether C lies within the segment bounds:

def on_segment(a, b, p):
    return (
        min(a.x, b.x) <= p.x <= max(a.x, b.x)
        and
        min(a.y, b.y) <= p.y <= max(a.y, b.y)
    )

This test assumes collinearity has already been established.

Complete Segment Intersection Algorithm

def segments_intersect(a, b, c, d):
    o1 = orientation(a, b, c)
    o2 = orientation(a, b, d)

    o3 = orientation(c, d, a)
    o4 = orientation(c, d, b)

    if o1 * o2 < 0 and o3 * o4 < 0:
        return True

    if o1 == 0 and on_segment(a, b, c):
        return True

    if o2 == 0 and on_segment(a, b, d):
        return True

    if o3 == 0 and on_segment(c, d, a):
        return True

    if o4 == 0 and on_segment(c, d, b):
        return True

    return False

This handles:

  • Proper crossings
  • Endpoint touching
  • Collinear overlap
  • Degenerate cases

Computing Line Intersections

Sometimes the question is not merely whether two lines intersect but where.

Consider:

Line 1:
A + t(B - A)

Line 2:
C + u(D - C)

The intersection occurs when:

A + t(B - A)
=
C + u(D - C)

This produces a system of two equations with two unknowns.

Let:

r = B - A
s = D - C

Then:

A + tr
=
C + us

Solving yields:

t =
cross(C - A, s)
/
cross(r, s)

provided:

cross(r, s) ≠ 0

The intersection point is:

A + tr

Example

Line 1:

A = (0,0)
B = (4,4)

Line 2:

C = (0,4)
D = (4,0)

Vectors:

r = (4,4)
s = (4,-4)

Compute:

cross(r,s)
=
4(-4)-4(4)
=
-32

Nonzero result means lines are not parallel.

Next:

cross(C-A,s)
=
cross((0,4),(4,-4))
=
-16

Therefore:

t = (-16)/(-32)
   = 1/2

Substitute:

(0,0) + 1/2(4,4)
=
(2,2)

The lines intersect at:

(2,2)

Parallel Lines

Two lines are parallel when:

cross(r,s)
=
0

The direction vectors have identical slopes.

Example:

(1,2)
(2,4)

Cross product:

1×4 - 2×2
=
0

No unique intersection exists.

Coincident Lines

Consider:

Line 1: y = x
Line 2: y = x

Every point on one line lies on the other.

In this situation:

cross(r,s)=0

and

cross(C-A,r)=0

The lines coincide.

Instead of one intersection point, infinitely many exist.

Segment algorithms must handle this case separately.

Numerical Robustness

Floating-point geometry introduces significant complications.

Instead of:

cross(r, s) == 0

use:

EPS = 1e-9

abs(cross(r, s)) < EPS

Near-parallel lines frequently produce tiny nonzero values caused by rounding.

Robust geometry libraries often use exact predicates for critical operations.

Applications

Polygon Clipping

Every clipping operation repeatedly computes:

edge-edge intersections

between subject polygons and clipping boundaries.

Sweep-Line Algorithms

Event processing often depends on detecting intersections between neighboring segments.

Computer Graphics

Ray tracing computes millions of intersections per frame.

Geographic Information Systems

Road networks and boundaries are assembled from intersection computations.

Robotics

Collision detection relies on segment and polygon intersection tests.

Complexity Analysis

Orientation:

O(1)

On-segment check:

O(1)

Complete segment intersection:

O(1)

Line intersection computation:

O(1)

No loops or recursion are required.

Common Pitfalls

Ignoring Collinear Overlap

Many implementations correctly detect crossings but fail when segments overlap on the same line.

Forgetting Endpoint Intersections

Touching endpoints are often valid intersections.

Requirements should be defined explicitly.

Comparing Floats Directly

Avoid:

cross == 0

Use epsilon comparisons.

Assuming Unique Intersections

Parallel and coincident lines require separate logic.

The general formula only works when a unique solution exists.

Overflow

Large integer coordinates may overflow intermediate cross-product calculations.

Use sufficiently large numeric types.

Discussion

Segment intersection is one of the foundational predicates of computational geometry. Orientation testing provides the underlying mechanism, while bounding-box checks and collinearity handling complete the solution. Many seemingly unrelated geometric algorithms eventually reduce to repeated intersection queries. Once robust intersection testing becomes available, higher-level structures such as polygon clipping, sweep-line algorithms, visibility graphs, motion planning systems, and map-processing pipelines become much easier to construct.