final-计算几何

这篇博客介绍了几何运算中的关键概念和操作,包括判断点是否为整数、点的比较、点的旋转、单位向量计算、点的极角排序以及直线的交点检测。此外,还提供了点集直径的计算方法,涉及到叉积、点积等几何运算,并给出了相应的实现代码。
摘要由CSDN通过智能技术生成

判断是否是整数:fabs(x – (int)x) > eps
double精度1e9,long double精度1e18
实数比较:
eps为精度,sign返回正负,cmp返回大小

typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){
    if (k>eps) return 1; else if (k<-eps) return -1; return 0;
}
int cmp(db k1,db k2){return sign(k1-k2);}

点:

struct point{
    db x,y;
    point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
    point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
    point operator * (db k1) const{return (point){x*k1,y*k1};}
    point operator / (db k1) const{return (point){x/k1,y/k1};}
    int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
    // 逆时针旋转
    point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
    point turn90(){return (point){-y,x};}
    bool operator < (const point k1) const{
        int a=cmp(x,k1.x);
        if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
    }
    db abs(){return sqrt(x*x+y*y);}
    db abs2(){return x*x+y*y;}
    db dis(point k1){return ((*this)-k1).abs();}
    //返回向量的单位向量
    point unit(){db w=abs(); return (point){x/w,y/w};}
    void scan(){double k1,k2; scanf("%lf%lf",&k1,&k2); x=k1; y=k2;}
    void print(){printf("%.11lf %.11lf\n",x,y);}
    //返回极角(弧度)
    db getw(){return atan2(y,x);}
    //返回原点对称点
    point getdel(){if (sign(x)==-1||(sign(x)==0&&sign(y)==-1)) return (*this)*(-1); else return (*this);}
    //返回半区
    int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)==-1);}
};

点积叉积:
这里默认起点是原点,非原点请平移

db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}

极角排序:
先分上下半区,然后用叉积判断大小。

旋转:
1、用旋转矩阵把点转换成旋转之后的点
[ c o s α − s i n α c o s α s i n α ] ⋅ [ x y ] \begin{bmatrix} cos\alpha&-sin\alpha\\ cos\alpha&sin\alpha\\ \end{bmatrix} · \begin{bmatrix} x\\ y\\ \end{bmatrix} [cosαcosαsinαsinα][xy]
2、用复数相乘,因为复数相乘的结果就是模相乘,辐角相加,所以乘上一个角度为α的单位向量就可以了
( x + y ⋅ i ) ⋅ ( c o s α + s i n α ⋅ i ) (x + y·i) · (cos\alpha + sin\alpha·i) (x+yi)(cosα+sinαi)
结果就是:

直线交点:
先判断是否平行再求交点

int checkLL(point k1,point k2,point k3,point k4){
    return cmp(cross(k3-k1,k4-k1),cross(k3-k2,k4-k2))!=0;
}
point getLL(point k1,point k2,point k3,point k4){
    db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3);
    return (k1*w2+k2*w1)/(w1+w2);
}

点集直径(最远点对):
有一个旋转卡壳的方法,不知道这个是不是
旋转卡壳:两条平行线卡住凸包,下一个卡住的点通过叉积判断,绕一圈就完事了

db convexDiameter(vector<point>A){
    int now=0,n=A.size(); db ans=0;
    for (int i=0;i<A.size();i++){
        now=max(now,i);
        while (1){
            db k1=A[i].dis(A[now%n]),k2=A[i].dis(A[(now+1)%n]);
            ans=max(ans,max(k1,k2)); if (k2>k1) now++; else break;
        }
    }
    return ans;
}

还有很多东西遇到再说吧

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值