判断一个点是否在多边形内

  1 /*
  2 fzu_1120
  3 判断点q是否在多边形内的一种方法,过q作水平射线L,
  4 如果L与多边形P的边界不相交,则q在P的外部。否则,
  5 L和P的边界相交,具体地说,交点个数为奇(偶)数
  6 时,点q在P的内(外)部。 */
  7 
  8 #include <stdio.h>
  9 #include <stdlib.h>
 10 #include <math.h>
 11 
 12 #define MaxNode 50
 13 #define INF  999999999
 14 
 15 typedef struct TPoint
 16 {
 17     double x;
 18     double y;    
 19 }TPoiont;
 20 
 21 typedef struct TSegment
 22 {
 23     
 24     TPoint p1;
 25     TPoint p2;
 26 }TSegment;
 27 
 28 typedef struct TPolygon
 29 {
 30     TPoint point[MaxNode];
 31     int n;
 32 }TPolygon;
 33 
 34 double multi(TPoint p1, TPoint p2, TPoint p0)
 35 {
 36     //求矢量[p0, p1], [p0, p2]的叉积
 37     //p0是顶点 
 38     return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
 39     //若结果等于0,则这三点共线
 40     //若结果大于0,则p0p2在p0p1的逆时针方向
 41     //若结果小于0,则p0p2在p0p1的顺时针方向 
 42 }
 43 
 44 double max(double x, double y)
 45 {
 46     //比较两个数的大小,返回大的数
 47     if(x > y) return x;
 48     else return y; 
 49 }
 50 
 51 double min(double x, double y)
 52 {
 53     //比较两个数的大小,返回小的数
 54     if(x < y) return x;
 55     else return y; 
 56 }
 57 
 58 bool Intersect(TSegment L1, TSegment L2)
 59 {
 60     //线段l1与l2相交而且不在端点上时,返回true    
 61     //判断线段是否相交
 62     //1.快速排斥试验判断以两条线段为对角线的两个矩形是否相交 
 63     TPoint s1 = L1.p1;
 64     TPoint e1 = L1.p2;
 65     TPoint s2 = L2.p1;
 66     TPoint e2 = L2.p2;
 67     //2.跨立试验
 68     if(
 69         (max(s1.x, e1.x) > min(s2.x, e2.x)) &&
 70         (max(s2.x, e2.x) > min(s1.x, e1.x)) &&
 71         (max(s1.y, e1.y) > min(s2.y, e2.y)) &&
 72         (max(s2.y, e2.y) > min(s1.y, e1.y)) &&
 73         (multi(s2, e1, s1) * multi(e1, e2, s1) > 0) &&
 74         (multi(s1, e2, s2) * multi(e2, e1, s2) > 0)
 75         )  return true;
 76     
 77     return false;    
 78 }
 79 
 80 
 81 bool Online(TSegment L, TPoint p)
 82 {
 83     //p在L上(不在端点)时返回true
 84     //1.在L所在的直线上 
 85     //2.在L为对角线的矩形中
 86     double dx, dy, dx1, dy1;
 87     dx = L.p2.x - L.p1.x;
 88     dy = L.p2.y - L.p1.y;
 89     dx1 = p.x - L.p1.x;
 90     dy1 = p.y - L.p1.y;
 91     if(dx * dy1 - dy * dx1 != 0) return false; //叉积
 92     if(dx1 * (dx1 - dx) < 0 || dy1 * (dy1 - dy) < 0) return true;
 93     return false; 
 94 }
 95 
 96 bool same1(TSegment L, TPoint p1, TPoint p2)
 97 {
 98     //判断p1, p2是否在L的同侧 
 99     if(multi(p1, L.p2, L.p1) * multi(L.p2, p2, L.p1)< 0) return true;
100     return false;    
101 }
102 
103 bool Inside(TPoint q, TPolygon polygon)
104 {
105     int c, i;
106     TSegment L1, L2;
107     c = 0;
108     L1.p1 = q;
109     L1.p2 = q;
110     L1.p2.x = INF; 
111     /*
112     (1)相交 
113     1.p[i]和p[i+1]在L的两侧 
114     2.p[i]和p[i+2]在L的同侧
115     3.p[u]和p[i+3]在L的同侧或异侧 
116     */
117     for(i = 0;i <= polygon.n - 1;i++){
118         L2.p1 = polygon.point[i];
119         L2.p2 = polygon.point[(i + 1) % polygon.n];
120         if(Intersect(L1, L2)){
121             c++; 
122             continue;
123         }
124         if(!Online(L1, polygon.point[(i + 1) % polygon.n])) continue; 
125         if(!Online(L1, polygon.point[(i + 2) % polygon.n]) && 
126             !same1(L1, polygon.point[i], polygon.point[(i + 2) % polygon.n])){
127             c++;
128             continue;
129         }
130         if(Online(L1, polygon.point[(i + 2) % polygon.n]) && 
131             !same1(L1, polygon.point[i], polygon.point[(i + 3) % polygon.n]))
132             c++;
133     }  
134     if(c % 2 == 0) return false;
135     else return true;
136 }
137 
138 int main()
139 {
140     int i, test, k;
141     int primp, primq;
142     TPoint p;
143     p.x = 0;
144     p.y = 0;
145     test = 1;
146     TPolygon polygon;
147     while(scanf("%d", &polygon.n) != EOF && polygon.n){
148         printf("Pilot %d\n", test++);
149         for(i = 0;i <= polygon.n - 1;i++){
150             scanf("%lf%lf", &polygon.point[i].x, &polygon.point[i].y);
151         }
152         scanf("%d%d", &primp, &primq);
153         if(Inside(p, polygon)){
154             printf("The pilot is in danger!\n");
155             k = (primp - 1) * (primq - 1) / 2;
156             printf("The secret number is %d.\n", k); 
157         }
158         else printf("The pilot is safe.\n");
159         printf("\n");
160     }
161     return 0;
162 }

 

你可能感兴趣的:(判断一个点是否在多边形内)