判断一个点P是否在多边形内部,有下面一个简单有效的算法:
注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,如果P在多边形外部,则交点个数必为偶数(0也在内)。
所以,我们可以顺序考虑多边形的每条边,求出交点的总个数。
还有一些特殊情况要考虑。
假如考虑边(P1,P2)
1)如果射线正好穿过P1或者P2,那么这个交点会被算作2次,处理办法是如果P的从坐标与P1,P2中较小的纵坐标相同,则直接忽略这种情况
2)如果射线水平,则射线要么与其无交点,要么有无数个,这种情况也直接忽略。
3)如果射线竖直,而P0的横坐标小于P1,P2的横坐标,则必然相交。
4)再判断相交之前,先判断P是否在边(P1,P2)的上面,如果在,则直接得出结论:P再多边形内部。
相关题目可以看下: http://acm.zju.edu.cn/show_problem.php?pid=1081
my code:
#include
<
iostream
>
using
namespace
std;
#define
eps 1.0e-5


inline
double
max(
double
a,
double
b)
{ return a>b?a:b; }

inline
double
min(
double
a,
double
b)
{ return a<b?a:b; }

inline
double
dabs(
double
a)
{ return a<0?-a:a; }

struct
Point
{
double x,y;
}
;

Point poly[
110
];
int
n,m;


bool
online(
const
Point
&
p1,
const
Point
&
p2,
const
Point
&
p3)
{
if(p2.x>=min(p1.x,p3.x)&&p2.x<=max(p1.x,p3.x)

&&p2.y>=min(p1.y,p3.y)&&p2.y<=max(p1.y,p3.y))
{
if(dabs((p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y))<=eps)
return true;
}
return false;
}


bool
insidepolygon(Point p)
{
int counter=0;
double xinters;
Point p1,p2;

p1=poly[0];

for(int i=1;i<=n;i++)
{
p2=poly[i%n];
if(online(p1,p,p2)) return true;

if(p.y>min(p1.y,p2.y))
{

if(p.y<=max(p1.y,p2.y))
{

if(p.x<=max(p1.x,p2.x))
{

if(p1.y!=p2.y)
{
xinters=(p.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
if(p1.x==p2.x||p.x<=xinters) counter++;
}
}
}
}
p1=p2;
}
if(counter%2==0)
return false;
return true;
}


int
main()
{
int t=0;
Point p;

while(cin>>n)
{
if(n==0) break;
if(t++>0) cout<<endl;
cout<<"Problem "<<t<<":"<<endl;
cin>>m;
for(int i=0;i<n;i++)
cin>>poly[i].x>>poly[i].y;

for(int i=0;i<m;i++)
{
cin>>p.x>>p.y;
if(insidepolygon(p))
cout<<"Within"<<endl;
else
cout<<"Outside"<<endl;
}
}
return 0;
}

注意到如果从P作水平向左的射线的话,如果P在多边形内部,那么这条射线与多边形的交点必为奇数,如果P在多边形外部,则交点个数必为偶数(0也在内)。
所以,我们可以顺序考虑多边形的每条边,求出交点的总个数。
还有一些特殊情况要考虑。
假如考虑边(P1,P2)
1)如果射线正好穿过P1或者P2,那么这个交点会被算作2次,处理办法是如果P的从坐标与P1,P2中较小的纵坐标相同,则直接忽略这种情况
2)如果射线水平,则射线要么与其无交点,要么有无数个,这种情况也直接忽略。
3)如果射线竖直,而P0的横坐标小于P1,P2的横坐标,则必然相交。
4)再判断相交之前,先判断P是否在边(P1,P2)的上面,如果在,则直接得出结论:P再多边形内部。
相关题目可以看下: http://acm.zju.edu.cn/show_problem.php?pid=1081
my code:




































































































