zoukankan      html  css  js  c++  java
  • 计算几何基础

    参考文章 https://blog.csdn.net/clover_hxy/article/details/53966405

    预备知识

    先来个小数读入优化

    double read() {
        double x = 0, f = 1, y = 0.1; char ch = getchar();
        for (; !isdigit(ch)&&ch!='.'; ch=getchar()) if (ch=='-') f = -1;
        for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0';
        if (ch == '.') ch = getchar();
        for (; isdigit(ch); ch=getchar()) x += (ch - '0') * y, y *= 0.1;
        return x * f;
    }

    常用模板

    const double eps = 1e-8;
    const double Pi = acos(-1.0);
    
    struct Vector{
        double x,y;
        Vector() {}
        Vector(double a,double b) { x = a, y = b; }
    };
    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 p) { return Vector(a.x * p, a.y * p); }
    Vector operator / (Vector a,double p) { return Vector(a.x / p, a.y / p); }
    bool operator == (Point a,Point b) { return (a.x == b.x) && (a.y == b.y); }

    精度控制

    int dcmp(double x) {
        if (fabs(x) <= eps) return 0;
        return x > 0 ? x : -x;
    }

    向量

    向量模长

    double len(Vector a) {
        return sqrt(a.x * a.x + a.y * a.y);
    }

    点积

    double dot(Vector a, Vector b) {
        return a.x * b.x + a.y * b.y;
    }

    叉积

    叉积判断两向量的位置,将两向量共起点,设一号向量为A,另一个为B,若B可以由A逆时针旋转某个度数(大于等于0,小于等于180),那么Cross(A,B) > 0,否则小于0

    double cross(Vector a, Vector b) {
        return a.x * b.y - a.y * b.x;
    }

    向量之间的夹角

    double Angle(Vector a, Vector b) {
        return acos(dot(a,b)/len(a)/len(b));
    }

    旋转,p是旋转角度(逆时针),弧度制。

    Vector rotate(Vector a,double p) {
        return Vector(a.x * cos(p) - a.y * sin(p), a.x * sin(p) + a.y * cos(p));
    }

    法向量

    Vector normal(Vector a) {
        double L = len(a);
        return Vector(-a.y/L, a.x/L);
    }

    点与直线

    点到直线的距离

    double distl(Point p,Point a,Point b) {
        Vector v = p - a, u = b - a;
        return fabs(cross(v,u)) / len(u);
    }

    点到线段的距离

    double dists(Point p,Point a,Point b) {
        if (a==b) return len(p-a);
        Vector v1 = p - a, v2 = p - b, v3 = b - a;
        if (dcmp(dot(v1,v3)) < 0) return len(v1);
        else if (dcmp(dot(v2,a-b)) < 0) return len(v2);
        return fabs(cross(v2,v3))/len(v3);
    }

    判断直线是否相交

    bool xiangjiao(Point a,Point b,Point c,Point d) {
        double u1 = cross(b-a,c-a), u2 = cross(b-a,d-a);
        double v1 = cross(d-c,a-c), v2 = cross(d-c,b-c);
        return dcmp(u1 * u2) < 0 && dcmp(v1 * v2) < 0;
    }

    求两直线的交点

    Point jiaodian(Line a, Line b) {
        Point A = a.s, B = a.t, C = b.s, D = b.t;
        double t1 = cross(D - A, B - A), t2 = cross(B - A, C - A);
        double t = t1 / (t1 + t2);
        return C * t + D * (1 - t);
    }

    多边形

    判断点是否在多边形内

    int pointin(Point p,Point* a,int n) {
        int flag = 0;
        for (int i=1; i<=n; ++i) {
            Point s = a[i], t = a[i % n + 1];
            if (p == s || p == t) return -1; // 在点上 
            if ((s.y < p.y && t.y >= p.y) ||  (s.y >= p.y && t.y < p.y)) {
                int x = s.x + (p.y - s.y) * (t.x - s.x) / (t.y - s.y); // 射线与线段的交点的横坐标 
                if (x == p.x) return -1; // 在边上 
                if (x > p.x) flag ++; // 过这条边,且在p的右边 
            }
        }
        return flag & 1; 
    }

    求多边形的面积

    double Area(Point *a,int n) {
        double ans = 0;
        for (int i=2; i<n; ++i) 
            ans += cross(a[i]-a[1],a[i+1]-a[1]);
        return ans / 2.0;
    } 
  • 相关阅读:
    第七周java学习总结
    第六周java学习总结
    20175206迭代与JDB测试
    第五周java学习总结
    实验一 Java开发环境的熟悉(Linux + Eclipse)
    第四周java学习总结
    第三周java学习总结
    es6零基础学习之项目目录创建(一)
    软键盘影响页面布局之定位
    当input的框全部不为空时,提交按钮变色
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9526120.html
Copyright © 2011-2022 走看看