zoukankan      html  css  js  c++  java
  • zoj 1081 Points Within 判断点是否在任意多边形内(模板)

    题目来源:

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=81

    分析:

    从p点出发做平行于x轴的射线 l。 求射线与 多边形 线段的交点数num, 若是偶数 , 该点 在外, 若为奇数, 该点在内。

    注意: 两个特判,  

    1:   一个是 射线 l 与 多边形的边  重合 , 若该p点在 线段上, 返回1, 否则 交点 记为 0 个

    2: 一个是 射线与 线段的交点 ,为线段的端点, 则我们 对线段的 较低交点 不计算。

    代码如下:

    const double EPS = 1e-12;
    const int Max_N = 110;
    double add(double a, double b){
        return (fabs(a + b) < EPS * ( fabs(a) + fabs(b) )) ? 0 : (a+ b) ;
    }
    struct Point{
        double x, y;
        Point(){}
        Point(double x , double y):x(x), y(y){}
        double dist(Point p){
            return sqrt( add( (x - p.x)*(x - p.x) , (y - p.y)*(y - p.y) ) ) ;
        }
        Point operator - (Point p){
            return Point( add(x ,- p.x) , add(y, - p.y)) ;
        }
        bool operator ==(Point p){
            return (add(x,-p.x) == 0)  && (add(y, -p.y) == 0) ;
        }
        double operator ^(Point p){
            return add(x * p. y , - y * p.x) ;
        }
    }po[Max_N];
    //判断点p0是否在线段p1p2内
    int on_segment(Point p1, Point p2, Point p0)
    {
        if (((p1-p0).x * (p2-p0).x <=0 )&& ((p1-p0).y * (p2-p0).y <=0))   // 中间是 &&
            return 1;
        return 0;
    }
    // 判断线段p1p2与q1是否相交
    int intersection(Point p1,Point p2, Point q1,Point q2)
    {
        double d1=(p2-p1)^(q1-p1);
        double d2=(p2-p1)^(q2-p1);
        double d3=(q2-q1)^(p1-q1);  //--由于前面的特判,低处的交点不作为计算------
        double d4=(q2-q1)^(p2-q1);
        if((d1==0 && on_segment(p1,p2,q1) )
           || (d2==0 && on_segment(p1,p2,q2) )
          // ||(d3==0&& on_segment(q1,q2,p1))     //由于前面的特判,低处的交点不作为计算-
           || (d4==0 && on_segment(q1,q2,p2)))
           return 1;
        else if(d1*d2<0 && d3*d4 <0)    // 中间是 &&
            return 1;
        return 0;
    }
    // 判断点p是否在线段p1p2上
    bool in_segment(Point p1, Point p2, Point p){
        return ( ((p - p1)^(p2 - p1)) == 0 && on_segment(p1 , p2 , p)) ;
    }
    int n , i ;
    // 判断点p在任意多边形po[Max_n]内, 顶点按顺时针或逆时针给出
    // 在边上返回2, 严格在内返回1, 严格在外返回0
    int point_is_inside(Point p){
        int i, num = 0;
        Point q ;
        q.x = 9999999.0 , q.y = p. y ; //q为平行于x轴 p点射线的终点
        for(i = 0 ; i< n;  i++){
            if(in_segment(po[i] ,po[(i+1 ) % n] , p ) )
                return 2;
            Point p1, p2 ;
            p1 = po[i], p2 = po[(i+1 ) % n] ;
            if(p1.y == p2.y)  // 特判,射线与重边的处理,交点数为0,不计算
                continue ;
            if(p1.y > p2.y)
                swap(p1, p2) ; // p1为较小点, 特判,低处的交点不计算
            if(intersection( p1 , p2 , p , q ))
                num ++ ;
        }
        return num & 1 ;
    }
    int main(){
        int  m  , i, j , k = 1  , t = 0 ;
        Point a;
        while(scanf("%d" , & n) && n){
            if(t) puts("") ;
            t++ ;
            scanf("%d" , &m) ;
            printf("Problem %d:
    " , k++) ;
            for(i = 0 ; i < n; i++)
                scanf("%lf%lf" , &po[i].x, &po[i].y ) ;
            for(i = 0 ; i< m ; i++){
                scanf("%lf%lf" , &a.x , &a.y) ;
                if(point_is_inside(a))
                    puts("Within") ;
                else puts("Outside") ;
            }
        }
        return 0;
    }
  • 相关阅读:
    jvm调优核心思路
    G1 垃圾回收器
    类加载和内存区域划分
    jvm优化案例
    垃圾回收
    buffer pool详解
    InnoDb存储引擎执行流程
    mysql总体架构
    (转载)C#串口介绍以及简单串口通信程序设计实现
    C++文本操作(读写文本文件/二进制文件)
  • 原文地址:https://www.cnblogs.com/zn505119020/p/3709757.html
Copyright © 2011-2022 走看看