# geo.point-in-polygon Whether a point lies inside a polygon: geofences, delivery zones, "is this address in the congestion charge area". ## Rules - **The boundary is inside.** A point exactly on an edge or a vertex returns true. Plain ray casting answers boundary points inconsistently (a point on the east edge of a square comes out outside, one on the west edge inside), so every edge is checked first: zero cross product and within the edge's extent. - **Even-odd rule.** A ray is cast towards increasing longitude and crossings are counted, with a half-open test on latitude so a ray passing exactly through a vertex counts it once, not twice. For a self-intersecting polygon the overlapping parts count as outside. - **Rings.** Vertices in order, either winding. Closing the ring (repeating the first vertex at the end) is optional. Fewer than 3 distinct vertices is an error. - **Coordinates** must be in -90..90 and -180..180. ## What it deliberately does not do It works on the flat longitude/latitude plane, treating edges as straight lines in degrees. That is how GeoJSON polygons and most map tools draw them, and it is accurate for zones of city or county size. It does not handle holes (test the outer ring, then each hole), polygons that cross the antimeridian (split them), or polygons that contain a pole. ## Floating point Only + − × ÷ and comparisons are used, in the same order in TypeScript, Python and Rust, so all three give the same answer for every input, including points so close to an edge that rounding decides them. Boundary detection is exact when the coordinates' products are exact (integers, or few decimals at small scale); for a point within about 1e-15 degrees of an edge given in arbitrary decimals, rounding decides, identically in every language. On 4,000 random cases, half of them on an integer grid to hit edges and vertices, the three languages agreed on every answer.