1

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?

Ian Clayman
  • 21
  • 1
  • 3

1 Answers1

0

These two methods are not the same criterion.

In the non-zero or winding rule, the directions of the line segments matter. The algorithm checks whether a line segment crosses the outgoing ray from the left or from the right and counts how often each case occurs. The point is considered ouside only if

The crossing-number or even-odd rule just counts how often a line is crossed. Every time you cross a line you go either from inside to outside or vice versa, so an even number of crossings means the point is outside.

If you go right from P1 in your example, you cross two lines, so the even-odd rule tells you P1 isn't in the polygon. But these two lines have the same orientation: If your overall shape is drawn in a clockwise fashion, both lines are drawn from top to bottom. In the words of the article you linked, the polygon winds around P1 twice. According to the winding rule, P1 is part of your polygon. Your program shows the correct behaviour.

Vector graphics programs and formats distinguish between these two rules. For example SVG has a fill-rule attribute, where you can set the behaviour. Postscript has fill and eofill operators for filling paths with the winding rule and even-odd rule respectively. The default is usually the winding rule, so that designers must take care to orient their paths correctly.

M Oehm
  • 28,726
  • 3
  • 31
  • 42
  • I see now that I missed the double winding concept. However, I noticed another edge case that I'm not sure how to handle: a point (10,5) which would exist on the rightmost line of the polygon. Both algorithms fails to consider this point as contained within the polygon, but intuitively it should be. Is there material as to how to improve the algorithm for robustness, including accommodating the case where the polygon is a Bezier spline? – Ian Clayman Apr 27 '20 at 16:39
  • That's also the desired behaviour: The odd-even rule discounts (10, 5), because it crosses two lines, and the winding-rule discounts it, because the two lines cross the ray in different directions. If you draw the big outer square clockwise, you pass the top left inner square clockwise, too, but you pass the lower right inner square anticlockwise. – M Oehm Apr 27 '20 at 17:02
  • The real edge cases are where your ray and the lines are collinear,e.g. (3, 8), or where they just intersect at one of the polygon's nodes. It gets even hairier when you have to deal with floating-point numbers. The path can also contain curves, but keep in mind that there may be multiple points where the ray crosses a Bezier curve. These problems are the foundation of all vector graphics, so "point in polygon", "polygon rendering", "polygon clipping" and so on may be useful terms to feed to your search engine. – M Oehm Apr 27 '20 at 17:07
  • This paper - [The Point in Polygon Problem for Arbitrary Polygons](https://www.inf.usi.ch/hormann/papers/Hormann.2001.TPI.pdf) - has a good discussion on the relationship between even-odd and winding number-based methods of defining the interior of a polygon. The refined algorithm for calculating point-in-polygon is also very helpful. – RaffleBuffle Apr 27 '20 at 20:24