Homeβ€Ί DSAβ€Ί Point in Polygon β€” Ray Casting and Winding Number Algorithms

Point in Polygon β€” Ray Casting and Winding Number Algorithms

Where developers are forged. Β· Structured learning Β· Free forever.
πŸ“ Part of: Geometry β†’ Topic 3 of 4
Learn point-in-polygon algorithms: ray casting (even-odd rule) and winding number.
βš™οΈ Intermediate β€” basic DSA knowledge assumed
In this tutorial, you'll learn:
  • Ray casting: count horizontal ray crossings β€” odd=inside, even=outside. O(n) per query.
  • Winding number: more robust for complex/self-intersecting polygons. Used in GIS applications.
  • Edge cases: ray through vertex or along edge require careful handling in ray casting.
✦ Plain-English analogy ✦ Real code with output ✦ Interview questions
⚑ Quick Answer
Given a polygon and a point, is the point inside? Ray casting: cast a ray from the point in any direction, count how many times it crosses the polygon boundary. Even = outside, odd = inside. It sounds simple but edge cases β€” rays passing exactly through vertices or along edges β€” require careful handling.

Point-in-polygon (PIP) is one of the most frequently implemented computational geometry algorithms. GIS systems (is this GPS coordinate in this city boundary?), game physics (is the player inside this room?), UI hit-testing (was this click inside this region?), and graphics rendering all need PIP. Two main algorithms: ray casting (even-odd rule, simple) and winding number (handles self-intersecting polygons, more robust).

Ray Casting Algorithm

Cast a horizontal ray from the point to +infinity. Count boundary crossings β€” odd = inside, even = outside.

point_in_polygon.py Β· PYTHON
123456789101112131415161718192021222324
def point_in_polygon_ray(point, polygon) -> bool:
    """
    Ray casting algorithm: cast ray from point to +x infinity.
    Count edge crossings β€” odd = inside, even = outside.
    """
    x, y = point
    n = len(polygon)
    inside = False
    j = n - 1
    for i in range(n):
        xi, yi = polygon[i]
        xj, yj = polygon[j]
        # Does edge i-j cross the horizontal ray from (x,y) to +infinity?
        if ((yi > y) != (yj > y)) and \
           (x < (xj - xi) * (y - yi) / (yj - yi) + xi):
            inside = not inside
        j = i
    return inside

# Square polygon
square = [(0,0),(4,0),(4,4),(0,4)]
print(point_in_polygon_ray((2,2), square))   # True (inside)
print(point_in_polygon_ray((5,2), square))   # False (outside)
print(point_in_polygon_ray((0,0), square))   # False (vertex β€” edge case)
β–Ά Output
True
False
False

Winding Number Algorithm

Winding number counts how many times the polygon winds around the point. Non-zero = inside. More robust than ray casting for self-intersecting polygons and complex GIS boundaries.

winding_number.py Β· PYTHON
12345678910111213141516171819
def winding_number(point, polygon) -> int:
    """Winding number: non-zero = inside."""
    x, y = point
    wn = 0
    n = len(polygon)
    for i in range(n):
        x1, y1 = polygon[i]
        x2, y2 = polygon[(i+1) % n]
        if y1 <= y:
            if y2 > y and orientation((x1,y1),(x2,y2),(x,y)) > 0:
                wn += 1
        else:
            if y2 <= y and orientation((x1,y1),(x2,y2),(x,y)) < 0:
                wn -= 1
    return wn

square = [(0,0),(4,0),(4,4),(0,4)]
print(winding_number((2,2), square))  # 1 (inside)
print(winding_number((5,2), square))  # 0 (outside)
β–Ά Output
1
0

🎯 Key Takeaways

  • Ray casting: count horizontal ray crossings β€” odd=inside, even=outside. O(n) per query.
  • Winding number: more robust for complex/self-intersecting polygons. Used in GIS applications.
  • Edge cases: ray through vertex or along edge require careful handling in ray casting.
  • For convex polygons: O(log n) using binary search on angles from centroid.

Interview Questions on This Topic

  • QExplain the ray casting algorithm and handle the vertex edge case.
  • QWhen would you use winding number over ray casting?
  • QHow would you optimise point-in-polygon for 10^6 queries against the same polygon?

Frequently Asked Questions

What is the performance of point-in-polygon for many queries?

Single query: O(n). For many queries against the same polygon: preprocess with a grid spatial index or R-tree β€” reduces average query to O(1) or O(log n). NumPy's vectorised ray casting handles millions of points per second against a single polygon.

πŸ”₯
Naren Founder & Author

Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.

← PreviousPolygon Area β€” Shoelace FormulaNext β†’Rotating Calipers β€” Diameter and Width
Forged with πŸ”₯ at TheCodeForge.io β€” Where Developers Are Forged