Click here to Skip to main content
Click here to Skip to main content

Tagged as

Is a Point inside a Polygon?

, 9 Mar 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
A short and efficient algorithm for checking point inclusion in a polygon.

Introduction

The question whether a point is contained within a polygon is a straight-forward one for us to answer visually. However, devising an algorithm that answers this question efficiently and covers most practical cases might still be a little difficult. In this article I will try to describe a short and efficient algorithm named PNPoly by W. Randolph Franklin which solves this problem.

Background

Often when dealing with 2D surfaces, map object or even simple hit tests a fast and efficient implementation is required. Algorithms that address these issues may vary in subset of polygons they are dealing with, whether they are convex, concave, with or without holes and so forth. In this article I will cover the broader case of both convex and concave polygons, but will not address the issue of holes, since it depends on the polygon representation of holes. 

The algorithm

Preliminary Check

First of all and before running this algorithm, it is advisable to perform a simple check that our target point resides outside the bounding rectangle. It's quick and straight-forward to calculate the bounding rectangle and can even be done "offline", while inserting points to the polygon. Then, the check whether our target point is outside the bounding rectangle should look like this:

if (p.x < minX || p.x > maxX || p.y < minY || p.y > maxY) {
    // We're outside the polygon!
}

where p is our target point and minX/maxX/minY/maxY are the bounding rectangle coordinates. If the above check evaluates to true we can simply return false and avoid further, more costly calculations.

Core algorithm (PNPoly)

Here is an implementation of the algorithm in C (taken from W. Randolph Franklin's website):

<a name="The C Code"></a>int pnpoly(int nvert, float *vertx, float *verty, float testx, float testy)
{
  int i, j, c = 0;
  for (i = 0, j = nvert-1; i < nvert; j = i++) {
    if ( ((verty[i]>testy) != (verty[j]>testy)) &&
	 (testx < (vertx[j]-vertx[i]) * (testy-verty[i]) / (verty[j]-verty[i]) + vertx[i]) )
       c = !c;
  }
  return c;
}

This is it! no additional code, a single loop that iterates over the array of points just once and toggles a flag. But what does it do?!? Let me explain. 

First of all, notice that each iteration considers two adjacent points and the target point. Then the if statement evaluates two conditions:

  1. Y-value of our target point is within the range [verty[j], verty[i]).
  2. X-value of our target point is below the linear line connecting the point j and i.

(If you're having problems to see this second condition, just write down the linear equation of the line, reorganize the expression a little bit and place testy as the free variable).

Every time the above two conditions are met, we toggle the flag c. So we return true if above conditions are met odd number of times and false otherwise. But what does that mean?!?

Correctness

Let's make the following observation:

a point is within a polygon if and only if its y-value is within the range of the projected polygon on the y-axis and the x-value of the point is below odd number of polygon edges. I will not prove this mathematically, but quick look at few examples will convince yourself that this is true. Notice that this observation is valid for holes too.

Now, if you would go back to the previous section which describes the two conditions you will immediately see that the algorithm is simply checking that the observation is met odd number of times.

Complexity 

Since the algorithm simply iterates through the points collection its runtime complexity is O(n), where n is the number of polygon points. 

References 

Further Reading  

  • Haines, Eric, "Point in Polygon Strategies," Graphics Gems IV, ed. Paul Heckbert, Academic Press, p. 24-46, 1994.
  • Haines, Eric, "Point in Polygon Strategies," web-page.
  • Thread at StackOverflow.com, Point in Polygon aka hit test, link.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

grinbergnir
Software Developer (Senior)
Israel Israel
No Biography provided

Comments and Discussions

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141030.1 | Last Updated 9 Mar 2012
Article Copyright 2012 by grinbergnir
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid