检查点是不是在多边形内
Posted
技术标签:
【中文标题】检查点是不是在多边形内【英文标题】:Check if Point Is Inside A Polygon检查点是否在多边形内 【发布时间】:2014-04-26 15:35:16 【问题描述】:我想检查一个点是否位于特定多边形内。多边形是:
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][1]))
&& (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/
【问题讨论】:
在多边形检查之外选择一个点,看看从该点到您的点的线是否与定义多边形周长的奇数条线相交。 你可以在这里查看代码:我在多边形jsfiddle.net/nvNNF/2 中放了一个点,它返回“False” en.wikipedia.org/wiki/Point_in_polygon 小心en.wikipedia.org/wiki/Complex_polygonspoly[i].y
应该是第 3 行末尾的 poly[i][1]
。该函数还检查点是否在多边形内,而不是该点是否属于多边形。
没有理由让你的 for 循环有这么多变量,从而降低可读性。您可以单独测试每个条件然后发出警报,一旦到达代码末尾,您就可以组合所有条件并再次检查。
【参考方案1】:
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
【讨论】:
鉴于您已包含参考,我认为复制和粘贴代码是可以的。它将归功于原作者。 @AaronDigulla 这并不完全正确。在 javascript 中尝试这个简单的事情:0,3 - 0,2 和 console.log 输出 @PedroSilva 让我这样说吧:它要么适用于 C/C++、Java 和 JavaScript,要么不适用于这三者中的任何一个。它们都使用完全相同的方法来表示数字。使用编译器不会给编程语言带来神话般的特性。 C/C++ 和 Java 库在打印结果时更擅长四舍五入。 谢谢,工作得很好,但刚刚意识到它对位于多边形边缘或角落的点给出了混合结果......如何编辑它以像往常一样接受这些? 如果你将多边形的坐标传递给这个函数来检查它们是否在自身内部,你会得到一半的结果。【参考方案2】:您的多边形数组看起来像 GeoJSON 多边形结构中的 coordinates
数组(在 https://macwright.org/2015/03/23/geojson-second-bite.html 和 http://geojson.org 阅读更多内容)。
所以也许你可以使用处理 geoJSON 数据的库?查看Is it possible to determine if a GeoJSON point is inside a GeoJSON polygon using JavasScript?中OP的答案和cmets
简而言之,turf
(https://github.com/turfjs/turf) 拯救了我的一天
还有d3
(https://github.com/d3/d3-geo#geoContains) 但我遇到了问题。
更新:
我注意到turf
在点位于多边形的“边缘”时给出不一致的结果。我创建了问题,正在等待开发人员的回答。
UPD2:
使用最新版本的turf
解决了“边界点”问题(我使用的是 3.0.14 而不是 4.6.1)。现在没事了。
【讨论】:
【参考方案3】:这是我终于开始工作的功能。我是通过从here 将 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。我更改为 varoddNodes = 0 并返回oddNodes == 1 以获得最终布尔值。 这对我不起作用。我总是得到 1. 无论是内部还是外部。请帮帮我。 这不起作用;无论如何,是否存在用颜色填充区域的开源功能?如果是这样,只需将所有填充点与指定坐标进行比较,这对于复杂的多边形更加可靠。【参考方案4】:在我的情况下,我做了以下事情,这对我来说很好
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;
【讨论】:
我在我的解决方案中尝试过,代码并非在所有情况下都有效,很多时候它对于位于多边形外的点返回 true。以上是关于检查点是不是在多边形内的主要内容,如果未能解决你的问题,请参考以下文章
哪个是检查用户位置(android 应用程序)是不是在多边形内的更好方法