HDU 1756 Cupid's Arrow 计算几何 判断一个点是否在多边形内

LINK:Cupid's Arrow

前置函数 atan2 返回一个向量的幅角.范围为[Pi,-Pi)

值得注意的是 返回的是 相对于x轴正半轴的辐角。

而判断一个点是否在一个多边形内 通常有三种方法:

一种就是令这个点向多边形内所有边求角度的和 如果为2Pi 或者 -2Pi那么就在其中

一种是射线法 看这个点引出的射线和多边形的交点个数。奇数在内部 反之在外部。

面积判别法 看下和每条边所形成面积 是否等于多边形的面积。

前两者都还可以用于凹多边形 第三者我不太清楚。

这里使用的是第一种方法:

struct Vec
{
	db x,y;Vec(){}Vec(db _x,db _y){x=_x;y=_y;}
	inline Vec operator +(Vec b){return Vec(x+b.x,y+b.y);}
	inline Vec operator -(Vec b){return Vec(x-b.x,y-b.y);}
	inline Vec operator -(){return Vec(-x,-y);}
	inline db operator *(Vec b){return x*b.x+y*b.y;}
	inline db operator %(Vec b){return x*b.y-b.x*y;}
	inline db operator ~(){return x*x+y*y;}
	inline bool operator ==(Vec b){return fabs(x-b.x)<=EPS&&fabs(y-b.y)<=EPS;}
	inline bool operator !=(Vec b){return fabs(x-b.x)>EPS||fabs(y-b.y)>EPS;}
	inline Vec Unit(){db _=sq(x*x+y*y);return Vec(x/_,y/_);}
	inline Vec Norm(){db _=sq(x*x+y*y);return Vec(-y/_,x/_);}
	inline bool Quad(){return y>EPS||(fabs(y)<=EPS&&x>=-EPS);}
	inline bool operator <(Vec b){return fabs(y-b.y)<=EPS?x<b.x:y<b.y;}
};typedef Vec pt;
inline Vec operator /(Vec a,db k){return Vec(a.x/k,a.y/k);}
inline Vec operator *(Vec a,db k){return Vec(a.x*k,a.y*k);}
inline Vec operator *(db k,Vec a){return Vec(a.x*k,a.y*k);}
inline bool para(Vec a,Vec b){return fabs(a%b)<=EPS;}
inline bool Toleft(Vec a,Vec b){return b%a>EPS;}//判断a是否在b的左边.
inline void O(pt a,char c=' '){printf("(%.3lf,%.3lf)%c",a.x,a.y,c);}
const int MAXN=110;
const db Pi=acos(-1.0);
int n,m;
pt a[MAXN];
inline db Angle(pt a,pt b,pt c)
{
	db w;b=b-c;a=a-c;w=atan2(b.y,b.x)-atan2(a.y,a.x);
	cout<<atan2(b.y,b.x)<<endl;
	cout<<atan2(a.y,a.x)<<endl;
	w=w<=-Pi-EPS?w+2*Pi:w;w=w>=Pi+EPS?w-2*Pi:w;return w;
}
inline db sumAngle(pt c)
{
	db w=0;
	rep(1,n,i)w+=Angle(a[i],a[i+1],c);
	return w;
}
int main()
{
	freopen("1.in","r",stdin);
	while(gt(n)==1)
	{
		rep(1,n,i)
		{
			int x,y;
			gt(x),gt(y);
			a[i]=Vec(x,y);
		}
		a[n+1]=a[1];
		gt(m);
		//cout<<atan2(0.0,-1.0)<<endl;
		rep(1,m,i)
		{
			int x,y;
			gt(x),gt(y);
			db ww=sumAngle(Vec(x,y));
			if(fabs(ww)<=EPS)puts("No");
			else puts("Yes");
		}
	}
	return 0;
}
posted @ 2020-04-30 20:49  chdy  阅读(152)  评论(0编辑  收藏  举报