判断点在任意多边形(包括凹凸边形)内

原文链接:点击打开链接

题目地址:http://www.cnblogs.com/try86/archive/2012/04/22/2465416.html
这一题,若点在边上,也将点看做成多边形内。
对于凸多边形有很多种方法判断点在多边形内,但若是凹多边形,则靠谱的方法不多,可以谷歌一下。

1)水平/垂直交叉点数判别法(适用于任意多边形包括凹凸边形)
注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,如果P在多边形外部,则交点个数必为偶数(0也在内)。所以,我们可以顺序考虑多边形的每条边,求出交点的总个数。还有一些特殊情况要考虑,具体见代码:

[cpp]  view plain copy
  1.    
  2. //offset为多边形坐标上限  
  3. //on_edge表示点在多边形边上时的返回值  
  4. #include<iostream>  
  5. #include<cmath>  
  6. #include<cstring>  
  7. #include<cstdio>  
  8. #include<cstdlib>  
  9. #include<time.h>  
  10. using namespace std;  
  11. const int offset=1000;  
  12. const double eps=1e-8;  
  13. struct Point{  
  14.     double x,y;  
  15. }p[105];  
  16. double cross(Point pi,Point pj,Point pk){ // (pi,pj)X(pi,pk)  
  17.     return (pj.x-pi.x)*(pk.y-pi.y)-(pj.y-pi.y)*(pk.x-pi.x);  
  18. }  
  19. int InPolygon(const Point *arr,const int &len,const Point &p,int on_edge=1){  
  20.  Point q;  
  21.  int i=0,counter;  
  22.  while(i<len){  
  23.    q.x=rand()+offset;//随机取一个足够远的点q  
  24.    q.y=rand()+offset;//以p为起点q为终点做射线L  
  25.    for(counter=i=0;i<len;i++){//依次对多边形的每条边进行考察  
  26.     if(fabs(cross(p,arr[i],arr[(i+1)%len]))<eps &&  
  27.     (arr[i].x-p.x)*(arr[(i+1)%len].x-p.x)<eps && (arr[i].y-p.y)*(arr[(i+1)%len].y-p.y)<eps)  
  28.       return on_edge; //点p在边上,返回on_edge  
  29.     else if(fabs(cross(p,q,arr[i]))<eps) break//点arr[i]在射线pq上,停止本循环,另取q  
  30.     else if(cross(p,arr[i],q)*cross(p,arr[(i+1)%len],q)<-eps &&  
  31.       cross(arr[i],p,arr[(i+1)%len])*cross(arr[i],q,arr[(i+1)%len])<-eps)  
  32.       counter++;  
  33.    }  
  34.  }  
  35.  return counter&1;  
  36. }  
  37. int main(){  
  38.  int n,m;  
  39.  while(scanf("%d",&n)==1){  
  40.    for(int i=0;i<n;i++)  
  41.     scanf("%lf%lf",&p[i].x,&p[i].y);  
  42.    scanf("%d",&m);  
  43.    Point temp;  
  44.    while(m--){  
  45.      scanf("%lf%lf",&temp.x,&temp.y);  
  46.      if(InPolygon(p,n,temp))  
  47.       puts("Yes");  
  48.      else  
  49.       puts("No");  
  50.    }  
  51.  }  
  52.  return 0;  


2)
角度和判别法
这个方法的原理是,多边形内一点(不含边上的点)到各相邻点的夹角之和为360度。
网上面很多人转载了这个方法,说是适用于任意多边形,其实不然,当然很多人的模板还是使用上面那种方法。。。
角度和判别法只适合凸多边形,对于这道题,针对这道题出组数据,点为顺时针给出:
4
0 0
5 10
10 0
5 5
1
5 0
这个多边形是凹多边形,点(5,0)并不在多边形内,但夹角之和却为360度,所以不能用这个方法
 
对于这个方法,如下代码提交,果断WA 

[cpp]  view plain copy
  1. <pre name="code" class="cpp"><pre name="code" class="cpp"><pre></pre>  
  2. <pre></pre>  
  3. <pre></pre>  
  4. <pre></pre>  
  5. <pre></pre>  
  6. <pre></pre>  
  7. <pre></pre>  
  8. <pre></pre>  
  9.      
  10. </pre></pre>  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值