判断点在多边形内部

来源:互联网 发布:电脑没网络怎么装驱动 编辑:程序博客网 时间:2024/04/29 05:28

用的是射线法,我的代码取的是向右的射线

这题没有点在边上的情况,但是还是要考虑很多

 

比如射线覆盖边,射线交短点的情况,为了区分各种状况 我分成了6中相交情况~

 

唉~有点多了 ~不过比较清晰~不知道别人是怎么做的

 

#include <stdio.h>struct edge{double ax,ay,bx,by;};struct point{double x,y;};//存储边edge E[105];point P[105];int N,M;//N边数也是点数,M待测点数void readE(){int i;for(i=0;i<N;++i)scanf("%lf%lf",&P[i].x,&P[i].y);for (i=0;i<N-1;++i){E[i].ax=P[i].x;E[i].ay=P[i].y;E[i].bx=P[i+1].x;E[i].by=P[i+1].y;}E[N-1].ax=P[N-1].x;E[N-1].ay=P[N-1].y;E[N-1].bx=P[0].x;E[N-1].by=P[0].y;}bool EQU(const double &a,const double &b){return a-b> - 10e-8 && a-b < 10e-8;}bool LESS(const double &a,const double &b){return a< b-10e-8;}bool GREATER(const double &a,const double &b){return a > b +10e-8;}// 0 不相交 1交叉  2 交1上 3 交2上 4交1下 5交2下  6覆盖int hor_cross_seg(point o,edge e){if (EQU(o.y,e.ay) && EQU(o.y,e.by)){if(o.x < e.ax-10e-8 && o.x < e.bx-10e-8)return 6;else return 0;}//上if (LESS(o.x,e.ax)&&EQU(o.y,e.ay)&& GREATER(o.y,e.by) ){return 2;}if(LESS(o.x,e.bx)&&EQU(o.y,e.by)&& GREATER(o.y,e.ay)) return 3;//下if (LESS(o.x,e.ax)&&EQU(o.y,e.ay)&& LESS(o.y,e.by)){return 4;}if (LESS(o.x,e.bx) && EQU(o.y,e.by)&& LESS(o.y,e.ay)){return 5;}//交叉if (EQU(e.by,e.ay)&& !EQU(o.y,e.ay)){return 0;}if (GREATER(e.ay,o.y)  && GREATER(e.by,o.y) ||(LESS(e.ay,o.y)  && LESS(e.by,o.y))){return 0;}double x=(o.y-e.ay)/(e.by-e.ay)*(e.bx-e.ax)+e.ax;if (x>o.x){return 1;}return 0;}bool testPoint(point t){int i,num=0;int laststatus,curst;laststatus=hor_cross_seg(t,E[N-1]);for (i=0;i<N;++i){curst=hor_cross_seg(t,E[i]);if (curst==0){laststatus=curst;}elseif (curst==1){laststatus=curst;++num;}elseif (curst==2){if(laststatus==5)  ++num;laststatus=curst;}elseif (curst==3){laststatus=curst;}elseif (curst==4){if(laststatus==3)  ++num;laststatus=curst;}elseif (curst==5){laststatus=curst;}}return num%2;}int calc(){int i,sum=0;point t;for (i=0;i<M;++i){scanf("%lf%lf",&t.x,&t.y);if(testPoint(t))sum++;}return sum;}int main(){while (scanf("%d",&N),N!=0){readE();scanf("%d",&M);printf("%d/n",calc());}}