关键是分清楚各种情况,写各种判断模块的时候不要漏掉某些情况,所以计算几何一般都是套现成的模板,自己手敲会很难保证不出问题
用的是求射线与多边形交点数的方法,模板是 XY 的,很精练了已经,嘿嘿,站在别人的键盘上,写着就是轻松好多啊……
#include<stdio.h> #include<math.h> #include<string.h> #define esp 1e-8 #define N 30 int dy(double x,double y) { return x > y + esp;}// x > y int xy(double x,double y) { return x < y - esp;}// x < y int dyd(double x,double y) { return x > y - esp;}// x >= y int xyd(double x,double y) { return x < y + esp;}// x <= y int dd(double x,double y) { return fabs( x - y ) < esp;}// x == y double max(double x,double y) { if(dy(x,y))return x; return y; } double min(double x,double y) { if(xy(x,y))return x; return y; } struct point { double x,y; }; double xmult(point a,point b,point c) { return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } int onSegment(point a,point b,point c) { if(dd(xmult(a,b,c),0.0)&& dyd(c.x,min(a.x,b.x)) && xyd(c.x,max(a.x,b.x)) && dyd(c.y,min(a.y,b.y)) && xyd(c.y,max(a.y,b.y))) return 1; return 0; } int is_Cross(point a,point b,point c,point d) { double d1=xmult(c,d,a); double d2=xmult(c,d,b); double d3=xmult(a,b,c); double d4=xmult(a,b,d); if(xy(d1*d2,0.0) && xy(d3*d4,0.0))return 1; if(dd(d1,0.0) && onSegment(c,d,a) || dd(d2,0.0) && onSegment(c,d,b) || dd(d3,0.0) && onSegment(a,b,c) || dd(d4,0.0) && onSegment(a,b,d) ) return 1; return 0; } int point_inPolygon(point po,point p[],int n) { point a=po,b; b.x=1e20; b.y=po.y; p[n]=p[0]; int i,cnt=0; for(i=0;i<n;i++) { //点 po 在多边形某条边上 if(onSegment(p[i],p[i+1],po)) return 1; //点 po 不在多边形边上 if( !dd(p[i].y,p[i+1].y) )//平行的边不考虑 { //判断 p[i],p[i+1]两点是否在a,b上 int tmp=-1; if( onSegment(a,b,p[i]) ) tmp=i; else if( onSegment(a,b,p[i+1]) ) tmp=i+1; //对于多边形的顶点和射线a,b相交的情况,如果该顶点是其所属的边上纵坐标较大的顶点,则计数,否则忽略 if( tmp!=-1 && dd(p[tmp].y,max(p[i].y,p[i+1].y)) || tmp==-1 && is_Cross(p[i],p[i+1],a,b) ) cnt++; } } return cnt%2==1; } int main() { int i,n,m,time=1,blank=0; point po,p[N]; while(scanf("%d",&n),n) { scanf("%d",&m); memset(p,0,sizeof(p)); for(i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); if(!blank) blank=1; else puts(""); printf("Problem %d:\n",time++); for(i=1;i<=m;i++) { scanf("%lf%lf",&po.x,&po.y); if( point_inPolygon(po,p,n) ) printf("Within\n"); else printf("Outside\n"); } } return 0; }