几何中点/线/多边形模板

来源:互联网 发布:sql 日志回滚 编辑:程序博客网 时间:2024/05/29 17:55


----------

#include<vector>#include<list>#include<map>#include<set>#include<deque>#include<queue>#include<stack>#include<bitset>#include<algorithm>#include<functional>#include<numeric>#include<utility>#include<iostream>#include<sstream>#include<iomanip>#include<cstdio>#include<cmath>#include<cstdlib>#include<cctype>#include<string>#include<cstring>#include<cstdio>#include<cmath>#include<cstdlib>#include<ctime>#include<climits>#include<complex>#define mp make_pair#define pb push_backusing namespace std;const double eps=1e-8;//精度const double pi=acos(-1.0);//πconst double inf=1e20;//无穷大const int maxp=1111;//最大点数/*    判断d是否在精度内等于0*/int dblcmp(double d){    if (fabs(d)<eps)return 0;    return d>eps?1:-1;}/*    求x的平方*/inline double sqr(double x){return x*x;}/*    点/向量*/struct point{    double x,y;    point(){}    point(double _x,double _y):x(_x),y(_y){};    //读入一个点    void input()    {        scanf("%lf%lf",&x,&y);    }    //输出一个点    void output()    {        printf("%.2f %.2f\n",x,y);    }    //判断两点是否相等    bool operator==(point a)const    {        return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0;    }    //判断两点大小    bool operator<(point a)const    {        return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x;    }    //点到源点的距离/向量的长度    double len()    {        return hypot(x,y);    }    //点到源点距离的平方    double len2()    {        return x*x+y*y;    }    //两点间的距离    double distance(point p)    {        return hypot(x-p.x,y-p.y);    }    //向量加    point add(point p)    {        return point(x+p.x,y+p.y);    }    //向量减    point sub(point p)    {        return point(x-p.x,y-p.y);    }    //向量乘    point mul(double b)    {        return point(x*b,y*b);    }    //向量除    point div(double b)    {        return point(x/b,y/b);    }    //点乘    double dot(point p)    {        return x*p.x+y*p.y;    }    //叉乘    double det(point p)    {        return x*p.y-y*p.x;    }    //XXXXXXX    double rad(point a,point b)    {        point p=*this;        return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));    }    //截取长度r    point trunc(double r)    {        double l=len();        if (!dblcmp(l))return *this;        r/=l;        return point(x*r,y*r);    }    //左转90度    point rotleft()    {        return point(-y,x);    }    //右转90度    point rotright()    {        return point(y,-x);    }    //绕点p逆时针旋转angle角度    point rotate(point p,double angle)    {        point v=this->sub(p);        double c=cos(angle),s=sin(angle);        return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);    }};/*    线段/直线*/struct line{    point a,b;    line(){}    line(point _a,point _b)    {        a=_a;        b=_b;    }    //判断线段相等    bool operator==(line v)    {        return (a==v.a)&&(b==v.b);    }    //点p做倾斜角为angle的射线    line(point p,double angle)    {        a=p;        if (dblcmp(angle-pi/2)==0)        {            b=a.add(point(0,1));        }        else        {            b=a.add(point(1,tan(angle)));        }    }    //直线一般式ax+by+c=0    line(double _a,double _b,double _c)    {        if (dblcmp(_a)==0)        {            a=point(0,-_c/_b);            b=point(1,-_c/_b);        }        else if (dblcmp(_b)==0)        {            a=point(-_c/_a,0);            b=point(-_c/_a,1);        }        else        {            a=point(0,-_c/_b);            b=point(1,(-_c-_a)/_b);        }    }    //读入一个线段    void input()    {        a.input();        b.input();    }    //校准线段两点    void adjust()    {        if (b<a)swap(a,b);    }    //线段长度    double length()    {        return a.distance(b);    }    //直线倾斜角 0<=angle<180    double angle()    {        double k=atan2(b.y-a.y,b.x-a.x);        if (dblcmp(k)<0)k+=pi;        if (dblcmp(k-pi)==0)k-=pi;        return k;    }    //点和线段关系    //1 在逆时针    //2 在顺时针    //3 平行    int relation(point p)    {        int c=dblcmp(p.sub(a).det(b.sub(a)));        if (c<0)return 1;        if (c>0)return 2;        return 3;    }    //点是否在线段上    bool pointonseg(point p)    {        return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0;    }    //两线是否平行    bool parallel(line v)    {        return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0;    }    //线段和线段关系    //0 不相交    //1 非规范相交    //2 规范相交    int segcrossseg(line v)    {        int d1=dblcmp(b.sub(a).det(v.a.sub(a)));        int d2=dblcmp(b.sub(a).det(v.b.sub(a)));        int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));        int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));        if ((d1^d2)==-2&&(d3^d4)==-2)return 2;        return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0||                d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0||                d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0||                d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0);    }    //线段和直线v关系    int linecrossseg(line v)//*this seg v line    {        int d1=dblcmp(b.sub(a).det(v.a.sub(a)));        int d2=dblcmp(b.sub(a).det(v.b.sub(a)));        if ((d1^d2)==-2)return 2;        return (d1==0||d2==0);    }    //直线和直线关系    //0 平行    //1 重合    //2 相交    int linecrossline(line v)    {        if ((*this).parallel(v))        {            return v.relation(a)==3;        }        return 2;    }    //求两线交点    point crosspoint(line v)    {        double a1=v.b.sub(v.a).det(a.sub(v.a));        double a2=v.b.sub(v.a).det(b.sub(v.a));        return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));    }    //点p到直线的距离    double dispointtoline(point p)    {        return fabs(p.sub(a).det(b.sub(a)))/length();    }    //点p到线段的距离    double dispointtoseg(point p)    {        if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0)        {            return min(p.distance(a),p.distance(b));        }        return dispointtoline(p);    }    //XXXXXXXX    point lineprog(point p)    {        return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));    }    //点p关于直线的对称点    point symmetrypoint(point p)    {        point q=lineprog(p);        return point(2*q.x-p.x,2*q.y-p.y);    }};/*    多边形*/struct polygon{    int n;//点个数    point p[maxp];//顶点    line l[maxp];//边    //读入一个多边形    void input(int n=4)    {        for (int i=0;i<n;i++)        {            p[i].input();        }    }    //添加一个点    void add(point q)    {        p[n++]=q;    }    //取得边    void getline()    {        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=dblcmp(a.sub(p).det(b.sub(p)));            if (d==0)            {                return dblcmp(a.distance(p)-b.distance(p))<0;            }            return d>0;        }    };    void norm()    {        point mi=p[0];        for (int i=1;i<n;i++)mi=min(mi,p[i]);        sort(p,p+n,cmp(mi));    }    //求凸包存入多边形convex    void getconvex(polygon &convex)    {        int i,j,k;        sort(p,p+n);        convex.n=n;        for (i=0;i<min(n,2);i++)        {            convex.p[i]=p[i];        }        if (n<=2)return;        int &top=convex.n;        top=1;        for (i=2;i<n;i++)        {            while (top&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0)                top--;            convex.p[++top]=p[i];        }        int temp=top;        convex.p[++top]=p[n-2];        for (i=n-3;i>=0;i--)        {            while (top!=temp&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0)                top--;            convex.p[++top]=p[i];        }    }    //判断是否凸多边形    bool isconvex()    {        bool s[3];        memset(s,0,sizeof(s));        int i,j,k;        for (i=0;i<n;i++)        {            j=(i+1)%n;            k=(j+1)%n;            s[dblcmp(p[j].sub(p[i]).det(p[k].sub(p[i])))+1]=1;            if (s[0]&&s[2])return 0;        }        return 1;    }    //点与多边形关系    //0 外部    //1 内部    //2 边上    //3 点上    int relationpoint(point q)    {        int i,j;        for (i=0;i<n;i++)        {            if (p[i]==q)return 3;        }        getline();        for (i=0;i<n;i++)        {            if (l[i].pointonseg(q))return 2;        }        int cnt=0;        for (i=0;i<n;i++)        {            j=(i+1)%n;            int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j])));            int u=dblcmp(p[i].y-q.y);            int v=dblcmp(p[j].y-q.y);            if (k>0&&u<0&&v>=0)cnt++;            if (k<0&&v<0&&u>=0)cnt--;        }        return cnt!=0;    }    //线段与多边形关系    //0 无任何交点    //1 在多边形内长度为正    //2 相交或与边平行    int relationline(line u)    {        int i,j,k=0;        getline();        for (i=0;i<n;i++)        {            if (l[i].segcrossseg(u)==2)return 1;            if (l[i].segcrossseg(u)==1)k=1;        }        if (!k)return 0;        vector<point>vp;        for (i=0;i<n;i++)        {            if (l[i].segcrossseg(u))            {                if (l[i].parallel(u))                {                    vp.pb(u.a);                    vp.pb(u.b);                    vp.pb(l[i].a);                    vp.pb(l[i].b);                    continue;                }                vp.pb(l[i].crosspoint(u));            }        }        sort(vp.begin(),vp.end());        int sz=vp.size();        for (i=0;i<sz-1;i++)        {            point mid=vp[i].add(vp[i+1]).div(2);            if (relationpoint(mid)==1)return 1;        }        return 2;    }    //直线u切割凸多边形左侧    //注意直线方向    void convexcut(line u,polygon &po)    {        int i,j,k;        int &top=po.n;        top=0;        for (i=0;i<n;i++)        {            int d1=dblcmp(p[i].sub(u.a).det(u.b.sub(u.a)));            int d2=dblcmp(p[(i+1)%n].sub(u.a).det(u.b.sub(u.a)));            if (d1>=0)po.p[top++]=p[i];            if (d1*d2<0)po.p[top++]=u.crosspoint(line(p[i],p[(i+1)%n]));        }    }    //取得周长    double getcircumference()    {        double sum=0;        int i;        for (i=0;i<n;i++)        {            sum+=p[i].distance(p[(i+1)%n]);        }        return sum;    }    //取得面积    double getarea()    {        double sum=0;        int i;        for (i=0;i<n;i++)        {            sum+=p[i].det(p[(i+1)%n]);        }        return fabs(sum)/2;    }    bool getdir()//1代表逆时针 0代表顺时针    {        double sum=0;        int i;        for (i=0;i<n;i++)        {            sum+=p[i].det(p[(i+1)%n]);        }        if (dblcmp(sum)>0)return 1;        return 0;    }    //取得重心    point getbarycentre()    {        point ret(0,0);        double area=0;        int i;        for (i=1;i<n-1;i++)        {            double tmp=p[i].sub(p[0]).det(p[i+1].sub(p[0]));            if (dblcmp(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 (dblcmp(area))ret=ret.div(area);        return ret;    }    //点在凸多边形内部的判定    int pointinpolygon(point q)    {        if (getdir())reverse(p,p+n);        if (dblcmp(q.sub(p[0]).det(p[n-1].sub(p[0])))==0)        {            if (line(p[n-1],p[0]).pointonseg(q))return n-1;            return -1;        }        int low=1,high=n-2,mid;        while (low<=high)        {            mid=(low+high)>>1;            if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>=0&&dblcmp(q.sub(p[0]).det(p[mid+1].sub(p[0])))<0)            {                polygon c;                c.p[0]=p[mid];                c.p[1]=p[mid+1];                c.p[2]=p[0];                c.n=3;                if (c.relationpoint(q))return mid;                return -1;            }            if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>0)            {                low=mid+1;            }            else            {                high=mid-1;            }        }        return -1;    }};


----------



原创粉丝点击