未经过题目测试。。。。

struct polygon
{
    int n;
    Point p[maxp];
    Line l[maxp];

    void input(int nn)
    {
        n=nn;
        for(int i=0;i<n;i++)
            p[i].input();
    }

    void add(Point q)
    {
        p[n++]=q;
    }

    void getline(void)
    {
        for(int i=0;i<n;i++)
            l[i]=Line(p[i],p[(i+1)%n]);
    }

    struct cmp
    {
        Point p;
        cmp(const Point &p0) { p=p0;}
        bool operator()(const Point &aa,const Point &bb)
        {
            Point a=aa,b=bb;
            int d=sgn((a-p)^(b-p));
            if(d==0)
                return sgn(a.dis(p)-b.dis(p))<0;
            return d>0;
        }
    };

    //进行极角排序
    //首先需要找到最左下角的点
    //需要重载号好 Point 的 < 操作符 (min 函数要用)
    void norm(void)
    {
        Point mi=p[0];
        for(int i=1;i<n;i++) mi=min(mi,p[i]);
        sort(p,p+n,cmp(mi));
    }

    //得到凸包
    //得到的凸包里面的点编号是 0∼n-1 的
    //两种凸包的方法
    //注意如果有影响,要特判下所有点共点,或者共线的特殊情况
    void get_convex(polygon &convex)
    {
        sort(p,p+n);
        convex.n=n;
        for(int i=0;i<min(n,2);i++)
            convex.p[i]=p[i];
        if(convex.n==2&&(convex.p[0]==convex.p[1])) convex.n--;
        if(n<=2) return ;
        int &top=convex.n;
        top=1;
        for(int i=2;i<n;i++)
        {
            while(top&&sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i]))<=0)
                top--;
            convex.p[++top]=p[i];
        }
        int temp=top;
        convex.p[++top]=p[n-2];
        for(int i=n-3;i>=0;i--)
        {
            while(top!=temp&&sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i]))<=0)
                top--;
            convex.p[++top]=p[i];
        }
        if(convex.n==2&&(convex.p[0]==convex.p[1])) convex.n--;
        convex.norm();//原来得到的是顺时针的点,排序后逆时针

    }

    //得到凸包的另外一种方法
    void get_convex_graham(polygon &convex)
    {
        norm();
        int &top=convex.n;
        top=0;
        if(n==1)
        {
            top=1;
            convex.p[0]=p[0];
            return ;
        }
        if(n==2)
        {
            top=2;
            convex.p[0]=p[0];
            convex.p[1]=p[1];
            if(convex.p[0]==convex.p[1]) top--;
            return ;
        }

        convex.p[0]=p[0];
        convex.p[1]=p[1];
        top=2;
        for(int i=2;i<n;i++)
        {
            while(top>1&&sgn((convex.p[top-1]-convex.p[top-2])^(p[i]-convex.p[top-2]))<=0)
                top--;
            convex.p[top++]=p[i];
        }
        if(convex.n==2&&(convex.p[0]==convex.p[1])) convex.n--;
    }

    //判断是不是凸的
    bool is_convex(void)
    {
        bool s[8];
        memset(s,false,sizeof(s));
        for(int i=0;i<n;i++)
        {
            int j=(i+1)%n;
            int k=(j+1)%n;
            s[sgn((p[j]-p[i])^(p[k]-p[i]))+1]=true;
            if(s[0]&&s[2]) return false;
        }
        return true;
    }

    //判断点和任意多边形的关系
    // 3 点上
    // 2 边上
    // 1 内部
    // 0 外部
    int rel_of_point(Point q)
    {
        for(int i=0;i<n;i++)
            if(p[i]==q) return 3;
        getline();
        for(int i=0;i<n;i++)
            if(l[i].p_is_on_seg(q)) return 2;
        int cnt=0;
        for(int i=0;i<n;i++)
        {
            int j=(i+1)%n;
            int k=sgn((q-p[j])^(p[i]-p[j]));
            int u=sgn(p[i].y-q.y);
            int v=sgn(p[j].y-q.y);
            if(k>0&&u<0&&v>=0) cnt++;
            if(k<0&&v<0&&u>=0) cnt--;
        }
        return cnt!=0;
    }

    //直线 u 切割凸多边形左侧
    //注意直线方向
    void convex_cut_line(Line u,polygon &po)
    {
        int &top=po.n;
        top=0;
        for(int i=0;i<n;i++)
        {
            int d1=sgn((u.e-u.s)^(p[i]-u.s));
            int d2=sgn((u.e-u.s)^(p[(i+1)%n]-u.s));
            if(d1>=0) po.p[top++]=p[i];
            if(d1*d2<0) po.p[top++]=u.cross_point(Line(p[i],p[(i+1)%n]));
        }
    }

    //得到周长
    double get_cir(void)
    {
        double sum=0;
        for(int i=0;i<n;i++)
            sum+=p[i].dis(p[(i+1)%n]);
        return sum;
    }

    //得到面积
    double get_area(void)
    {
        double sum=0;
        for(int i=0;i<n;i++)
            sum+=(p[i]^p[(i+1)%n]);
        return abs(sum)/2;
    }

    //得到方向
    //1 逆时针
    //2顺时针
    bool get_dir(void)
    {
        double sum=0;
        for(int i=0;i<n;i++)
            sum+=(p[i]^p[(i+1)%n]);
        if(sgn(sum)>0) return 1;
        return 0;
    }

    //得到重心
    Point get_bary_centre(void)
    {
        Point ret(0,0);
        double area=0.0;
        for(int i=1;i<n-1;i++)
        {
            double tmp=(p[i]-p[0])^(p[i+1]-p[0]);
            if(sgn(tmp)==0) continue;
            area+=tmp;
            ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp;
            ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp;
        }
        if(sgn(area)) ret=ret/area;
        return ret;
    }

    //多边形和圆交的面积
    double area_circle(circle c)
    {
        double ans=0;
        for(int i=0;i<n;i++)
        {
            int j=(i+1)%n;
            if(sgn((p[j]-c.p)^(p[i]-c.p))>=0)
                ans+=c.area_triangle(p[i],p[j]);
            else ans-=c.area_triangle(p[i],p[j]);
        }
        return abs(ans);
    }

    //多边形和圆关系
    // 2 圆完全在多边形内
    // 1 圆在多边形里面,碰到了多边形边界
    // 0 其它
    int rel_of_circle(circle c)
    {
        getline();
        int x=2;
        if(rel_of_point(c.p)!=1) return 0;
        for(int i=0;i<n;i++)
        {
            if(c.rel_of_seg(l[i])==2) return 0;
            if(c.rel_of_seg(l[i])==1) x=1;
        }
        return x;
    }

};