CGL_3_C:Polygon-Point Containment

题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C

题目给出一个多边形,然后给出一个点,需要判断该点与多边形的关系:

	IN 2 //在多边形内
	ON 1 //在多边形边上
	OUT 0//在多边形内部

基本思路是,

先判断这个点是不是在多变形的边上,用类似于ccw的方法来判断;

从这个点发出一条沿x轴方向的射线,射向这个多边形:

如果这条射线和这个多边形的交点个数为偶数,则说明该点在多边形外部;

如果这条射线和这个多边形的交点个数为奇数,则说明该店在多边形内部;

核心代码是这样:

int contains(Polygon g, Point p) {
	int n = g.size();
	bool x = false;
	for (int i = 0; i < n; i++) {
		Point a = g[i] - p, b = g[(i + 1) % n] - p;
		if (abs(cross(a, b)) < EPS && dot(a, b) < EPS) return 1;
		if (a.y > b.y) swap(a, b);
		if (a.y < EPS && EPS < b.y && cross(a, b) > EPS)
			x = !x;
	}
	return (x ? 2 : 0);
}

我们在代码中,这样来实现发出射线这个过程:

遍历这个多边形的每两个相邻的点,g[n]和g[n+1],和p点,先判断是否p点在g[n]和g[n+1]线段上,是的话直接return 1;

然后判断射线是否经过了这条线段:

以点p为原点,指向g[n]的向量为a,指向g[n+1]的向量为b;如果这两个向量一个在x轴上部,一个在y轴下部,那么就说明从点p发出的与x轴平行的射线是可以穿过这条线段的;

实现部分代码如下:


int main(){
	Polygon g;
	Point p ,t;
	int n, q;
	scanf("%d", &n);
	for (int i = 0; i < n; i++) {
		scanf("%lf %lf", &t.x, &t.y);
		g.push_back(t);
	}
	cin>>q;
	for (int i = 0; i < q; i++) {
		cin>>p.x>>p.y;
		cout<<contains(g, p)<<endl;
	}
	return 0;
}

错点:

1.在判断a和b是否一个在x轴上方,一个在x轴下方时,先选出一个y值较大的为a;然后在判断时,要注意      

 if (a.y < EPS && EPS < b.y && cross(a, b) > EPS) 要加上 cross(a, b) > EPS 避免出现三点共线,但是p点不在线段上的情况;

猜你喜欢

转载自blog.csdn.net/qq_33982232/article/details/81125220