PHP point-in-polygon algorithm

The point-in-polygon algorithm allows you to programmatically check if a particular point is inside a polygon or outside of it. A common way to tackle the problem is to count how many times a line drawn from the point (in any direction) intersects with the polygon boundary. If the line and the polygon intersect an even number of times (or not at all), then the point is outside. If they intersect an odd number of times, the point is inside. It is true even for complex forms that have a lot of coordinates and thus create a very precise boundary.

Let’s see a sample image before we get to the code.

This shows how it can be determined if a point is inside or outside a polygon.Here, the lines drawn from point 1 intersect twice or not at all, because it is outside.

Point 2 is inside and thus the lines drawn from it intersect once or three times.

Even in special cases, such as point 3, we see that this method works: the line intersects twice and the point is therefore outside.

I use this approach in the PHP code below, which returns one of these 4 possible values:

  • inside if the point is inside the polygon.
  • outside if, you guessed it, the point is outside of the polygon.
  • vertex if the point sits exactly on a vertex AND $pointOnVertex = true (line 2)
  • boundary if the point sits on the boundary. If $pointOnVertex = false, then boundary is also returned if the point is on a vertex.

Using the point-in-polygon PHP code

Set the point(s) value(s) and an array containing your polygon vertices (in the form “Xcoordinate Ycoordinate”), then call the pointInPolygon function. The first and last polygon coordinates must be identical, to “close the loop”.

As you can see in the following example, it is easy to check multiple points at once. The code also works with negative coordinates, for the polygon as well as for the points to check.

Point in polygon - sampleThis will output:

point 1 (50 70): vertex
point 2 (70 40): inside
point 3 (-20 30): inside
point 4 (100 10): outside
point 5 (-10 -10): outside
point 6 (40 -20): inside
point 7 (110 -20): boundary

