点在多边形内算法——判断一个点是否在一个复杂多边形的内部
假设我们有一个多边形由n个点组成Pn={p1,p2,p3,p4,p5...pn}
, 求一个点p(x,y)
是否在多边形内?
在图形编程中,坐标的利用是不可忽视的。在这里判断一个点是否在多边行内部(可以包括线上)就要利用到各个点的坐标关系。
最简单的方法是使用射线法,因为它能适用于所有类型的多边形,不用考虑特殊的情况而且速度也比较快。该算法的思想很简单:在多边形外面任意一点画一条虚拟的射线到p(x,y)
然后计算该射线与多边形上的边相交的次数。如果该次数是偶数,说明p(x,y)
在多边形外,如果是奇数,则在多边形内。
题目:zzuoj 1245
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <cmath> #include <queue> #include <set> using namespace std; #define maxn 110 double x0,yy0; int n,m; double x[maxn],y[maxn]; bool contains(double x0,double yy0) { int crossings = 0; for(int i = 0;i < m;i++) { bool cond1 = (x[i] <= x0) && (x0 < x[i+1]); bool cond2 = (x[i+1] <= x0) && (x0 < x[i]); //容易错的地方:计算斜率时一定要判断它存不存在,否则会re if((cond1 || cond2) && x[i+1]-x[i] == 0) { if(yy0 <= y[i] && yy0 >= y[i+1] || yy0 >= y[i] && yy0 <= y[i+1]) { return true; }else{ return false; } }else{ double slope = (y[i+1]-y[i])/(x[i+1]-x[i]); bool above = (fabs(yy0-slope*(x0-x[i])+y[i])< 1e-7); bool e = (yy0 == slope*(x0-x[i])+y[i]); if((cond1 || cond2) && e) return true; if((cond1 || cond2) && above) crossings++; } } return (crossings % 2 != 0); } int main() { while(~scanf("%lf%lf%d%d",&x0,&yy0,&n,&m)) { int tag =-1; for(int i = 1;i <= n;i++) { for(int j = 0;j < m;j++) { scanf("%lf%lf",&x[j],&y[j]); } x[m] = x[0];y[m] = y[0]; if(tag == -1) { if(contains(x0,yy0)) tag = i; } } printf("%d\n",tag); } }