ZOJ1081 Points Within,判断点是否在多边形 内

/*******************************************************************************
 # Author : Neo Fung
 # Email : neosfung@gmail.com
 # Last modified: 2011-11-15 21:31
 # Filename: ZOJ1081 Points Within.cpp
 # Description : 
 ******************************************************************************/
// #include "stdafx.h"
// #define DEBUG

#include <fstream>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <string>
#include <memory.h>
#include <limits.h>
#include <algorithm>
#include <math.h>
#include <float.h>

#define MAX 110
#define EPS 1e-10
using namespace std;

struct POINT
{
	double x,y;
}point[MAX];

struct LINE{
	POINT a,b;
};

double inline Distance(const POINT &lhs,const POINT &rhs)
{	return sqrt((lhs.x-rhs.x)*(lhs.x-rhs.x)+(lhs.y-rhs.y)*(lhs.y-rhs.y));}

double inline crossProduct(const POINT &a,const POINT &b,const POINT &c)	
//向量ac在ab的方向
{	
	double ans=(c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);  
	return ans;
}

bool inline _less(const double &lhs,const double &rhs)
{
	return lhs < rhs - EPS;  
}
bool inline _less_or_equal(const double &lhs,const double &rhs)
{
	return lhs < rhs + EPS;  
}
bool inline _equal(const double &lhs,const double &rhs)
{
	return fabs(lhs-rhs)< EPS;  
}

/************************************************************************/
/* 点c是否在点a与点b的线段上(包括端点)                                */
/************************************************************************/
bool PointOnSegment(const POINT &a,const POINT &b,const POINT &c)
{
	if(_equal(crossProduct(a,b,c),0.0) &&
			_less_or_equal(min(a.x,b.x),c.x) &&
			_less_or_equal(c.x,max(a.x,b.x)) &&
			_less_or_equal(min(a.y,b.y),c.y) &&
			_less_or_equal(c.y,max(a.y,b.y)))
		return true;
	else
		return false;
}

/************************************************************************/
/* 确定两条线段是否相交                                                 */
/************************************************************************/
int   intersect(const LINE  &lhs,const LINE &rhs)  
{  
	return((max(lhs.a.x,lhs.b.x)>=min(rhs.a.x,rhs.b.x))&&  
		(max(rhs.a.x,rhs.b.x)>=min(lhs.a.x,lhs.b.x))&&  
		(max(lhs.a.y,lhs.b.y)>=min(rhs.a.y,rhs.b.y))&&  
		(max(rhs.a.y,rhs.b.y)>=min(lhs.a.y,lhs.b.y))&&  
		(crossProduct(lhs.a,lhs.b,rhs.a)*crossProduct(lhs.a,rhs.b,lhs.b)>=0)&&  
		(crossProduct(rhs.a,rhs.b,lhs.a)*crossProduct(rhs.a,lhs.b,rhs.b)>=0));  
}  


bool inPolygon(const POINT &p,const POINT *pArray,const int &n)
{
	if(n==1)
		return(_equal(pArray[0].x,p.x)&&_equal(pArray[0].y,p.y));
	if(n==2)
		return PointOnSegment(pArray[0],pArray[1],p);

	int sum=0;
	LINE tline;
	tline.a=p;
	tline.b.x=DBL_MAX;
	tline.b.y=p.y;

	for(int i=0;i<n;++i)
	{
		const POINT p1=pArray[i];
		const POINT p2=pArray[(i+1)%n];
		LINE side;
		side.a=p1;
		side.b=p2;

		if(PointOnSegment(p1,p2,p))
			return true;
		if(_equal(p1.y,p2.y))
			continue;

		if (intersect(side,tline))
		{
			++sum;
		}

	}
	return sum%2;
}

int main(void)
{
#ifdef DEBUG  
	freopen("data.txt","r",stdin);  
#endif  
	int n,m;
	int ncases=1,flag=1;
	POINT p;

	while(scanf("%d",&n) && n)
	{
		if (flag)
			flag=0;
		else
			printf("\n");

		scanf("%d",&m);
		printf("Problem %d:\n",ncases++);
		for (int i=0;i<n;++i)
		{
			scanf("%lf%lf",&point[i].x,&point[i].y);
		}

		while(m--)
		{
			scanf("%lf%lf",&p.x,&p.y);
			if (inPolygon(p,point,n))
			{
				printf("Within\n");
			} 
			else
			{
				printf("Outside\n");
			}
		}
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值