So I've implemented a very unoptimized version of the Winding Number and Crossing Number algorithms found at http://geomalgorithms.com/a03-_inclusion.html, but I've come across a case where the Winding Number algorithm fails to yield the expected result.
I've created a polygon and three points as graphed here. For P0 and P2 both algorithms behave predictably. However, for point P1 (a point contained by a "null space" within the polygon's bounds) the crossing number algorithm succeeds while the winding number algorithm fails to recognize the point as not being contained by the polygon.
This is the algorithm as implemented:
int wn_PnPoly(Vector2 P, Vector2[] V)
{
int n = V.Length - 1;
int wn = 0; // the winding number counter
// loop through all edges of the polygon
for (int i = 0; i < n; i++)
{ // edge from V[i] to V[i+1]
if (V[i].y <= P.y)
{ // start y <= P.y
if (V[i + 1].y > P.y) // an upward crossing
if (isLeft(V[i], V[i + 1], P) > 0) // P left of edge
++wn; // have a valid up intersect
}
else
{ // start y > P.y (no test needed)
if (V[i + 1].y <= P.y) // a downward crossing
if (isLeft(V[i], V[i + 1], P) < 0) // P right of edge
--wn; // have a valid down intersect
}
}
return wn;
}
float isLeft(Vector2 P0, Vector2 P1, Vector2 P2)
{
return ((P1.x - P0.x) * (P2.y - P0.y)
- (P2.x - P0.x) * (P1.y - P0.y));
}
Am I missing something obvious here? Why does the crossing number algorithm succeed in this case while winding number fails?