Learn
Lesson · Geometric Algorithms · Area, distance and the measured column

Inside, by Parity and by Winding

A horizontal ray from the query point crosses the boundary an odd number of times exactly when the point is inside — provided the rule for counting a crossing is written so that a ray passing through a vertex is not counted twice. A different definition counts how many times the boundary winds around the point. On a simple polygon the two agree; on a self-intersecting one they are different questions, and the page tests for simplicity before claiming they must match.

count the edge when exactly one endpoint is strictly above the ray odd crossings inside, even outside; the ray's direction does not matter the comb at height 4: 6 crossings outside, 5 crossings inside, same line the winding number counts signed turns of the boundary around the point simple polygon: parity and winding agree, and the page checks simplicity first on the boundary is a third answer, and both routes report it
Two definitions of inside, and the hypothesis that makes them one

Core ideas

What this lesson establishes

The half-open rule that makes ray casting work, the second definition, and the condition under which they are the same question.

1

The vertex case is handled by a rule, not by a nudge

A ray that passes exactly through a vertex touches two edges, and counting both or neither gives the wrong parity. The fix is to count an edge only when exactly one of its endpoints is STRICTLY above the ray's height: a vertex at exactly the ray's height belongs to whichever of its two edges has its other end above. That makes each genuine crossing count once, with no perturbation of the input and no tolerance.

2

Winding is a different question with the same answer here

The winding number counts how many times the boundary travels counter-clockwise around the point, minus the clockwise times. For a simple polygon it is +1 or −1 inside and 0 outside, so winding ≠ 0 and crossings odd agree. For a figure-eight they do not: a point in one lobe can have winding 0 and odd parity, or winding 2 and even parity, depending on the shape. The page reports both numbers and checks simplicity before saying they must match.

3

On the boundary is a third answer

A point lying exactly on an edge is neither inside nor outside, and both routes detect it directly by testing each edge with an exact on-segment predicate. The page reports it as its own verdict rather than forcing it into one of the other two, because which of them a boundary point falls into is a convention and not a fact.

The material

Casting a ray correctly, and the second definition beside it

The half-open rule, the parity theorem, the winding number, and the simplicity test the page runs before comparing them.

Definition · Ray parity, with the half-open rule

For 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 algorithm

For 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 places

The 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 number

The 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.

Interactive

The doubled area, its sign, and whether a point is inside

Two exact formulas for the area, and two definitions of inside

Area, orientation, and insidetwo formulas for the area and two definitions of inside
the polygonthe ray from the query pointinsideoutside

Method

Testing a point against a polygon

Decide the boundary convention first, then count with a rule that has no ties in it.

1

Test for the boundary separately and first

Run an exact on-segment predicate against every edge. A point on the boundary is its own verdict, and forcing it into inside or outside is a convention that the consumer, not the geometry, should choose.

2

Count with the strictly-above rule

An edge counts when exactly one endpoint is strictly above the ray's height. Write it that way rather than as a pair of inequalities you reason about case-by-case, because the whole point of the rule is that it removes the cases.

3

Use the orientation determinant to place the crossing, not a division

Whether the crossing is at x ≥ qx can be decided by the sign of orient(vᵢ, vᵢ₊₁, q) combined with which way the edge runs, and that is exact. Computing the intersection's x coordinate and comparing it introduces a division for no reason.

4

Check simplicity before claiming the two definitions agree

Test every pair of non-adjacent edges for intersection. If any pair meets, parity and winding are answering different questions and the page should report both rather than asserting either. On a convex hull, which is always simple, the question does not arise.

Rays, vertices, and two definitions

Score 0 / 0

The comb, at seven points on one horizontal line

The comb has 14 vertices, three teeth rising from y = 2 to y = 6, and doubled area 96. Every query below is at height y = 4.

query crossings parity verdict (−1, 4) 6 even outside ( 1, 4) 6 even outside the leftmost notch ( 3, 4) 5 odd INSIDE the first tooth ( 5, 4) 4 even outside a notch ( 7, 4) 3 odd INSIDE the second tooth ( 9, 4) 2 even outside a notch (11, 4) 1 odd INSIDE the third tooth 2A = 96, area 48, counter-clockwise simple polygon: yes, no two non-adjacent edges meet winding number at (−1, 4) = 0, at (3, 4) = 1 parity and winding agree at every one of the seven

The count decreases by exactly one at each step to the right, and the parity therefore alternates. That is not a property of combs; it is the proof of the parity theorem, made into a table. Each step to the right passes exactly one edge, so exactly one edge stops being ahead of the ray.

The two leftmost queries are both outside and both have 6 crossings, which is the one place the pattern pauses. (1, 4) sits above the leftmost notch, whose floor is the edge at y = 2; the polygon's left side runs only from (0, 2) down to (0, 0), so at height 4 there is no boundary at all to its left. The six edges that straddle y = 4 are the vertical ones at x = 2, 4, 6, 8, 10 and 12, and the ray from (1, 4) meets every one of them just as the ray from (−1, 4) does.

For a faded rehearsal, predict the crossing count for a query at (13, 4), to the right of everything. The supplied first move is that a ray from outside to the right of the whole polygon crosses nothing. Then predict the winding number there, and say what the parity would be for a query at (6, 4) — a point exactly on a vertical edge — and which of the three verdicts the page would report.

Common mistakes

1
Nudging the query point to avoid a vertexIt changes the question, and on grid-aligned data the nudged point often lands on another vertex. The half-open rule costs nothing and removes the case entirely, which is the general pattern here: degenerate inputs get a rule, not a perturbation.
2
Assuming parity and winding are the same testThey agree on simple polygons, which is most of what anyone draws, so the difference goes unnoticed until a self-intersecting input arrives — and then the disagreement looks like a bug in one of them. The page checks simplicity explicitly, in quadratic time, and reports what it found.
3
Folding “on the boundary” into inside or outside silentlyIt is a convention, and different consumers want different ones: a filling algorithm and an adjacency test disagree about it deliberately. Detect it, report it as a third verdict, and let whatever consumes the answer decide. Both routes on this page detect it with an exact on-segment test, so the detection itself is never in doubt.

Check your understanding

✓
Finish when you can write the ray-crossing rule so that a ray through a vertex needs no special case, and say when winding and parity part company.

You should be able to state the half-open condition and justify it on both vertex cases, prove the parity theorem from the side-change argument, define the winding number and say what it is inside a simple polygon, and name the hypothesis that has to be checked before treating the two as one test.

Note: The last lesson of this course leaves predicates behind and goes back to distance. “The Closest Pair and the Strip” is a divide-and-conquer recursion whose whole correctness rests on a pair that might straddle the dividing line, and whose famous bound of seven neighbours per strip point is measured on the page against the number of comparisons actually made.

Kept in this browser only, for you. Nothing is sent anywhere and nothing checks it. Carry it to another device.

Feedback and recommendations

Something to change about this lesson? Write it down, tick it off when it is handled, and export the list when you want to act on it. Kept in this browser only: nothing is sent anywhere, and nobody is notified.

No recommendations yet for this lesson.