ZOJ1081 Points Within(判断点是否在多边形内部)

关键是分清楚各种情况,写各种判断模块的时候不要漏掉某些情况,所以计算几何一般都是套现成的模板,自己手敲会很难保证不出问题

用的是求射线与多边形交点数的方法,模板是 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;
}



 

你可能感兴趣的:(ZOJ1081 Points Within(判断点是否在多边形内部))