zoukankan      html  css  js  c++  java
  • 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("
    ");
    85         printf("Problem %d:
    ",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
    ");
    91             else
    92                 printf("Outside
    ");
    93         }
    94     }
    95     return 0;
    96 }

    Freecode : www.cnblogs.com/yym2013

  • 相关阅读:
    node.js入门
    分布式爬虫
    ES6入门
    Vue.js入门
    用scrapy爬取亚马逊网站项目
    垃圾回收器
    HTTP协议详解
    有效的邮箱地址
    C#中正则表达式的使用
    抽象类
  • 原文地址:https://www.cnblogs.com/yym2013/p/3650678.html
Copyright © 2011-2022 走看看