25 thoughts on “PHP point-in-polygon algorithm

  1. MrDog

    Very nice and saved me a lot of work. But one query – you say the last point in the polygon must be the same as the first one to close the loop which I understand – but the first one is (-50,30) and the last one is (-50,-30) which are not the same – which implies to me that the last value is not really needed?

    1. Michael Post author

      Thanks for pointing that out!
      It was a mistake (now corrected) in the sample. The last coordinate does have to be the same as the first one.


  2. Rhijul

    Is there a way to optimise the code to run the algorithm for searching multiple points. Basically if we can get the status of all the points whether they are inside or outside. I know we can run the same algorithm over all the points, but then the we will be repeating a lot of our intersection calculations and the algorithm would not be that efficient.

  3. Diego

    Thank you so much, the algorithm works like a charm with latitudes/longitudes… I will definitively buy you coffee :D

  4. Nilesh Nayak


    I have a set of points as detailed below.

    $pointlocation = new pointLocation();

    $pts[] = “51.22881787980134 -1.157684326171875″;
    $pts[] = “51.138432319543924 -1.043701171875″;
    $pts[] = “51.11990293528057 -0.998382568359375 “;
    $pts[] = “51.12248887705868 -0.9455108642578125″;
    $pts[] = “51.19483648846099 -0.778656005859375″;
    $pts[] = “51.222367645529715 -0.701751708984375″;
    $pts[] = “51.269648373496736 -0.696258544921875″;
    $pts[] = “51.30443311306082 -0.71685791015625″;
    $pts[] = “51.336617716006664 -0.770416259765625″;
    $pts[] = “51.350771787631196 -0.9468841552734375″;

    $centerpoint = “51.263217 -0.9525255999999445″;
    echo $pointlocation->pointInPolygon($centerpoint, $pts);

    This seems to show that the point is outside when in effect, it is inside.

    If I am not wrong, the following statement causes the issue.

    if ($point[‘y’] > min($vertex1[‘y’], $vertex2[‘y’]) and $point[‘y’] <= max($vertex1['y'], $vertex2['y']) and $point['x'] <= max($vertex1['x'], $vertex2['x']) and $vertex1['y'] != $vertex2['y']) {

    I am not sure what this statement is trying to do.

    Can you please shed light on this as we are using this in one of our projects.

    1. Michael Post author

      Hi Nilesh,

      Don’t forget that, as mentionned in the article, the first and last point of the polygon array must be identical, to close it ;)
      So, just add $pts[] = “51.22881787980134 -1.157684326171875″; as the last point and the script will return inside, as it should.

      Kind regards,


  5. Parth

    hey this how i am using this but it always show outside as result

    $pointLocation = new pointLocation();
    $points=array(“22.560019387 72.907277656″);
    $polygon = array(“72.9443135978394 22.5665187803137″,”72.9671445609741 22.5735726534814″,
    “72.9671445609741 22.5735726534814″,”72.9735818626099 22.5691343034821″,”72.9702344657593 22.5570470009717″,
    “72.9702344657593 22.5570470009717″,”72.9810920478516 22.5427786579349″,”72.9810920478516 22.5427786579349″,
    “72.9810920478516 22.5427786579349″,”72.9496780158692 22.5259718289148″,”72.9496780158692 22.5259718289148″,
    “72.9156890632324 22.5396077146951″,”72.9156890632324 22.5396077146951″,”72.9194656135254 22.5623576184676″,
    “72.9440990211182 22.5663998917189″,”72.9443135978394 22.5665187803137″);

    foreach($points as $key => $point) {
    echo “point ” . ($key+1) . ” ($point): ” . $pointLocation->pointInPolygon($point, $polygon) . “”;

    please help


    1. Michael Post author

      Hi Parth,

      It seems you switched the x and y values of the point, but even if it were x=72.907277656 and y=22.560019387, it would clearly be outside, as none of the polygon coordinates has x less than 7.91



  6. Jonas


    great work!
    I have a question, is there a way to make a “hole” in the middle of a polygon (like in the sample picture; point 3).

    Kind Regards from Germany


    1. Michael Post author

      Thanks Jonas,
      It is indeed currently not supported, but I’ll try to add it in a future version of the script. Anyway, the basic idea is to check the number of intersections with both boundaries (the external polygon and the “hole”) and add them up. If the total is an odd number (or 0), then the point is either outside or in the hole. I hope that helps.

  7. akismet-80400ff01fa0a76a61544fe392b1cb6b

    Is there a way of inverting the search so that instead of searching for multiple points in a single polygon it searches for a single point in multiple polygons?

    1. Michael Post author

      You just have to run the script in a loop, so it checks whether the point is inside/outside each of the polygons.

  8. ideasbinariasangel

    hi, i need help please.
    i have an array with coordinates:
    $polygons :
    [0] => 18.41059802826527 -88.03557809904612
    [1] => 18.41580996014612 -88.24981149747505
    [2] => 18.4716617793069 -88.249813060726
    [3] => 18.475569353943605 -88.30062482830219
    [4] => 18.487291543546217 -88.31985090252014
    [5] => 18.484686681799133 -88.34594343181584
    [6] => 18.485989117621315 -88.36654279704898
    [7] => 18.476871859036027 -88.37615583415798
    [8] => 18.49510589119781 -88.40224836345367
    [9] => 18.478174354235335 -88.44482038493693
    [164] => 18.14315877533503 -87.9022376682663
    [165] => 18.16044934189305 -87.92489697002266
    [166] => 18.16044934189305 -88.02995373271435
    [167] => 18.410310718038836 -88.03630833016227
    [168] => 18.41059802826527 -88.03557809904612

    if i write:
    $point = “18.511268 -88.289952 ”
    it’s work fine, but when i write $point inside a while structure (i get many points from a table) it’s don’t work, because coordinate 18.511268 -88.289952 says outside when must be inside.

    i am thinking this mistake is because i have many points (543) to validate inside a while structure, so, the server’s memory may be is “confused” like a result of the operations.

    please help me, thank you.

    * note that the first and last position are the same in $polygons.

    1. Michael Post author

      I don’t see why there would be an issue with the use of while. Since it works when you run the script with a single point, it should give the same result for that particular point when checking multiple points. The only thing that comes to mind would be that a variable is not reset properly in that while loop, but it’s really difficult to say without seeing the code.
      As shown in the sample code above, you can put all the points in the $points array, and they will all be checked in the foreach loop. Have you tried fetching all you points from the table (using while) to populate the $points array and then running the point-in-polygon script in the foreach, as in that sample?

  9. Paul Lee

    First of all, I’m very grateful that you’ve done this. I experimented with some code a long time ago but it became so long winded that I gave up :(

    Could I possibly ask a question? (Hopefully you’re OK with this…)

    I’m creating an array of objects in php, each one has member variables, including the vertices of a polygon. I’m trying to find out if a given co-ordinates is within the polygons, but I can’t get it to work.

    This is my code so far

    class EData
    public $datemod; // This is just a dummy for the time being
    public $vertices;

    function __construct( $dm, $v )
    $this->datemod = $dm;
    $this->vertices = $v;

    $elist = array();
    array_push($elist, new EData( “am”, array(“25 90″, “75 90″, “60 -90″, “40 -90″, “25 90″) ) );
    array_push($elist, new EData( “pm”, array(“80 90″, “120 90″, “100 -90″, “90 -90″, “80 90″) ) );

    $lat = 50;
    $long = 80;

    $pointvar = $lat . ” ” . $long;
    $pointstr = (string) $pointvar; // cast to string

    $pointLocation = new pointLocation();

    for( $i=0; $i pointInPolygon($point, $elist[$i]->vertices) . “”;


    The first output should say that the point is within the polygon but not the second but it says both are outside. Can you see what is wrong?

      1. Michael Post author

        Hi Paul,
        Good to know it was just a typo and that it is working fine now.
        And thanks for your comment. I’m very glad to know that this code is useful to you!

  10. Alexis


    Thanks for this function. Very useful.
    I suggest this improvement to close the polygon automatically if needed.

    $first = null;
    $last = null;

    foreach ($polygon as $vertex) {
    $vertices[] = $this->pointStringToCoordinates($vertex);
    if($i == 0){
    $first = $this->pointStringToCoordinates($vertex);
    $last = $this->pointStringToCoordinates($vertex);

    if($first != $last){
    $vertices[] = $first;


Leave a comment