计算几何模板 ①

Posted harry-bh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算几何模板 ①相关的知识,希望对你有一定的参考价值。

包含一些点与直线,线段的操作
凸包的构建与判断之类的操作

#include<cmath>
#include<cstring>
#include<vector>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const double eps=1e-6;
const double Pi=acos(-1.00);
inline int dcmp(double x)
{
    if(x>eps)return 1;
    return x<-eps?-1:0;
}
struct Vector
{
    double x,y;
    Vector(double X=0,double Y=0)
    {
        x=X,y=Y;
    }
    bool operator < (const Vector &b)const 
    {
        return dcmp(x-b.x)==0?y<b.y:x<b.x;
    }
    bool operator == (const Vector &b)const 
    {
        return dcmp(x-b.x)==0&&dcmp(y-b.y)==0;
    }
}p[5];
double dabs(Vector a)
{
    return sqrt(a.x*a.x+a.y*a.y);
}
typedef Vector Point;
Vector operator + (Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
Vector operator - (Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
Vector operator * (Vector a,double b){return Vector(a.x*b,a.y*b);}
Vector operator / (Vector a,double b){return Vector(a.x/b,a.y/b);}
struct Line
{
    Point s,e;
    Line(Point X=Vector(),Point Y=Vector())
    {
        s=X,e=Y;
    }
};
typedef Line Segment;
double dot(Vector a,Vector b)
{
    return a.x*b.x+a.y*b.y;
}
double cross(Vector a,Vector b)
{
    return a.x*b.y-a.y*b.x;
}
double dist(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

bool on_seg(Point a,Segment a1)
{
    Point b=a1.s,c=a1.e;
    return dcmp(cross(b-a,c-a))==0&&min(b.x,c.x)<=a.x&&a.x<=max(b.x,c.x)&&min(b.y,c.y)<=a.y&&a.y<=max(b.y,c.y);
}
Point get_cross(Point a,Point b,Point c,Point d)
{
    double t=cross(b-a,c-a)/(cross(b-a,c-a)+cross(d-a,b-a));
    return Point(c.x+(d.x-c.x)*t,c.y+(d.y-c.y)*t);
}
bool is_cross(Line a1,Line a2)
{
    Point a=a1.s,b=a1.e,c=a2.s,d=a2.e;
    int c1=dcmp(cross(b-a,c-a));
    int c2=dcmp(cross(b-a,d-a));
    int o1=dcmp(cross(d-c,b-c));
    int o2=dcmp(cross(d-c,a-c));
    if(c1*c2<=0&&o1*o2<=0)return true;
    if(c1==0&&on_seg(c,a1))return true;
    if(c2==0&&on_seg(d,a1))return true;
    if(o1==0&&on_seg(b,a2))return true;
    if(o2==0&&on_seg(a,a2))return true;
    return false;
}
Point get_nearest_point_on_segment(Point a,Line a1)
{
    Point b=a1.s,c=a1.e;
    double t=dot(a-b,c-b)/dot(c-b,c-b);
    if(dcmp(t)!=-1&&dcmp(1-t)!=-1)return Vector(b.x+(c.x-b.x)*t,b.y+(c.y-b.y)*t);
    if(dist(a,b)<dist(a,c))return b;
    return c;
}
bool is_cross_line(Line a1,Segment a2)
{
    Point a=a1.s,b=a1.e,c=a2.s,d=a2.e;
    int c1=dcmp(cross(b-a,c-a));
    int c2=dcmp(cross(b-a,d-a));
    if(c1*c2<=0)return true;
    return false;
}
struct Circle
{
    Point O;
    double R;
    Circle(Point o=Vector(),double r=0)
    {
        O=o,R=r;
    }
};
Point Base;
bool cmp_ang(const Point &a,const Point &b)
{
    int tmp=dcmp(cross(a-Base,b-Base));
    if(tmp==0)return dist(Base,a)<dist(Base,b);
    else return tmp>0;
}
void sort_point(Point *s,int L,int R,Point base)
{
    Base=base;
    sort(s+L,s+1+R,cmp_ang);
    return;
}
struct Polygon
{
    Point node[10025];
    Line edge[10025];
    int cnt;
    double C;
    double A;
    void build_edge()
    {
        for(int i=1;i<cnt;i++)edge[i]=Line(node[i],node[i+1]);
        edge[cnt]=Line(node[cnt],node[1]);
        return;
    }
    bool is_convex_hull()
    {
        bool s[3];
        memset(s,0,sizeof(s));
        for(int i=1;i<cnt-1;i++)
        {
            s[dcmp(cross(node[i+1]-node[i],node[i+2]-node[i]))+1]=true;
            if(s[0]&&s[2])return false;
        }
        s[dcmp(cross(node[cnt-1]-node[cnt-2],node[cnt]-node[cnt-2]))+1]=true;
        s[dcmp(cross(node[cnt]-node[cnt-1],node[1]-node[cnt-1]))+1]=true;
        s[dcmp(cross(node[1]-node[cnt],node[2]-node[cnt]))+1]=true;
        if(s[0]&&s[2])return false;
        return true;
    }
    int is_in_polygon(Point a)
    {
        Line ray;
        ray.s=a;
        ray.e=Vector(-100000000.0,a.y);
        int ans=0;
        for(int i=1;i<=cnt;i++)
        {
            Point s1=edge[i].s,s2=edge[i].e;
            if(on_seg(a,edge[i]))return 0;
            if(dcmp(s1.y-s2.y)==0)continue;
            if(on_seg(s1,ray))
            {
                if(dcmp(s1.y-s2.y)>0)ans++;
            }
            else if(on_seg(s2,ray))
            {
                if(dcmp(s2.y-s1.y)>0)ans++;
            }
            else if(is_cross(ray,edge[i]))ans++;
        }
        if(ans%2==1)return 1;
        return -1;
    }
    bool circle_is_in_polygon(Circle a)
    {
        if(is_in_polygon(a.O)<0)return false;
        for(int i=1;i<=cnt;i++)
        if(dcmp(dist(a.O,get_nearest_point_on_segment(a.O,edge[i]))+eps-a.R)<0)return false;
        return true;
    }
    void get_convex_hull(Point *s,int num)
    {
        if(num==0)
        {
            cnt=0;
            return;
        }
        if(num==1)
        {
            cnt=1;
            node[1]=s[1];
            return;
        }
        if(num==2)
        {
            cnt=2;
            node[2]=s[2];
            node[1]=s[1];
            return ;
        }
        for(int i=1;i<=num;i++) 
        if(s[i]<s[1])swap(s[1],s[i]);
        sort_point(s,2,num,s[1]);
        cnt=2;
        node[1]=s[1],node[2]=s[2];
        for(int i=3;i<=num;i++)
        {
            while(cnt>=2&&dcmp(cross(node[cnt]-node[cnt-1],s[i]-node[cnt-1]))<=0)cnt--;
            node[++cnt]=s[i];
        }
        return;
    }
    double get_Circumference()
    {
        C=0;
        for(int i=1;i<=cnt;i++)
        C+=dist(edge[i].s,edge[i].e);
        return C;
    }
    double get_Area()
    {
        A=0;
        for(int i=1;i<cnt;i++)A+=cross(node[i],node[i+1])/2;
        A+=cross(node[cnt],node[1])/2;
        return A;
    }   
};
bool is_cross_polygon(Polygon a,Polygon b)
{
    for(int i=1;i<=a.cnt;i++)
    for(int j=1;j<=b.cnt;j++)
    if(is_cross(a.edge[i],b.edge[j]))return true;
    return false;
}
int main()
{
    return 0;
}

以上是关于计算几何模板 ①的主要内容,如果未能解决你的问题,请参考以下文章

计算几何模板中的代码

计算光栅化片段的数量

计算几何 点积叉积 点类模板

计算几何模板

3维计算几何模板

计算几何模板