• 计算几何


    超级全的计算几何全家桶~

    好久没写博客了= =

    正好刚听学长讲了计算几何,就收录下一些相关操作吧

    图形存储

    • 点:我们可以直接存储x,y坐标或x,y,z坐标

    • 向量:起点在原点的向量用x,y坐标或x,y,z坐标表示,任意一个向量可以用两个向量相减的形式表示

    struct node //或Vector
    {
        double x,y;
    };
    
    • 直线:用两个点或一个点和一个向量的形式
    struct line  //直线
    {
        node p,v;
    };
    
    • 多边形:按顺时针或逆时针把点存起来,相邻点有连线
    struct polygon  //多边形
    {
        int n;  //边数
        node p[N + 5];  //点
    };
    

    误差避免

    • 计算机存储浮点数会有些许误差,所以一般我们设一个很小的数(eps=10^{-6})来避免误差
    const double eps = 1e-6;
    int com(double a,double b)  //比较a和b的大小
    {
        double x = a - b;
        if (fabs(x) < eps)
            return 0;
        else
            if (x > 0)
                return 1;
            else
                return -1;
    }
    

    基础计算

    后面的(vec{a},vec{b})均为(vec{a}=(x_1,y_1),vec{b}=(x_2,y_2)),直线(l_1,l_2)均为(vec{p_1}+tvec{v_1},vec{p_2}+tvec{v_2})

    • 两点之间距离:(dist=sqrt{(x_1-x_2)^2+(y_1-y_2)^2})
    double dist(node a,node b)  //两点之间的距离
    {
        return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    }
    
    • 向量加、减、数乘、数除:x,y对应操作就行了
    node operator +(const node &a,const node &b)
    {
        return (node){a.x + b.x,a.y + b.y};
    }
    node operator -(const node &a,const node &b)
    {
        return (node){a.x - b.x,a.y - b.y};
    }
    node operator *(const node &a,const double &b)
    {
        return (node){a.x * b,a.y * b};
    }
    node operator /(const node &a,const double &b)
    {
        return (node){a.x / b,a.y / b};
    }
    
    • 点乘:(dot(vec{a},vec{b})=x_1cdot x_2+y_1cdot y_2=|vec{a}|cdot|vec{b}|cdot cosleft langlevec{a},vec{b} ight angle)
    double dot(node a,node b)   //点乘
    {
        return a.x * b.x + a.y * b.y;
    }
    
    • 模长:(|vec{a}|=sqrt{|dot(vec{a},vec{a})|})
    double molen(node a)  //模长
    {
        return sqrt(fabs(dot(a,a)));
    }
    
    • 叉积:(cross(vec{a},vec{b})=x_1cdot y_2-x_2cdot y_1=|vec{a}|cdot|vec{b}|cdot sinleft langlevec{a},vec{b} ight angle)
    double cross(node a,node b)  //叉积
    {
        return a.x * b.y - a.y * b.x;
    }
    
    • 向量旋转(alpha)弧度:(x'=xcosalpha-ysinalpha,y'=xsinalpha+ycosalpha)
    node rot(node x,double a)  //旋转
    {
        return (node){x.x * cos(a) - x.y * sin(a),x.x * sin(a) + x.y * cos(a)};
    }
    
    • 直线交点:由方程算出交点在任何一条直线上的(t),再算交点,设(vec{u}=vec{p_1}-vec{p_2},t_1=frac{cross(vec{v_1},vec{u})}{cross(vec{v_1},vec{v_2})}),交点即为(vec{p_1}+t_1vec{v_1})
    node linepoint(line a,line b)  //直线交点
    {
        node u = a.p - b.p;
        double t = cross(a.v,u) / cross(a.v,b.v);
        return a.p + a.v * t;
    }
    
    • 点到直线的距离:在直线任取两个点用等积法求高
    double pointlinedist(node a,line l)  //点到直线的距离
    {
        node x = l.p + l.v * 2.33,y = l.p + l.v * 6.66;
        return fabs(cross(a - x,y - x)) / molen(x - y);
    }
    
    • 点到线段的距离:要分两种情况讨论
    1. 过点的垂线不过线段:距离为点和线段端点的连线长度
    2. 过点的垂线过线段:距离就是垂线长度

    至于怎么判断:利用点乘的性质(夹角小于(90^circ)为正否则为负),设线段两端点为(A,B),线段外的点为(C),若(dot(vec{AC},vec{AB})<0)(dot(vec{AB},vec{BC})>0)(反向),则为情况1,否则为情况2

    double pointline_Seg(node c,node a,node b)  //点到线段的距离
    {
        node l1 = b - a,l2 = c - a,l3 = c - b;
        if (com(dot(l1,l2),0) < 0)
            return molen(l2);
        else
            if (com(dot(l1,l3),0) > 0)
                return molen(l3);
            else
                return fabs(cross(l1,l2)) / molen(l1);
    }
    
    • 多边形面积计算:将一个有(n)个边的划分成(n-2)个三角形,然后算面积(也就是叉积)的和,注意叉积不能取绝对值,要最后取绝对值,因为对于凹多边形会有多算的面积
    double polygon_S(polygon a)
    {
        double s = 0;
        for (int i = 1;i < a.n - 1;i++)
            s += cross(a.p[i + 1] - a.p[1],a.p[i + 2] - a.p[1]) / 2;
        return fabs(s);
    }
    

    先写这么多吧QAQ,有空以后补上

  • 相关阅读:
    2021年《jmeter高级调优项目实战》秋季班(火热报名中!)
    Jmeter分布式压力测试过程可能遇到的各种坑
    Python编程与数据结构
    Xftp 提示需要升级
    [学习笔记]LGV引理
    PyTorch模型训练特征图可视化
    测试PostGIS是否安装成功
    sift算法使用
    IDEA中Maven Projects里项目灰色解决办法
    SpringCloud从入门到进阶(一)——懂生活就懂微服务
  • 原文地址:https://www.cnblogs.com/sdlang/p/13068312.html
Copyright © 2020-2023  润新知