Check if Point Is Inside A Polygon

走远了吗. 提交于 2019-11-26 04:19:52

问题


I want to check if a point lies within a specific polygon. The polygon is:

 polygon=   [ [-73.89632720118, 40.8515320489962],
              [-73.8964878416508, 40.8512476593594],
              [-73.8968799791431, 40.851375925454],
              [-73.8967188588015, 40.851660158514],
              [-73.89632720118, 40.8515320489962] ]

The points I want to check are:

1 = [40.8515320489962,-73.89632720118]
2 = [40.8512476593594,-73.8964878416508]
3 = [40.851375925454,-73.8968799791431]
4 = [40.851660158514,-73.8967188588015]
5 = [40.8515320489962,-73.89632720118]

How can I tell if each of these points lies within this polygon?

The algorithm below does not work. I don\'t know why.

pt[lat,long]

function isPointInPoly(poly, pt){
    for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
        ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1] < poly[i].y))
        && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
        && (c = !c);
    return c;
}

I don\'t want to use a third party solution such as google maps API or this one https://github.com/mattwilliamson/Google-Maps-Point-in-Polygon.

My attempt is here: http://jsfiddle.net/nvNNF/2/


回答1:


There is a project on Github with code: https://github.com/substack/point-in-polygon (MIT license):

function inside(point, vs) {
    // ray-casting algorithm based on
    // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html

    var x = point[0], y = point[1];

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

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

    return inside;
};

Usage:

// array of coordinates of each vertex of the polygon
var polygon = [ [ 1, 1 ], [ 1, 2 ], [ 2, 2 ], [ 2, 1 ] ];
inside([ 1.5, 1.5 ], polygon); // true

The test function is here: https://github.com/substack/point-in-polygon/blob/master/index.js

Note: This code doesn't work reliably when the point is a corner of the polygon or on an edge. There is an improved version here: https://github.com/mikolalysenko/robust-point-in-polygon




回答2:


Your polygon array looks like coordinates array in GeoJSON polygon structure (read more at https://macwright.org/2015/03/23/geojson-second-bite.html and http://geojson.org). So maybe you can use libraries which are working with geoJSON data? Look at answer and comments to OP in Is it possible to determine if a GeoJSON point is inside a GeoJSON polygon using JavasScript?

In short, my day was saved by turf (https://github.com/turfjs/turf) There is also d3 (https://github.com/d3/d3-geo#geoContains) but i had issues with it.

UPD: I noticed turf is giving inconsistent results when point is on 'edge' of polygon. I created issue and i am waiting for answer from developers.

UPD2: 'Boundary points' issue is resolved by using latest version of turf (i used 3.0.14 instead of 4.6.1). It's all right now.




回答3:


Here is the function I finally got working. I got it by adopting C code to javascript from here (with explanation).

function checkcheck (x, y, cornersX, cornersY) {

    var i, j=cornersX.length-1 ;
    var odd = false;

    var pX = cornersX;
    var pY = cornersY;

    for (i=0; i<cornersX.length; i++) {
        if ((pY[i]< y && pY[j]>=y ||  pY[j]< y && pY[i]>=y)
            && (pX[i]<=x || pX[j]<=x)) {
              odd ^= (pX[i] + (y-pY[i])*(pX[j]-pX[i])/(pY[j]-pY[i])) < x; 
        }

        j=i; 
    }

return odd;
}

Where cornersX = array with x or latitude vertices array, cornersY = array with y or longitude array. X, Y - latitude and longitude of tested point.




回答4:


In my case i did following thing it's working fine for me

function isLatLngInZone(latLngs,lat,lng){
  // latlngs = [{"lat":22.281610498720003,"lng":70.77577162868579},{"lat":22.28065743343672,"lng":70.77624369747241},{"lat":22.280860953131217,"lng":70.77672113067706},{"lat":22.281863655593973,"lng":70.7762061465462}];
  vertices_y = new Array();
  vertices_x = new Array();
  longitude_x = lng;
  latitude_y = lat;
  latLngs = JSON.parse(latLngs);
  var r = 0;
  var i = 0;
  var j = 0;
  var c = 0;
  var point = 0;

  for(r=0; r<latLngs.length; r++){
   vertices_y.push(latLngs[r].lat);
   vertices_x.push(latLngs[r].lng);
  }
  points_polygon = vertices_x.length;
  for(i = 0, j = points_polygon; i < points_polygon; j = i++){
   point = i;
   if(point == points_polygon)
    point = 0;
   if ( ((vertices_y[point]  >  latitude_y != (vertices_y[j] > latitude_y)) && (longitude_x < (vertices_x[j] - vertices_x[point]) * (latitude_y - vertices_y[point]) / (vertices_y[j] - vertices_y[point]) + vertices_x[point]) ) )
    c = !c;
  }
return c;
}



回答5:


After @AaronDigulla, whose answer is the best, with no additional library, here is a shorter version, point being destructured into [x,y]. The performance is 20% slower (jsperf), but works fine and probably more readable.

const intersect = (xi,yi, xj,yj, u,v) =>
    ((yi > v) != (yj > v)) && (u < (xj - xi) * (v - yi) / (yj - yi) + xi);
const inside = ([x,y], vs, vl1) => vs.some(([xi,yi], i, t) =>
   (i++ < vl1) && intersect(xi,yi, t[i][0],t[i][1], x,y));

Usage:

const ins = pointsToCheck.map(p => intersect(p, polygon, polygon.length - 1));


来源:https://stackoverflow.com/questions/22521982/check-if-point-is-inside-a-polygon

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!