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

原文链接:点击打开链接

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

1)水平/垂直交叉点数判别法(适用于任意多边形包括凹凸边形)

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


 
//offset为多边形坐标上限
//on_edge表示点在多边形边上时的返回值
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<time.h>
using namespace std;
const int offset=1000;
const double eps=1e-8;
struct Point{
    double x,y;
}p[105];
double cross(Point pi,Point pj,Point pk){ // (pi,pj)X(pi,pk)
    return (pj.x-pi.x)*(pk.y-pi.y)-(pj.y-pi.y)*(pk.x-pi.x);
}
int InPolygon(const Point *arr,const int &len,const Point &p,int on_edge=1){
 Point q;
 int i=0,counter;
 while(i<len){
   q.x=rand()+offset;//随机取一个足够远的点q
   q.y=rand()+offset;//以p为起点q为终点做射线L
   for(counter=i=0;i<len;i++){//依次对多边形的每条边进行考察
    if(fabs(cross(p,arr[i],arr[(i+1)%len]))<eps &&
    (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)
      return on_edge; //点p在边上,返回on_edge
    else if(fabs(cross(p,q,arr[i]))<eps) break; //点arr[i]在射线pq上,停止本循环,另取q
    else if(cross(p,arr[i],q)*cross(p,arr[(i+1)%len],q)<-eps &&
      cross(arr[i],p,arr[(i+1)%len])*cross(arr[i],q,arr[(i+1)%len])<-eps)
      counter++;
   }
 }
 return counter&1;
}
int main(){
 int n,m;
 while(scanf("%d",&n)==1){
   for(int i=0;i<n;i++)
    scanf("%lf%lf",&p[i].x,&p[i].y);
   scanf("%d",&m);
   Point temp;
   while(m--){
     scanf("%lf%lf",&temp.x,&temp.y);
     if(InPolygon(p,n,temp))
      puts("Yes");
     else
      puts("No");
   }
 }
 return 0;


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值