31

Suppose I Draw a polygan using leaflet like in the follow demo: http://leaflet.github.io/Leaflet.draw/

My question is how I can determine if a given point reside inside the polygon or not.

gusjap
  • 2,397
  • 5
  • 24
  • 38
Majdi Taleb
  • 731
  • 3
  • 9
  • 26
  • If the polygon is closed then you can orientate every segment (inside/outside). Drawing a half-line from any point to infinity will end up in odd or even number of segment intersections (always odd or always even for every direction): even number of intersections are points outside the polygon and odd are inside. Thus you may choose any direction e.g. the x-axis: check for intersecting segments on `[pt.x,pt.y]-[inf, pt.y]` (you can also bound the half-line to the bounding box of the polygon). There are of course ways to do this more efficiently: https://en.wikipedia.org/wiki/Point_location – BeyelerStudios Aug 03 '15 at 15:06
  • I ask if there are a method that let me determine the latitude and the longitude of a polygon, and then determine if the point is inside the polygon or not using javascript – Majdi Taleb Aug 04 '15 at 12:29

3 Answers3

56

Use the Ray Casting algorithm for checking if a point (marker) lies inside of a polygon:

function isMarkerInsidePolygon(marker, poly) {
    var polyPoints = poly.getLatLngs();       
    var x = marker.getLatLng().lat, y = marker.getLatLng().lng;

    var inside = false;
    for (var i = 0, j = polyPoints.length - 1; i < polyPoints.length; j = i++) {
        var xi = polyPoints[i].lat, yi = polyPoints[i].lng;
        var xj = polyPoints[j].lat, yj = polyPoints[j].lng;

        var intersect = ((yi > y) != (yj > y))
            && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
        if (intersect) inside = !inside;
    }

    return inside;
};

See jsfiddle for example.

Original source for the code: https://github.com/substack/point-in-polygon/blob/master/index.js


See also 2014's similar answer, https://stackoverflow.com/a/41138512/287948

Peter Krauss
  • 13,174
  • 24
  • 167
  • 304
gusjap
  • 2,397
  • 5
  • 24
  • 38
  • 6
    that worked although `poly.getLatLngs()` returns an array of arrays so the first line had to be `var polyPoints = poly.getLatLngs()[0];` If you want to support donut shaped polygons, you need another wrapping loop. – ProblemsOfSumit Aug 23 '16 at 08:26
20

Here is the modified(with @Sumit hints) version of @gusper answer that worked for me:(i had donuts)

function isMarkerInsidePolygon(marker, poly) {
    var inside = false;
    var x = marker.getLatLng().lat, y = marker.getLatLng().lng;
    for (var ii=0;ii<poly.getLatLngs().length;ii++){
        var polyPoints = poly.getLatLngs()[ii];
        for (var i = 0, j = polyPoints.length - 1; i < polyPoints.length; j = i++) {
            var xi = polyPoints[i].lat, yi = polyPoints[i].lng;
            var xj = polyPoints[j].lat, yj = polyPoints[j].lng;

            var intersect = ((yi > y) != (yj > y))
                && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
            if (intersect) inside = !inside;
        }
    }

    return inside;
};
roberrrt-s
  • 7,914
  • 2
  • 46
  • 57
VitalyZ
  • 445
  • 1
  • 4
  • 12
8

I found that none of the above answers worked for counting markers within non-contiguous polygons. Here's an example polygon where the above functions returned 0 markers inside:

Non-contiguous Polygon

For anyone who needs to do that, the Leaflet.PointInPolygon package worked for me: https://github.com/hayeswise/Leaflet.PointInPolygon

It's a bit slow, but it seems to be accurate.

lauren.marietta
  • 2,125
  • 1
  • 11
  • 19