← Back to index

Point-in-polygon (ray casting)

Cast a horizontal ray from the point and count how many polygon edges it crosses. An odd count means the point is inside — works for concave shapes too. The polygon is regenerated with a random number of vertices (5–8) and random radii, so it's usually concave.

See also: Point-in-triangle — the corresponding test for a triangle, using barycentric coordinates.

Pseudocode

inside = false
for each edge (a, b):
    if (a.y > p.y) != (b.y > p.y):                       // edge straddles the ray
        xCross = a.x + (p.y - a.y) * (b.x - a.x) / (b.y - a.y)
        if p.x < xCross:
            inside = !inside
return inside

Source

function pointInPolygon(px, py, poly) {
    let inside = false
    for (let i = 0, j = poly.length - 1; i < poly.length; j = i++) {
        const xi = poly[i].x, yi = poly[i].y
        const xj = poly[j].x, yj = poly[j].y
        if ((yi > py) !== (yj > py)) {
            const xCross = xi + (py - yi) * (xj - xi) / (yj - yi)
            if (px < xCross) inside = !inside
        }
    }
    return inside
}