UVALive 7004(计算几何 判断点与多边形的关系)

In a 2-D plane, there are n simple polygons. Some polygons may not be convex. Each polygon has atmost k vertices. Each vertex is represented as a pair of x and y coordinates. It is known that for eachvertex (x, y), x and y are both non-negative integers that are at most 100,000. Two polygons may haveoverlaps or even one is inside the other. Given a point P = (x p , y p ) in the plane, where x p and y p arealso non-negative integers that are at most 100,000, your task is to decide, for each polygon, whether

P is inside or outside the polygon, or on the boundary of it.


Technical Specification
• The number of polygons is bounded by 10, i.e., 0 < n ≤ 10.
• The number of vertices in a polygon is at least 3 and at most 10, i.e., 2 < k ≤ 10.

• Each coordinate in any vertex is at least 0 and at most 100,000.


Input
There are at most 10 test cases. The first line is the number of test cases. For each test case, the first
line contains three integers n, x p and y p which are the number of polygons, and the x and y coordinates
of the point P . The next n lines each contain the number of vertices and the coordinates of the vertices
of each polygon in clockwise order. Each vertex is represented by 2 integers separated by a blank. Any

two vertices are also separated by a blank.


Output
For each test case, output the relative location of P with respect to each polygon by n numbers. The
i-th number is ‘0’ if P is on the boundary of it, is ‘1’ if P is inside, but not on the boundary, of it, and

is ‘2’ if it is outside and not on the boundary of it.


Sample Input
2
3 10 5
4 2 7 10 8 10 1 1 1
3 9 2 9 10 13 2
4 2 2 2 8 8 3 3 2
1 7 3
5 0 0 5 10 10 5 5 3 10 1
Sample Output
0 1 2

2


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <set>
#include <bits/stdc++.h>
#include <queue>
#include <stack>
#include <cmath>
#define LL long long
#define INF 0x3f3f3f3f
#define RR freopen("in.txt","r",stdin)
#define WW freopen("out.txt","w",stdout)

using namespace std;

const int maxn = 20000+10;
const double eps = 1e-8;
const double PI = acos(-1.0);
int sgn(double x)
{
    if(fabs(x) < eps)
        return 0;
    if(x < 0)
        return -1;
    else
        return 1;
}



struct Point
{
    double x,y;
    Point() {}
    Point(double _x,double _y)
    {
        x = _x;
        y = _y;
    }
    Point operator -(const Point &b)const
    {
        return Point(x - b.x,y - b.y);
    }
    double operator ^(const Point &b)const
    {
        return x * b.y - y*b.x;
    }
    double operator *(const Point &b)const
    {
        return x * b.x + y*b.y;
    }
    void transXY(double B)
    {
        double tx = x,ty = y;
        x = tx * cos(B) - ty * sin(B);
        y = tx * sin(B) + ty * cos(B);
    }

};

struct Line
{
    Point s,e;
    Line() {}
    Line(Point _s,Point _e)
    {
        s = _s,e = _e;
    }

    pair<int, Point>operator &(const Line &b)const
    {
        Point res = s;
        if(sgn((s-e)^(b.s-b.e)) == 0)
        {
            if(sgn((s-b.e)^(b.s-b.e)) == 0)
            {
                return make_pair(0,res);
            }
            else return make_pair(1,res);
        }
        double t = ((s-b.s)^(b.s-b.e)) / ((s-e)^(b.s-b.e));
        res.x += (e.x-s.x)*t;
        res.y += (e.y-s.y)*t;
        return make_pair(2,res);
    }
};

bool inter(Line l1,Line l2)
{
    return
        max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x) &&
        max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x) &&
        max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y) &&
        max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y) &&
        sgn((l2.s -l1.e)^(l1.s-l1.e)) * sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 &&
        sgn((l1.s-l2.e)^(l2.s-l2.e)) * sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0;

}

bool OnSeg(Point P,Line L)
{
    return sgn((L.s-P)^(L.e-P)) == 0 && sgn((P.x - L.s.x)*(P.x - L.e.x)) <= 0 && sgn( (P.y - L.s.y)*(P.y - L.e.y) ) <= 0;
}
int inPoly(Point p,Point poly[],int n)
{
    int cnt = 0;
    Line ray,side;
    ray.s = p;
    ray.e.y = p.y;
    ray.e.x = -100000000000.0;

    for(int i=0; i<n; i++)
    {
        side.s = poly[i];
        side.e = poly[(i+1)%n];
        if(OnSeg(p,side))
            return 0;
        if(sgn(side.s.y - side.e.y) == 0)
            continue;
        if(OnSeg(side.s,ray))
        {
            if(sgn(side.s.y - side.e.y) > 0)
                cnt++;
        }
        else if(OnSeg(side.e,ray))
        {
            if(sgn(side.e.y - side.s.y) > 0)
                cnt++;
        }
        else if(inter(ray,side))
            cnt++;
    }
    if(cnt % 2 == 1)
        return 1;
    else
        return 2;
}

Point poly[20],p;
int main()
{
    //RR;
    int n,T;
    scanf("%d",&T);
    while(T--)
    {
        cin>>n>>p.x>>p.y;
        int t;
        for(int i=0; i<n; i++)
        {
            scanf("%d",&t);
            for(int j=0; j<t; j++)
            {
                cin>>poly[j].x>>poly[j].y;
            }
            if(i)
                printf(" ");
            printf("%d",inPoly(p,poly,t));
        }
        printf("\n");
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值