首先明白 在任意多边形内一点,发射一条射线(以水平为例),必然与奇数条变相交。
如下图为例:
那么我们得到判定条件:
奇数个交点 ==》 点在多边形内
偶数个交点 ==》 点在多边形外
特例说明,如果要是设定,在线段上也算点在多边形内
那么判断共线且非射线即可。
代码如下:
#include<iostream>
#include<vector>
using namespace std;
const double eps=1e-8;
inline int dcmp(double x){
return x<-eps ? -1:x>eps;
}
struct Point{
double x,y;
Point(){}
Point(double a,double b):x(a),y(b){}
Point operator -(const Point &rhs) const{
return Point(x-rhs.x,y-rhs.y);
}
};
double det(const Point &a,const Point &b)
{
return a.x*b.y-a.y*b.x;
}
double dot(const Point &a,const Point &b)
{
return a.x*b.x+a.y*b.y;
}
bool on_point_segment(Point p,Point a1,Point a2)
{
return dcmp(det(a1-p,a2-p))==0&&dcmp(dot(a1-p,a2-p))<=0;
}
int in_point_polygon(Point o,const vector<Point> &poly,bool flag)
{
int t=0,k;
Point a,b;
int n=poly.size();
for(int i=0;i<n;i++)
{
if(on_point_segment(o,poly[i],poly[(i+1)%n]))
return flag;
}
for(int i=0;i<n;i++)
{
a=poly[i];
b=poly[(i+1)%n];
if(dcmp(a.y-b.y)>0)swap(a,b);
if(dcmp(det(a-o,b-o))<0&&dcmp(a.y-o.y)<0&&dcmp(o.y-b.y)<=0)
t++;
}
k=t&1;
if(k==1)
return 2;
else
return 0;
}
int main()
{
vector <Point> a;
vector <Point> b;
int n,m;
Point s;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>s.x>>s.y;
a.push_back(s);
}
cin>>m;
for(int i=0;i<m;i++)
{
cin>>s.x>>s.y;
b.push_back(s);
}
for(int i=0;i<m;i++)
{
printf("%d\n",in_point_polygon(b[i],a,1));
}
}
例题:
题目背景
原魔在最近一次更新中,上线了「层岩巨渊」。其中许多区域分布着神秘的「黑泥」,角色处于「黑泥」中,攻击力会变得更强,与旅行者战斗时具有巨大优势。但「层岩巨渊」非常昏暗,原魔们需要你来帮助他们判断他与「黑泥」的位置关系。
题目描述
「黑泥」呈区域性分布,具体来说是一个凸多边形。逆时针给出每个顶点的坐标,并给出若干角色的坐标。请你判断角色与「黑泥」的位置关系。若角色在「黑泥」外请输出0
,若角色在「黑泥」边界上请输出1
,若角色在「黑泥」内请输出2
,
输入格式
第一行一个正整数n,表明这是一个n边形 接下来n行,每行两个数x,y。表明这个顶点的横坐标与纵坐标。 第n+1行一个正整数m,表明接下来有m次查询。 接下来m行,每行两个整数x,y。表明这个查询点(即角色所在坐标)的横坐标与纵坐标。
输出格式
输出m行,每行为角色与「黑泥」的位置关系(0或1或2)
样例输入
4 0 0 3 1 2 3 0 3 3 2 1 0 2 3 2
样例输出
2 1 0
数据范围
-
凸多边形的端点互不相同
-
凸多边形的任意两边最多只有一个交点