zoukankan      html  css  js  c++  java
  • 几何模板

    #include <bits/stdc++.h>
    
    const double eps = 1e-8;
    
    inline int dcmp(double x) {
        return x < -eps ? -1 : x > eps;
    }
    
    struct Point;
    using Vector = Point;
    using Polygon = std::vector<Point>;
    
    struct Point {
        double x,y;
    
        Point() {}
    
        Point(double _x,double _y) : x(_x),y(_y) {}
    
        Point operator + (const Point &rhs) const {
            return Point(x + rhs.x,y + rhs.y);
        }
    
        Point operator - (const Point &rhs) const {
            return Point(x - rhs.x,y - rhs.y);
        }
    
        Point operator * (double t) const {
            return Point(x * t,y * t);
        }
    
        bool operator == (const Point &rhs) const {
            return dcmp(x - rhs.x) == 0 && dcmp(y - rhs.y) == 0;
        }
    
        double length() const {
            return hypot(x,y);
        }
    
        void read() {
            scanf("%lf%lf",&x,&y);
        }
    
        // *this 绕 o 逆时针旋转 angle 角度
        Point rotate(const Point &o,double angle) const {
            Point t = (*this) - o;
            double c = cos(angle),s = sin(angle);
            return Point(o.x + t.x * c - t.y * s,o.y + t.x * s + t.y * c);
        }
    
        // *this 向量的单位法向量(左转90度,长度归一化)
        Vector normal() const {
            double L = length();
            return Vector(-y / L,x / L);
        }
    
    };
    
    double det(const Point &a,const Point &b) {
        return a.x * b.y - a.y * b.x;
    }
    
    double dot(const Point &a,const Point &b) {
        return a.x * b.x + a.y * b.y;
    }
    
    // 用于极角排序的cmp函数
    bool polar_cmp(const Point &a,const Point &b) {
        if (dcmp(a.y) * dcmp(b.y) <= 0) {
            if (dcmp(a.y) > 0 || dcmp(b.y) > 0) return dcmp(a.y - b.y) < 0;
            if (dcmp(a.y) == 0 && dcmp(b.y) == 0) return dcmp(a.x - b.x) < 0;
        }
        return dcmp(det(a,b)) > 0;
    }
    
    // 直线与直线的交点
    Point intersection_line_line(Point p,Vector v,Point q,Vector w) {
        Vector u = p - q;
        double t = det(w,u) / det(v,w);
        return p + v * t;
    }
    
    // 点到直线距离
    double distance_point_line(Point p,Point a,Point b) {
        Vector v1 = b - a,v2 = p - a;
        return std::abs(det(v1,v2)) / v1.length();
    }
    
    // 点到线段距离
    double distance_point_segment(Point p,Point a,Point b) {
        if (a == b) return (p - a).length();
        Vector v1 = b - a,v2 = p - a,v3 = p - b;
        if (dcmp(dot(v1,v2)) < 0) return v2.length();
        else if (dcmp(dot(v1,v3)) > 0) return v3.length();
        else return std::abs(det(v1,v2)) / v1.length();
    }
    
    // 点在直线上的投影
    Point projection_point_line(Point p,Point a,Point b) {
        Vector v = b - a;
        return a + v * (dot(v,p - a) / dot(v,v));
    }
    
    // 线段规范相交判定
    bool intersection_proper_segment_segment(Point a1,Point a2,Point b1,Point b2) {
        double c1 = det(a2 - a1,b1 - a1),c2 = det(a2 - a1,b2 - a1),
               c3 = det(b2 - b1,a1 - b1),c4 = det(b2 - b1,a2 - b1);
        return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
    }
    
    // 点在线段上判定(端点也算)
    bool on_point_segment(Point p,Point a1,Point a2) {
        return dcmp(det(a1 - p,a2 - p)) == 0 && dcmp(dot(a1 - p,a2 -p)) <= 0;
    }
    
    // 线段相交判定(交在点上也算)
    bool intersection_segment_segment(Point a1,Point a2,Point b1,Point b2) {
        if (intersection_proper_segment_segment(a1,a2,b1,b2)) return true;
        return on_point_segment(a1,b1,b2) || on_point_segment(a2,b1,b2)
            || on_point_segment(b1,a1,a2) || on_point_segment(b2,a1,a2);
    }
    
    // 点在多边形内判定
    bool in_point_polygon(Point o,const Polygon &poly,bool flag) {
        // 传入flag表示在边界上算不算在里面
        int t = 0;
        Point a,b;
        int n = poly.size();
        for (int i = 0; i < n; ++ i) {
            if (on_point_segment(o,poly[i],poly[(i + 1) % n]))
                return flag;
        }
        for (int i = 0; i < n; ++ i) {
            a = poly[i];
            b = poly[(i + 1) % n];
            if (dcmp(a.y - b.y) > 0) std::swap(a,b);
            if (dcmp(det(a - o,b - o)) < 0 && 
                    dcmp(a.y - o.y) < 0 && dcmp(o.y - b.y) <= 0)
                ++ t;
        }
        return t & 1;
    }
    
    int main() {
    }
  • 相关阅读:
    最高级的自律是享受孤独
    【黑马】交换两个变量的值
    字符串换行
    互联网视频直播/点播流媒体服务器使用http和rtmp做点播时有什么区别?
    视频互联网直播/点播服务器中关于内容分发CDN的相关问题汇总
    网页直播系统推流端和拉流端都有哪些环节?
    线上课堂教育行业选择互动直播时有哪些直播方案?
    自建视频流媒体服务器需要满足哪些条件?
    互联网直播点播平台在进行iframe直播分享时如何禁止本地视频自动播放?
    视频直播/点播流媒体服务器是否可以对接RTSP视频流?
  • 原文地址:https://www.cnblogs.com/zyf0163/p/5672599.html
Copyright © 2011-2022 走看看