找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 1886|回复: 1

[分享] 一点是否在多边形内部

[复制链接]

已领礼包: 40个

财富等级: 招财进宝

发表于 2013-6-15 02:14:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

已知一个点和一个多边形,怎么让傻乎乎的计算机判断出点在形内形外呢?这里定义多边形边集也为多边形内部。

常见的有两种方法:

1.射线法。从这个点向右水平发出一条射线,如果交点个数是偶数则在形内,奇数在形外。有一个弊端:如果这条射线恰好与这条边重合了,交点个数怎么算?常见的是将这条射线向上微移,不过不少人觉得这样做很不放心。

2.环顾法。顾名思义,就是环顾一圈:从一个顶点按照顺时针顺序环顾,旋转的极角累加,如果等于360度就是形内、0度是形外,介于两者之间即为边上。这种方法很完美,但代价是其中计算除法和arccos的速度太慢,大约比射线法慢20倍。
我比较倾向射线法+微移,所谓微移只是意识上的微移,在代码中射线是没有变化的、判断条件改变了一下:

1.叉积大于0
2.对于多边形某条边,设顶点高的为A,低的为B,则需要满足A严格高于射线、B不高于(低于或等于)射线
同时满足1和2就算作有一个交点。为防止另一种bug的发生(不细讲估计看的也有点儿不耐烦了),在遍历边的同时一旦发现此点在边上停止计算,结果即为形内。这样射线发也完美无BUG了。
下面写的还没有经过测试,仅供参考;如果哪位发现了BUG,请留言与此,一起改正。
bool inpolyon(point a)
{
        int h,i,j,k,t=0;
        for (h=1;h<=n;h++)
        {
              i=h;
              j=h+1;
              if (j==n+1)        j=1;
              if (dblcmp(d[i].y-d[j].y)==-1)        k=i,i=j,j=k;
              k=dblcmp(cross(a,d[j],d[i]));
              if (!k)
              {
                    if (betweencmp(a,d[j],d[i])<=0)        return true;
              }
              else if (k>0 && dblcmp(d[i].y-a.y)==1 && dblcmp(d[j].y-a.y)<=0)        t++;
        }
        if (t%2)        return true;
        return false;
}
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
发表于 2013-9-28 21:47:26 | 显示全部楼层
射线法。从这个点向右水平发出一条射线,如果交点个数是偶数则在形内,奇数在形外。
怎么偶数就在内,奇数在外啊?
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2024-12-22 10:54 , Processed in 0.376787 second(s), 31 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表