我想确定一个多边形,并实现一个算法来检查一个点是否在多边形内部或外部。
有没有人知道是否有任何类似算法的可用示例?
我想确定一个多边形,并实现一个算法来检查一个点是否在多边形内部或外部。
有没有人知道是否有任何类似算法的可用示例?
检查一个点是否在多边形内部 -
考虑具有顶点a1、a2、a3、a4、a5的多边形。以下一组步骤应该有助于确定点P是在多边形内还是外。
计算由边a1->a2和连接a2到P以及P到a1的向量形成的三角形的向量面积。同样,计算每个可能的三角形的向量面积,其中一个边为多边形的边缘,另外两个连接P到该边缘。
对于一个点来说,要想在多边形内部,每个三角形都需要有正面积。即使其中一个三角形有负面积,那么点P也会被认为在多边形外部。
为了计算给定表示其3条边的向量的三角形的面积,请参考http://www.jtaylor1142001.net/calcjat/Solutions/VCrossProduct/VCPATriangle.htm
如果你的多边形是凸的,那么问题就比较简单。对于每一条线段,你可以进行一个简单的测试,以确定点是在该线段内部还是外部(向两个方向无限延伸)。否则,对于凹多边形,从你的点引出一条虚拟射线,直到无限远处(任意方向)。计算它穿过多少条边界线。奇数表示点在内部,偶数表示点在外部。
最后一个算法比看起来要棘手得多。当你的虚拟射线恰好碰到多边形的顶点时,你必须非常小心。
如果你的虚拟射线向-x方向前进,你只需要计算包含至少一个y坐标严格小于你的点的点的线段。这是使大多数奇怪的边缘情况正确工作的方法。
class PolygonHelps {
public static function isPointInPolygon(&$poly, $point){
$c = false;
$n = $j = count($poly);
for ($i = 0, $j = $n - 1; $i < $n; $j = $i++){
if ( ( ( ( $poly[$i]->lat <= $point->lat ) && ( $point->lat < $poly[$j]->lat ) )
|| ( ( $poly[$j]->lat <= $point->lat ) && ( $point->lat < $poly[$i]->lat ) ) )
&& ( $point->lng < ( $poly[$j]->lng - $poly[$i]->lng )
* ( $point->lat - $poly[$i]->lat )
/ ( $poly[$j]->lat - $poly[$i]->lat )
+ $poly[$i]->lng ) ){
$c = !$c;
}
}
return $c;
}
}
Jan的回答非常好。
这里是使用GeoCoordinate类的相同代码。
using System.Device.Location;
...
public static bool IsPointInPolygon(List<GeoCoordinate> poly, GeoCoordinate point)
{
int i, j;
bool c = false;
for (i = 0, j = poly.Count - 1; i < poly.Count; j = i++)
{
if ((((poly[i].Latitude <= point.Latitude) && (point.Latitude < poly[j].Latitude))
|| ((poly[j].Latitude <= point.Latitude) && (point.Latitude < poly[i].Latitude)))
&& (point.Longitude < (poly[j].Longitude - poly[i].Longitude) * (point.Latitude - poly[i].Latitude)
/ (poly[j].Latitude - poly[i].Latitude) + poly[i].Longitude))
c = !c;
}
return c;
}
$polygonBox = [
[55.761515, 37.600375],
[55.759428, 37.651156],
[55.737112, 37.649566],
[55.737649, 37.597301],
];
$sbPolygonEngine = new sbPolygonEngine($polygonBox);
$isCrosses = $sbPolygonEngine->isCrossesWith(55.746768, 37.625605);
// $isCrosses is boolean
(答案被我删除了,因为最初格式错误)