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;
}