13.3 Point in Polygon 707
all the trapezoids of all the strips. The sort of the y-values requires O(n log n) time,
although any particular polygon might only have a very small number of distinct
y-values. The trapezoids themselves are sorted by sorting the line segment left and
right boundaries of the trapezoids within each strip. The boundaries never overlap,
so the sort is well defined. This sort is also O(n log n) in time. The data structure
uses binary search trees to allow dynamic construction. One tree is used to sort the
horizontal strips, the other tree is used to sort the trapezoids within a strip. The
point-in-polygon test amounts to searching the first binary tree to locate the strip
containing the y-value of the input point, then searching the second binary tree to
locate the trapezoid that contains the point, if it exists. If no trapezoid is found, the
point must lie outside the polygon.
13.3.5 A Grid Method
This method is suggested by Haines in Heckbert (1994). An axis-aligned bounding
box is constructed for the polygon. A grid is imposed on the box, and the polygon is
rasterized into it. The grid cells are labeled based on their relationship to the polygon
as fully inside, fully outside, or indeterminate. The indeterminate cells are assigned
a list of edges that intersect the cell, and one corner of the cell is tagged as inside or
outside accordingly.
The grid data structure supports a constant-time point-in-polygon test when
the point occurs in a fully inside or fully outside cell. If the point occurs in an
indeterminate cell, the line segment connecting the test point and the tagged corner
is tested for intersection with all the edges in the cell’s edge list. The parity of the
number of intersections and knowing if the tagged corner is inside or outside tell you
whether or not the test point is inside or outside. This is exactly the point-in-general-
polygon test, but confined to the indeterminate cell. Because of the localization, the
number of intersection calculations is far fewer than those used in the algorithm that
counts intersections for all polygon edges. The containment test is O(1), but you pay
the price in O(nm) memory for an n × m grid and in O(nm) time to rasterize the
polygon and classify the grid cells.
Haines notes that care must be taken when a polygon edge crosses (or nearly
crosses) a grid corner. The corner is unclassifiable. Numerous options are given: deal
with the numerical precision and topological problems, regrid a slightly modified
bounding box (jittering, so to speak) in hopes that the problem goes away, or tag
entire cell edges and use the horizontal or vertical segment connecting the test point
and cell edge in the intersection counting with the edges in the cell’s edge list. If you
choose to cope with the numerical precision and topological problems, you might
as well just use the point-in-general-polygon test and deal with the same problems,
saving yourself the memory overhead and expensive preprocessing that goes with
the grid method. Regridding the bounding box is also an expensive proposition,
especially if the regridding must occur often (or worse, occurs for each test point).