Definition · Ray parity, with the half-open ruleFor a query point q and a polygon with vertices v₁, …, vₙ, cast the horizontal ray from q in the direction of increasing x. An edge vᵢvᵢ₊₁ is counted when exactly one of yᵢ, yᵢ₊₁ is strictly greater than qy, and the intersection of the edge's line with the ray's line lies at x ≥ qx. The point is inside when the number of counted edges is odd.
The strictly-above test is doing the delicate work. Written as yᵢ > qy on one end and yᵢ₊₁ ≤ qy on the other, the condition treats the horizontal line through q as half-open: a vertex exactly at that height counts as below. So a ray through a vertex where the boundary passes from below to above counts exactly one of the two edges, and a ray through a vertex where the boundary touches and turns back counts either both or neither — which is the right answer in both cases.
Theorem · The Jordan parity theorem, as an algorithmFor a simple polygon and a point q not on the boundary, the number of edges counted by the rule above is odd if and only if q is in the interior.
Take the ray from q and travel along it to infinity. Beyond the polygon's bounding box the point is certainly outside. Every time the ray properly crosses the boundary, the side changes; every time it touches a vertex without passing through, it does not. The counting rule is exactly a bookkeeping of the first kind of event and not the second: a vertex at the ray's height is assigned to the edge going strictly above it, so a pass-through contributes one and a touch-and-return contributes zero or two.
Hence the parity of the count equals the number of side changes between q and infinity. Since the far end is outside, q is inside exactly when that number is odd.
□
Example · A comb, and the same horizontal line at seven placesThe lab's comb has 14 vertices and three upward teeth, with doubled area 96 so an area of 48. Query at (−1, 4), outside to the left: the ray crosses 6 edges, even, outside. Query at (3, 4), inside the first tooth: 5 crossings, odd, inside. At (5, 4), in the notch between teeth: 4 crossings, outside. At (7, 4): 3, inside. At (9, 4): 2, outside. At (11, 4): 1, inside. Every one of those is on the same horizontal line, and the count falls by one at each boundary crossing exactly as the theorem says.
That sequence — 6, 5, 4, 3, 2, 1, 0 as the query point moves right — is the proof made visible. Each step to the right passes one edge, reducing the number of edges still ahead of the ray by one, and flipping the parity. It is worth typing those seven query points into the lab in order.
The winding number, and where it separates
Definition · The winding numberThe winding number of a closed polygon about a point q not on it is the net number of counter-clockwise revolutions the boundary makes around q. It is computed by walking the edges and adding +1 each time an edge crosses the horizontal line through q upward on the right, and −1 each time one crosses it downward on the right — where “on the right” is decided by an orientation determinant.
For a simple polygon the winding number is +1 inside if the vertices were typed counter-clockwise, −1 if clockwise, and 0 outside. So winding ≠ 0 and odd parity agree. The lab's L-shaped example has winding 1 at an interior point; the clockwise square from the previous lesson has winding −1 at its centre, and the point is inside both times.
For a polygon that crosses itself the two genuinely differ. A doubly wound loop has winding 2 at its centre and even parity, so parity says outside and winding says inside twice over. Neither is wrong; they answer different questions, and which one a consumer wants depends on whether it is filling a region or integrating around a contour. The page tests non-adjacent edge pairs for intersection before reporting that the two must agree, and says so in amber when the polygon is not simple.
Three routes, because two agreeing could be two copies of one mistake
Besides parity and winding, the arithmetic checker behind this kit casts the ray UPWARD instead of rightward and requires that verdict to agree too, on every preset and on thousands of random query points against random convex hulls. A ray cast in a different direction shares no sub-expression with one cast rightward, so a mistake in the half-open comparison shows as a disagreement rather than as a consistent wrong answer.
That is the same discipline as the two area formulas and the three determinant routes. It is not belt and braces for its own sake: a point-in-polygon test that is wrong only on rays through vertices will pass any test suite whose query points were chosen carelessly, and the vertex case is the one that actually occurs on grid-aligned data.