【原创】计算几何的基本模板

计算几何的模板

线不分直线和线段),以及求两点距离、已知两点求两点连线解析式(仅支持斜截式)、联立两条直线、求一点到直线距离最近点对功能。

存代码而已,别太当真。

v1.1版本更新: 2017-07-25 增加了最近点对算法,将函数移至主函数下方,修改了部分注释

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

const double INF=0x7fffffff;//坐标的边界(下界)
const int MAXN=1000;//点的数量

inline int Read()
{
    int p=0,f=1;
    char c=getchar();
    while(c<'0' or c>'9') 
    {
        if(c=='-') f=-1;
        c=getchar();
    }
    while(c>='0' and c<='9')
        p=p*10+c-'0',c=getchar();
    return p*f;
}

struct point
{
    double x,y;
    void ReadPoint()//读入一个点的横纵坐标
    {
        x=Read()*1.0,y=Read()*1.0;
    }
    void SavePoint(double xx,double yy)//保存一个点的横纵坐标
    {
        x=xx,y=yy;
    }
};

double length(point a,point b);//求两点间距离
double slope(point a,point b);//求两点连线的斜率
double intercept(double k,point a);//已知斜率和一个点,求截距

struct line
{
    double len,k,b,tr;//len线段长度 k斜率 b截距 tr如果垂直于x轴,它的值
    bool mk;//是否垂直于x轴
    point u,v;//两个端点
    void SaveLine(point zz,point wy)//已知两点求这两点连线的以上信息
    {
        u=zz,v=wy;
        if(zz.x==wy.x) mk=1,tr=zz.x;
        else 
        {
            mk=0; tr=0;
            len=length(zz,wy);
            k=slope(zz,wy);
            b=intercept(k,zz);
        }
    }
};

point ex(line p,line q);//联立两条直线,返回交点
double dist(point a,line b);//求一个点到直线的距离

/***********最近点对**************/
bool greater_x(point a,point b);
bool greater_y(int a,int b);
int crl[MAXN];//最近点对的辅助数组
double closest_pair(int l,int r);//最近点对的算法
double pairpair();//最近点对主程序
/***********最近点对*************/

point p[MAXN];//点集
int n;//点数
/************************/
int main()
{

}
/*******主程序在这!*******/
/***********************/


double length(point a,point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double slope(point a,point b)
{
    return (a.y-b.y)/(a.x-b.x);
}

double intercept(double k,point a)
{
    return a.y-k*a.x;
}

point ex(line p,line q)
{
    point h;
    if(p.k==q.k) h.x=-INF,h.y=-INF;//平行则无交点
    else if(p.mk==0) h.x=p.tr,h.y=q.k*h.x+q.b;//一条垂直于x轴,另一条不垂直
    else if(q.mk==0) h.x=q.tr,h.y=p.k*h.x+p.b;
    else h.x=(p.b-q.b)/(q.k-p.k),h.y=p.k*h.x+p.b;
    return h;
}

double dist(point a,line b)
{
    if(b.mk) return fabs(a.x-b.u.x);
    line c;
    c.k=-1/b.k;
    c.b=intercept(c.k,a);
    point p=ex(b,c);
    return length(a,p);
}

bool greater_x(point a,point b)
{
    return a.x<b.x;
}

bool greater_y(int a,int b)
{
    return p[a].y<p[b].y;
}

double closest_pair(int l,int r)
{
    if(l+1==r)
        return length(p[l],p[r]);
    else if(l+2==r)
        return min(min(length(p[l],p[l+1]),length(p[l+1],p[l+2])),
        length(p[l],p[l+2]));
    int mid=(l+r)>>1,cnt=0;
    double ans=min(closest_pair(l,mid),closest_pair(mid+1,r));
    for(int i=l;i<=r;i++)
        if(p[i].x>=p[mid].x-ans&&p[i].x<=p[mid].x+ans)
            crl[++cnt]=i;
    sort(crl+1,crl+1+cnt,greater_y);
    for(int i=1;i<=cnt;i++)  
        for(int j=i+1;j<=cnt;j++) 
        {
            if(p[crl[j]].y-p[crl[i]].y>=ans) break;  
            ans=min(ans,length(p[crl[i]],p[crl[j]])); 
        }   
    return ans;
}

double pairpair()
{
    sort(p+1,p+1+n,greater_x);
    return closest_pair(1,n);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值