我在StackOverflow上看到了我在PHP代码中实现的“多边形点”光线跟踪算法。大多数情况下,它运作良好,但在一些复杂的情况下,复杂的多边形和恶性点,它会失败,它表示该点不在多边形中。
例如:
你会发现here我的Polygon和Point类:pointInPolygon方法在Polygon类中。在文件的末尾,有两个点应该位于给定的多边形内(Google地球上为True)。第二个效果很好,但第一个是错误的:(。
您可以使用this KML file轻松检查Google地球上的多边形。
答案 0 :(得分:43)
一直在那里:-)我还通过stackoverflows PiP建议,包括你的参考和this thread。不幸的是,没有任何建议(至少是我尝试过的那些)对于现实生活场景来说是完美无缺的:就像用户在徒手上绘制谷歌地图上的复杂多边形,“恶性”右对左边的问题,负数等等。
PiP算法必须适用于所有情况,即使多边形包含数十万个点(如县边界,自然公园等) - 无论多边形多么“疯狂”。
所以我最终建立了一个新的算法,基于天文学应用程序的一些来源:
//Point class, storage of lat/long-pairs
class Point {
public $lat;
public $long;
function Point($lat, $long) {
$this->lat = $lat;
$this->long = $long;
}
}
//the Point in Polygon function
function pointInPolygon($p, $polygon) {
//if you operates with (hundred)thousands of points
set_time_limit(60);
$c = 0;
$p1 = $polygon[0];
$n = count($polygon);
for ($i=1; $i<=$n; $i++) {
$p2 = $polygon[$i % $n];
if ($p->long > min($p1->long, $p2->long)
&& $p->long <= max($p1->long, $p2->long)
&& $p->lat <= max($p1->lat, $p2->lat)
&& $p1->long != $p2->long) {
$xinters = ($p->long - $p1->long) * ($p2->lat - $p1->lat) / ($p2->long - $p1->long) + $p1->lat;
if ($p1->lat == $p2->lat || $p->lat <= $xinters) {
$c++;
}
}
$p1 = $p2;
}
// if the number of edges we passed through is even, then it's not in the poly.
return $c%2!=0;
}
说明性测试:
$polygon = array(
new Point(1,1),
new Point(1,4),
new Point(4,4),
new Point(4,1)
);
function test($lat, $long) {
global $polygon;
$ll=$lat.','.$long;
echo (pointInPolygon(new Point($lat,$long), $polygon)) ? $ll .' is inside polygon<br>' : $ll.' is outside<br>';
}
test(2, 2);
test(1, 1);
test(1.5333, 2.3434);
test(400, -100);
test(1.01, 1.01);
输出:
2,2 is inside polygon
1,1 is outside
1.5333,2.3434 is inside polygon
400,-100 is outside
1.01,1.01 is inside polygon
现在,我在几个网站上切换到上述算法已有一年多了。与“SO算法”不同,到目前为止还没有任何抱怨。请参见行动here(国家真菌学数据库,对丹麦语感到抱歉)。您可以绘制多边形,或选择“kommune”(一个县) - 最终将多边形与数千个点比较到数千个记录。)
<强>更新强> 注意,这个算法的目标是geodata / lat,lngs可以非常精确(十进制小数),因此将“in polygon”视为 in polygon - 而不是在多边形的边界上。 1,1被视为外部,因为它是 on 边界。 1.0000000001,1.01不是。