ZOJ1081 Points Within

本文介绍了一种计算几何中的基本算法——判断一个点是否位于一个多边形内部的方法。该方法通过从待判断的点出发绘制一条射线,并统计射线与多边形边界相交的次数来实现。如果交点数量为奇数,则认为该点在多边形内;反之则在外部。此外还考虑了特殊情况,如点恰好位于多边形的边上。

计算几何问题,基本思想从要判断的点引一条射线看和多边形交点的个数,如果是奇数个,那么就在多边形内,否则在多边形外。先判断点是否在多边形边上的情况判掉,再判断线段相交。

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->#include<iostream>
#include
<vector>
usingnamespacestd;

constintMAXSIZE=100;
constdoubleMax=100000000;

structPoint
{
doublex;
doubley;
}points[MAXSIZE];

Pointpc;
//选择的射线点

doubleCrossMultiply(constPoint&a,constPoint&b,constPoint&c)
{
//叉乘
doublex1,y1,x2,y2;
x1
=b.x-a.x;
y1
=b.y-a.y;
x2
=c.x-b.x;
y2
=c.y-b.y;
returnx1*y2-x2*y1;
}
doubleinterSect(constPoint&a,constPoint&b,constPoint&c,constPoint&d)
{
doubled1,d2,d3,d4;
d1
=CrossMultiply(a,b,c),
d2
=CrossMultiply(a,b,d),
d3
=CrossMultiply(c,d,a),
d4
=CrossMultiply(c,d,b);
if((d1*d2)<0&&(d3*d4)<0)
return1.;
elseif((d1*d2)==0||(d3*d4)==0)
return0;
else
return-1.;
}
boolIsOnEdge(constPoint&p,constvector<Point>&ptVect)
{
//点是否在边上
inti,j,size,minX,maxX,minY,maxY;
size
=ptVect.size();//点的数目
for(i=0;i<size;++i)
{
j
=i+1;
if(j==size)
{
j
=0;
}
if(CrossMultiply(ptVect[i],ptVect[j],p)==0)
{
//在同一直线上
if(p.x>=min(ptVect[i].x,ptVect[j].x)&&p.x<=max(ptVect[i].x,ptVect[j].x)&&p.y>=min(ptVect[i].y,ptVect[j].y)&&p.y<=max(ptVect[i].y,ptVect[j].y))
{
//在线段内
returntrue;
}
}
}
returnfalse;
}
boolisInside(constPoint&p,constvector<Point>&ptVect)
{
//判断点是否在多边形内部
inti,j,num,size;
doubled;
num
=0;//射线与线段相交的点的个数
size=ptVect.size();
for(i=0;i<size;++i)
{
//处理每条线段
j=i+1;
if(j==size)
{
j
=0;
}
d
=interSect(p,pc,ptVect[i],ptVect[j]);
if(d>0)
num
++;//严格相交
elseif(d==0)
{
//有一端点在另一直线上
if(ptVect[i].y>0||ptVect[j].y>0)
num
++;
}
}
if(num%2==0)
returnfalse;
else
returntrue;
}
intmain(void)
{
intN,M,i,pX,pY,cases=0;
while(cin>>N&&N!=0)
{
cin
>>M;
if(cases!=0)
cout
<<endl;
vector
<Point>pointVect;
for(i=0;i<N;++i)
{
cin
>>points[i].x>>points[i].y;
pointVect.push_back(points[i]);
}
cout
<<"Problem"<<++cases<<":"<<endl;
for(i=0;i<M;++i)
{
Pointp;
cin
>>p.x>>p.y;
pc.x
=Max,pc.y=p.y;//故意把射线点选择在同一水平线,无穷远处
if(IsOnEdge(p,pointVect))
{
//在一条边上
cout<<"Within"<<endl;
continue;
}
elseif(isInside(p,pointVect))
{
//在多边形内部
cout<<"Within"<<endl;
}
else
{
cout
<<"Outside"<<endl;
}
}
}
return0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值