多边形内的点 PHP 错误
我在 php 中使用多边形内的点检查,但出现了重大错误 - 因为不在多边形内的点出现在内部。
我的基本函数如下(在此处找到,从类修改为简单函数: http:// /www.assemblesys.com/dataServices/php_pointinpolygon.php)。我唯一能想到的是某处存在某种舍入错误?
举一个例子,我试图确定一个点是否在中央公园(一个简单的广场)内,但我从公园外的点得到了积极的结果。
感谢您的任何见解,
-D
$central_park = array('40.768109,-73.981885', '40.800636,-73.958067', '40.796900,-73.949184', '40.764307,-73.972959');
$test_points = array('40.7546755,-73.9758343', '40.764405,-73.973951', '40.7594219,-73.9733896', '40.768137896318315,-73.9814176061', '40.7982394,-73.9523718', '40.685135,-73.973562', '40.7777062,-73.9632719', '40.764109,-73.975948', '40.758908,-73.9813128', '40.7982782,-73.9525028', '40.7463886,-73.9817654', '40.7514592,-73.9760405', '40.7514592,-73.9760155', '40.7514592,-73.9759905', '40.7995079,-73.955431', '40.7604354,-73.9758778', '40.7642878,-73.9730075', '40.7655335,-73.9800484', '40.7521678,-73.9777978', '40.7521678,-73.9777728')
function pointStringToCoordinates($pointString) {
$coordinates = explode(",", $pointString);
return array("x" => trim($coordinates[0]), "y" => trim($coordinates[1]));
}
function isWithinBoundary($point,$polygon){
$point = pointStringToCoordinates($point);
$vertices = array();
foreach ($polygon as $vertex) {
$vertices[] = pointStringToCoordinates($vertex);
}
// Check if the point is inside the polygon or on the boundary
$intersections = 0;
$vertices_count = count($vertices);
for ($i=1; $i < $vertices_count; $i++) {
$vertex1 = $vertices[$i-1];
$vertex2 = $vertices[$i];
if ($vertex1['y'] == $vertex2['y'] and $vertex1['y'] == $point['y'] and $point['x'] > min($vertex1['x'], $vertex2['x']) and $point['x'] < max($vertex1['x'], $vertex2['x'])) { // Check if point is on an horizontal polygon boundary
$result = TRUE;
}
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']) {
$xinters = ($point['y'] - $vertex1['y']) * ($vertex2['x'] - $vertex1['x']) / ($vertex2['y'] - $vertex1['y']) + $vertex1['x'];
if ($xinters == $point['x']) { // Check if point is on the polygon boundary (other than horizontal)
$result = TRUE;
}
if ($vertex1['x'] == $vertex2['x'] || $point['x'] <= $xinters) {
$intersections++;
}
}
}
// If the number of edges we passed through is even, then it's in the polygon.
if ($intersections % 2 != 0) {
$result = TRUE;
} else {
$result = FALSE;
}
return $result;
}
I am using a point-in-polygon check in php, but I am getting major errors - as in points that are not in the polygon are coming up as inside.
My basic functions are typed out below (found here, modified from a class to a simple function: http://www.assemblysys.com/dataServices/php_pointinpolygon.php). The only thing I can think of is some kind of rounding errors someplace?
As one example, I am trying to determine whether a point is in Central Park, a simple square, but I get positives from points outside the park.
Thanks for any insight,
-D
$central_park = array('40.768109,-73.981885', '40.800636,-73.958067', '40.796900,-73.949184', '40.764307,-73.972959');
$test_points = array('40.7546755,-73.9758343', '40.764405,-73.973951', '40.7594219,-73.9733896', '40.768137896318315,-73.9814176061', '40.7982394,-73.9523718', '40.685135,-73.973562', '40.7777062,-73.9632719', '40.764109,-73.975948', '40.758908,-73.9813128', '40.7982782,-73.9525028', '40.7463886,-73.9817654', '40.7514592,-73.9760405', '40.7514592,-73.9760155', '40.7514592,-73.9759905', '40.7995079,-73.955431', '40.7604354,-73.9758778', '40.7642878,-73.9730075', '40.7655335,-73.9800484', '40.7521678,-73.9777978', '40.7521678,-73.9777728')
function pointStringToCoordinates($pointString) {
$coordinates = explode(",", $pointString);
return array("x" => trim($coordinates[0]), "y" => trim($coordinates[1]));
}
function isWithinBoundary($point,$polygon){
$point = pointStringToCoordinates($point);
$vertices = array();
foreach ($polygon as $vertex) {
$vertices[] = pointStringToCoordinates($vertex);
}
// Check if the point is inside the polygon or on the boundary
$intersections = 0;
$vertices_count = count($vertices);
for ($i=1; $i < $vertices_count; $i++) {
$vertex1 = $vertices[$i-1];
$vertex2 = $vertices[$i];
if ($vertex1['y'] == $vertex2['y'] and $vertex1['y'] == $point['y'] and $point['x'] > min($vertex1['x'], $vertex2['x']) and $point['x'] < max($vertex1['x'], $vertex2['x'])) { // Check if point is on an horizontal polygon boundary
$result = TRUE;
}
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']) {
$xinters = ($point['y'] - $vertex1['y']) * ($vertex2['x'] - $vertex1['x']) / ($vertex2['y'] - $vertex1['y']) + $vertex1['x'];
if ($xinters == $point['x']) { // Check if point is on the polygon boundary (other than horizontal)
$result = TRUE;
}
if ($vertex1['x'] == $vertex2['x'] || $point['x'] <= $xinters) {
$intersections++;
}
}
}
// If the number of edges we passed through is even, then it's in the polygon.
if ($intersections % 2 != 0) {
$result = TRUE;
} else {
$result = FALSE;
}
return $result;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
原始代码存在几个问题,关闭多边形修复了其中一个问题,但该代码也为多边形边界线上的点给出了错误的结果。仅当点不在边界上时才需要执行 isWithinBoundary 函数末尾的 if..else 语句。由于边界上的点实际上不会与边界相交,因此边界点的相交计数始终为奇数,这意味着最终的 IF 语句对于边界点始终返回 FALSE。
我对代码做了一些调整,这个版本是一个独立的页面,有一些简单的测试数据,它输出正在做出的决定。
您现在可能已经自己发现并修复了这些问题,但这可能会帮助其他找到并使用此代码的人。
There were a couple of problems with the original code, closing the polygons fixed one of these but the code also gave incorrect results for points on the boundary lines of the polygon. The if..else statement at the end of the isWithinBoundary function only needs to be executed if a point IS NOT on a boundary. As a point on the boundary won't actually intersect the boundary then the count of intersections would always be odd for a boundary point meaning that this final IF statement would always return FALSE for a boundary point.
I have tweaked the code a little, this version is a self contained page that has some simple test data and it outputs the decisions being made.
You've probably spotted and fixed these problems yourself by now, but this might help other people who find and use this code.
好吧,我再次发现自己愚蠢地回答了自己愚蠢的问题。
我没有通过将第一个坐标附加到数组中的最后一个点来关闭多边形。这导致了不匹配点的非常独特的外观 - 它们似乎都从无界端溢出多边形。
所以这个 -
应该是这个 -
这就是我今天的愚蠢之处。谢谢。
Well, once again I find myself foolishly answering my own foolish question.
I was not closing the polygon by appending the first coordinate to the last spot in the array. This caused a very distinctive look of the mismatched points - they all appeared to be spilling out of the polygon from the unbounded end.
So this -
Should be this -
And that's how I was dumb today. Thank you.
您的代码的问题是变量 $result 被此代码覆盖,
即使 $result == TRUE 在这里:
在原始代码中,有一个“return”,它是正确的,而不是您的错误。
The problem with your code is that the variable $result is overwritten by this code
even if $result == TRUE here:
In the original code there was an 'return' which was correct instead of your is wrong.