检查点是否在多边形内


79

我想检查一个点是否位于特定的多边形内。多边形为:

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

我要检查的要点是:

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]

如何判断这些点中的每一个是否都位于该多边形内?

以下算法无效。我不知道为什么

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;
}

我不想使用第三方解决方案,例如google maps API或https://github.com/mattwilliamson/Google-Maps-Point-in-Polygon这样的第三方解决方案。

我的尝试在这里:http : //jsfiddle.net/nvNNF/2/


5
在多边形检查之外选择一个点,查看从该点到您的点的线是否与定义多边形周长的奇数线相交。
霍根

您可以在此处检查代码:我在polygone jsfiddle.net/nvNNF/2中放了一点,它返回“ False”
user3378649 2014年


poly[i].y应该poly[i][1]在第3行的末尾。该函数还会检查该点是否在多边形内,而不是该点是否属于该多边形。
2014年

没有理由让您的for循环具有如​​此多的变量,从而降低了可读性。您可以分别测试每个条件,然后发出警报,一旦到达代码末尾,就可以合并所有条件并再次检查。
几乎是初学者

Answers:


117

Github上有一个项目,代码为:https : //github.com/substack/point-in-polygon(MIT许可证):

function inside(point, vs) {
    // ray-casting algorithm based on
    // https://wrf.ecse.rpi.edu/Research/Short_Notes/pnpoly.html/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;
};

用法:

// 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

测试功能在这里:https : //github.com/substack/point-in-polygon/blob/master/index.js

注意:当该点是多边形的一个角或在一条边上时,此代码无法可靠地工作。这里有一个改进的版本:https : //github.com/mikolalysenko/robust-point-in-polygon


如果您已包含参考,我认为可以复制并粘贴代码。它将归功于原始作者。
Chathuranga Chandrasekara

1
@AaronDigulla那不是完全正确。试试这个简单的事情在javascript:0,3-0,2和console.log输出
Pedro Silva

2
@PedroSilva让我这样说:它要么在C / C ++,Java和JavaScript中工作,要么对这三种都不起作用。它们都使用完全相同的方法来表示数字。使用编译器不会给编程语言带来神话般的功能。C / C ++和Java库在打印结果时将其取整更好一点。
亚伦·迪古拉

1
谢谢,我的工作很棒,但是刚刚意识到,它可以为多边形的边或角上的点提供混合的结果。
treeseal7年7

1
如果将多边形的坐标传递给此函数以检查它们是否在其内部,则将对它们的一半成真。
亚历山大·普拉夫丁

15

您的多边形数组看起来像是coordinatesGeoJSON多边形结构中的数组(有关更多信息,访问https://macwright.org/2015/03/23/geojson-second-bite.htmlhttp://geojson.org)。因此,也许您可​​以使用正在处理geoJSON数据的库?在中找到OP的答案和注释。是否可以使用JavasScript确定GeoJSON点是否在GeoJSON多边形内?

简而言之,我的一天被turfhttps://github.com/turfjs/turf)保存了,还有d3https://github.com/d3/d3-geo#geoContains),但是我对此有疑问。

UPD:turf当点位于多边形的“边缘”时,我注意到给出的结果不一致。我创建了问题,正在等待开发人员的答复。

UPD2:“边界点”问题已通过使用的最新版本解决turf(我使用3.0.14而不是4.6.1)。现在没事了


11

这是我终于可以使用的功能。我是通过从这里采用C代码到javascript来实现的(有解释)。

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;
}

其中cornersX=具有x或纬度顶点数组的数组,cornersY=具有y或经度数组的数组。X,Y-测试点的经度和纬度。


谢谢!效果很好。我能够适应这一点。返回值为false,0或1。我将其更改为var oddNodes = 0,然后返回oddNodes == 1以得到最终的布尔值。
涡轮增压

它对我不起作用。我总是得到1.无论内在还是外在。请帮我。
克里希纳

这行不通;无论如何,它是否存在开源功能来用颜色填充区域?如果是这样,那将是将所有填充点与指定坐标进行比较的问题,对于复杂多边形而言,可靠性要高得多。
jumpjack '18

2

就我而言,我做了以下事情对我来说很好

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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.