ZOJ1081(射线法判断点是否在多边形内部)
射线法判是否在多边形内部的板子吧
射线法:过该点做一条平行于x轴的射线 ,若该与多边形有奇数个交点,则该点在多边形内部
这可以转化为求改点与多边形的每一条边是否有交点
但要注意一些特殊情况,比如交点时多边形的顶点,这时我们需要规定交在边的下端点 统计进答案或是交在边的上端点统计进答案
(也就是保证一个点要么都被统计要么都不被统 计)。
详解代码
#include<bits/stdc++.h>
using namespace std;
int n,m;
inline int read(){
char ch=getchar();
int res=0,f=1;
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
return res*f;
}
struct point{
int x,y;
point(){}
point(int a,int b):
x(a),y(b){}
friend inline point operator -(const point &a,const point &b){//重载运算符
return point(b.x-a.x,b.y-a.y);
}
friend inline int operator *(const point &a,const point &b){
return a.x*b.y-a.y*b.x;
}
friend inline int dot(const point &a,const point &b){//点积
return a.x*b.x+a.y*b.y;
}
}f,p[105];
inline bool check(const point &a,const point &b,const point &c){//判断共线的情况 (三点共线且被判定的点在线段中间)
int d=(a-c)*(b-c);
if(d!=0) return false;//如果差积不为0,则三点不共线
int fk=dot(a-c,b-c);
return fk<=0;//如果点积大于0,则被判定的点不在线段中间
}
inline int area(){//求多边形的面积
int ans=0;
for(int i=0;i<n;i++){
ans+=p[i]*p[i+1];
}
return ans;
}
inline bool init(point q){
int num=0;
for(int i=0;i<n;i++){//枚举找相交的边
if(check(p[i],p[i+1],q)) return true;//如果在线段之间则满足
int f1=p[i].y-q.y,f2=p[i+1].y-q.y;
int det=(p[i]-q)*(p[i+1]-q);
if((det>=0&&f1<0&&f2>=0)||(det<=0&&f1>=0&&f2<0)) num++;//这里默认的是做一条平行于x轴的射线,并判断有没有交点
}
return num&1;//相交的边数是否为奇数
}
int main(){
for(int T=1;;T++){
n=read();
if(n==0) break;
m=read();
for(int i=0;i<n;i++){
p[i].x=read(),p[i].y=read();
}
p[n]=p[0];
if(T!=1){
cout<<'\n';
}
cout<<"Problem "<<T<<":"<<'\n';
for(int i=1;i<=m;i++){
f.x=read(),f.y=read();
if(init(f)) cout<<"Within"<<'\n';
else cout<<"Outside"<<'\n';
}
}
}