zoj 1081:Points Within(计算几何,判断点是否在多边形内,经典题)

Points Within

Time Limit: 2 Seconds      Memory Limit: 65536 KB

Statement of the Problem

Several drawing applications allow us to draw polygons and almost all of them allow us to fill them with some color. The task of filling a polygon reduces to knowing which points are inside it, so programmers have to colour only those points.

You're expected to write a program which tells us if a given point lies inside a given polygon described by the coordinates of its vertices. You can assume that if a point is in the border of the polygon, then it is in fact inside the polygon.

Input Format

The input file may contain several instances of the problem. Each instance consists of: (i) one line containing integers N, 0 < N < 100 and M, respectively the number of vertices of the polygon and the number of points to be tested. (ii) N lines, each containing a pair of integers describing the coordinates of the polygon's vertices; (iii) M lines, each containing a pair of integer coordinates of the points which will be tested for "withinness" in the polygon.

You may assume that: the vertices are all distinct; consecutive vertices in the input are adjacent in the polygon; the last vertex is adjacent to the first one; and the resulting polygon is simple, that is, every vertex is incident with exactly two edges and two edges only intersect at their common endpoint. The last instance is followed by a line with a 0 (zero).

Output Format

For the ith instance in the input, you have to write one line in the output with the phrase "Problem i:", followed by several lines, one for each point tested, in the order they appear in the input. Each of these lines should read "Within" or "Outside", depending on the outcome of the test. The output of two consecutive instances should be separated by a blank line.

Sample Input

3 1
0 0
0 5
5 0
10 2
3 2
4 4
3 1
1 2
1 3
2 2
0

Sample Output

Problem 1:
Outside

Problem 2:
Outside
Within


  

  计算几何,判断点是否在多边形内

  套用了以前写的模板,很easy的就过了。经典题。

  代码:

 1 #include <stdio.h>
 2 struct Point{
 3     double x,y;
 4 };
 5 struct Line{
 6     Point p1,p2;
 7 };
 8 double xmulti(Point p1,Point p2,Point p0)    //求p1p0和p2p0的叉积,如果大于0,则p1在p2的顺时针方向
 9 {
10     return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
11 }
12 double Max(double a,double b)
13 {
14     return a>b?a:b;
15 }
16 double Min(double a,double b)
17 {
18     return a<b?a:b;
19 }
20 bool ponls(Point q,Line l)    //判断点q是否在线段l上
21 {
22     if(q.x > Max(l.p1.x,l.p2.x) || q.x < Min(l.p1.x,l.p2.x)
23         || q.y > Max(l.p1.y,l.p2.y) || q.y < Min(l.p1.y,l.p2.y) )
24         return false;
25     if(xmulti(l.p1,l.p2,q)==0)    //点q不在l的延长线或者反向延长线上,如果叉积再为0,则确定点q在线段l上
26         return true;
27     else
28         return false;
29 }
30 bool pinplg(int pointnum,Point p[],Point q)
31 {
32     Line s;
33     int c = 0;
34     for(int i=1;i<=pointnum;i++){    //多边形的每条边s
35         if(i==pointnum)
36             s.p1 = p[pointnum],s.p2 = p[1];
37         else
38             s.p1 = p[i],s.p2 = p[i+1];
39         if(ponls(q,s))    //点q在边s上
40             return true;
41         if(s.p1.y != s.p2.y){    //s不是水平的
42             Point t;
43             t.x = q.x - 1,t.y = q.y;
44             if( (s.p1.y == q.y && s.p1.x <=q.x) || (s.p2.y == q.y && s.p2.x <= q.x) ){    //s的一个端点在L上
45                 int tt;
46                 if(s.p1.y == q.y)
47                     tt = 1;
48                 else if(s.p2.y == q.y)
49                     tt = 2;
50                 int maxx;
51                 if(s.p1.y > s.p2.y)
52                     maxx = 1;
53                 else
54                     maxx = 2;
55                 if(tt == maxx) //如果这个端点的纵坐标较大的那个端点
56                     c++;
57             }
58             else if(xmulti(s.p1,t,q)*xmulti(s.p2,t,q) <= 0){    //L和边s相交
59                 Point lowp,higp;
60                 if(s.p1.y > s.p2.y)
61                     lowp.x = s.p2.x,lowp.y = s.p2.y,higp.x = s.p1.x,higp.y = s.p1.y;
62                 else
63                     lowp.x = s.p1.x,lowp.y = s.p1.y,higp.x = s.p2.x,higp.y = s.p2.y;
64                 if(xmulti(q,higp,lowp)>=0)
65                     c++;
66             }
67         }
68     }
69     if(c%2==0)
70         return false;
71     else
72         return true;
73 }
74 int main()
75 {
76     int i,n,m,num=1;
77     while(scanf("%d",&n)!=EOF){
78         if(n==0) break;
79         scanf("%d",&m);
80         Point p[101];
81         for(i=1;i<=n;i++)    //输入多边形的顶点
82             scanf("%lf%lf",&p[i].x,&p[i].y);
83         if(num!=1)    //如果不是第一组数据块就先输出一个空行
84             printf("\n");
85         printf("Problem %d:\n",num++);
86         for(i=1;i<=m;i++){
87             Point t;
88             scanf("%lf%lf",&t.x,&t.y);
89             if(pinplg(n,p,t))
90                 printf("Within\n");
91             else
92                 printf("Outside\n");
93         }
94     }
95     return 0;
96 }

 

Freecode : www.cnblogs.com/yym2013

posted @ 2014-04-07 20:56  Freecode#  阅读(745)  评论(0编辑  收藏  举报