Skip to content
Part IA Lent Term

Winding Numbers and Point-in-Polygon

The Problem

Given a polygon PP (assumed planar, closed, and simple unless stated otherwise) and a point QQ, determine whether QQ is inside or outside PP.

Two main approaches exist: ray casting and winding numbers. For simple polygons they produce identical results. For complex (self-intersecting) polygons, they may differ, and the winding number provides a more useful definition.

Ray Casting (Crossing Number)

Shoot a ray (semi-line) from QQ in any direction. Count the number of intersections of the ray with polygon edges:

  • Odd count: QQ is inside
  • Even count: QQ is outside

Ray casting diagram

Why It Works

The polygon divides the plane into inside and outside regions. Every time the ray crosses an edge, it moves from inside to outside (or vice versa). Since the ray starts at QQ and extends to infinity (which is outside), the parity of crossings determines the initial region.

Awkward Cases

The ray may pass through a vertex or be collinear with an edge. Solutions:

  1. Shoot a horizontal ray (avoids floating-point ambiguity with vertical comparisons).
  2. If the ray hits a vertex, check the neighbouring vertices:
    • If both neighbours are on the same side of the ray (both above or both below), the ray grazed the vertex — no crossing.
    • If neighbours are on opposite sides, the edge was crossed.
  3. If a neighbour is also on the ray, skip it and check the next vertex in the same direction around the perimeter.

Alternatively, pick a random ray direction; with probability 1 it will miss all vertices (assuming finite precision is not an obstacle).

Complexity

For nn vertices: Θ(n)\Theta(n) time — each edge is tested once.

Winding Number

The winding number of QQ with respect to polygon PP is the number of times the polygon “winds around” QQ. Formally:

w=12πi=1nθiw = \frac{1}{2\pi} \sum_{i=1}^{n} \theta_i

where θi\theta_i is the signed angle subtended by edge pipi+1p_i p_{i+1} at point QQ.

  • w=0w = 0: QQ is outside
  • w=±1w = \pm 1: QQ is inside (for simple polygons)
  • w>1|w| > 1: QQ is inside a self-intersecting polygon, wound around multiple times

Implementation Without Trigonometry

Computing actual angles via arctangent is slow and suffers floating-point error. Instead, use cross products and dot products to compute the signed contribution of each edge.

For each edge ABAB, the signed angle contribution can be determined from:

QA×QBandQAQB\overrightarrow{QA} \times \overrightarrow{QB} \quad \text{and} \quad \overrightarrow{QA} \cdot \overrightarrow{QB}

The cross product gives the sine of the angle (signed); the dot product gives the cosine. The quadrant of the angle determines the exact contribution to the winding number without needing arctan\arctan.

Intuition

Imagine a string attached to a post at point QQ. Walk around the polygon perimeter holding the string. When you return to the start, count how many times the string is wrapped around the post. Odd wraps = inside, even = outside.

Comparison

MethodSimple PolygonsComplex PolygonsTimeTrig?
Ray castingΘ(n)\Theta(n)AmbiguousΘ(n)\Theta(n)No
Winding numberΘ(n)\Theta(n)Well-definedΘ(n)\Theta(n)Can avoid

Worked Example: Ray Casting

Polygon: square with vertices (0,0),(4,0),(4,4),(0,4)(0,0), (4,0), (4,4), (0,4). Test point Q=(2,2)Q = (2,2) with a horizontal ray to the right.

Edges checked:

  • (0,0)(4,0)(0,0)\to(4,0): y=0y=0, ray at y=2y=2, no intersection.
  • (4,0)(4,4)(4,0)\to(4,4): vertical edge at x=4x=4, ray from x=2x=2 hits at (4,2)(4,2). Intersection! Count = 1.
  • (4,4)(0,4)(4,4)\to(0,4): y=4y=4, no intersection.
  • (0,4)(0,0)(0,4)\to(0,0): vertical edge at x=0x=0, but ray goes right from x=2x=2, so no intersection.

Count = 1 (odd) → inside. Correct.

Summary

ConceptDetail
Ray castingCount edge crossings; odd = inside
Winding numberSum signed angles / 2π2\pi; 0 = outside
Horizontal raySimplest to implement
Vertex handlingCheck neighbours: same side = grazing (no count)
ComplexityΘ(n)\Theta(n) for both methods
No trigonometryUse cross products and dot products for winding number