判断一个点是否在一个复杂的多边形中

博客介绍了判断点是否在多边形内的算法,通过比较测试点与多边形边的Y坐标,统计穿过测试点Y开端的边对应的节点数,根据奇偶判断点的位置。还给出了不同类型多边形(如边相交、顶点在Y开端等)的示例,最后提供了C#代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

       图形1

图形1示范了一个典型的有十四条边的凹的多边形。其中红点就是需要去测试的,去判断他是不是在这个多边形中。

 

当前的解决方法是和测试点比较任何一个边的Y坐标,和编译一系列的节点,这些节点的任何一边的点穿过测试点的Y开端。在这个例子中,一共有多边形的8条边穿过这个Y开端。另外的6条边没有。然后,如果那里有奇数目的节点在测试点的任何一边,则这个测试点就在这个多边形中。如果在测试点的任何一边有偶数目的测试点,则这个测试点就在这个多边形之外。在我们的这个例子中,有5个节点在测试点的左边,有三个点在测试点的右边,因此这个点在多边形之中。

(注意:这个算法并不在意多边形是否是顺时针还是逆时针的方向)

    图形2

图形2示范了当一个穿过自己的多边形,在这个例子中,一个十条边的多边形他的边互相穿越。这个效果很像“exclusive or”,或者是XOR对于一个汇编语言的程序员。这个多边形的的一部分被其他消除了。因此,这个测试点是在多边形之外,如同上面验证的,在点的任何一边只有偶数目的节点。

  图形3

在图形3中,这是一个六条边有互相穿越的连线但是并不删除自己的多边形。这个不是问题,

上述的算仍然适用。

 

 

图形4

图形4演示的问题是当一个顶点直接落在测试点的Y开端。因为a边和b边同时和开端

接触,他们能同时产生一个节点吗?不能,因为如果这样一来的话在测试点的两边就有两个节点,测试点就应该在多边形之外,然而事实恰好相反。

这个解决方案非常简单,如果那些正好在Y端的点必需考虑属于哪一条边,让我们武断的说这个点是属于上面条边的。

 图形5

图形5演示的是一个整条边都放置在开端上的例子,简单的根据图形4的规则来考虑。

Side c有一个交点,side d不产生任何的交点。Side e 也不产生节点。

 

最后的笔记

 如果这个点是在这个多边形的边界上,这个算法会发送一个不可预知的结果,例如这个结果可能是“inside” 或者 “outside” 根据系统的坐标。

 

Code Sample


// Globals which should be set before calling this function:
//
// int    polySides  =  how many corners the polygon has
// float  polyX[]    =  horizontal coordinates of corners
// float  polyY[]    =  vertical coordinates of corners
// float  x, y       =  point to be tested
//
// (Globals are used in this example for purposes of speed.
// Change as desired.)
//
// The function will return TRUE if the point x,y is inside the
// polygon, or FALSE if it is not. If the point x,y is exactly on
// the edge of the polygon, then the function may return TRUE or
// FALSE.
//
// Note that division by zero is avoided because the division is
// protected by the "if" clause which surrounds it.

boolean pointInPolygon() {

  int      i, j=0         ;
  boolean  oddNODES=FALSE ;

  for (i=0; i<polySides; i++) {
    j++; if (j==polySides) j=0;
    if (polyY[i]<y && polyY[j]>=y
    ||  polyY[j]<y && polyY[i]>=y) {
      if (polyX[i]+(y-polyY[i])/(polyY[j]-polyY[i])*(polyX[j]-polyX[i])<x) {
        oddNODES=!oddNODES; }}}

  return oddNODES; }

转载于:https://www.cnblogs.com/wanghualiang/archive/2005/07/13/192301.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值