判断一个点是否在多边形内部
判断一个点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:
注意到如果从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;
}
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;
}