zoukankan      html  css  js  c++  java
  • 计算几何模板整理

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef double db;
    const db eps = 1e-10;  // 误差
    const db pi = acos(-1.0);  // 圆周率
    const ll inf = 0x3f3f3f3f3f3f3f3f;  // 无穷大
    const ll maxn = 1e5 + 10;
    
    // 精度三态函数
    inline int dcmp(db x) {
        if(fabs(x) < eps) return 0;
        return x > 0? 1: -1;
    }
    
    class Point {
    public:
        double x, y;
        Point(double x = 0, double y = 0) : x(x), y(y) {}  // 构造器
        // 输入
        void input() {
            scanf("%lf%lf", &x, &y);
        }
        // 一般用于排序
        bool operator<(const Point &a) const {
            return (!dcmp(x - a.x))? dcmp(y - a.y) < 0: x < a.x;
        }
        // 判断点的坐标是否相同
        bool operator==(const Point &a) const {
            return dcmp(x - a.x) == 0 && dcmp(y - a.y) == 0;
        }
        // 点到点的距离的平方
        db dis2(const Point a) {
            return pow(x - a.x, 2) + pow(y - a.y, 2);
        }
        // 点到点的距离
        db dis(const Point a) {
            return sqrt(dis2(a));
        }
    
        // 向量的模的平方
        db dis2() {
            return x * x + y * y;
        }
        // 向量的模
        db dis() {
            return sqrt(dis2());
        }
        // 向量加法
        Point operator+(const Point a) {
            return Point(x + a.x, y + a.y);
        }
        // 向量减法
        Point operator-(const Point a) {
            return Point(x - a.x, y - a.y);
        }
        // 向量数乘
        Point operator*(double p) {
            return Point(x * p, y * p);
        }
        // 向量数除
        Point operator/(double p) {
            return Point(x / p, y / p);
        }
        // 向量点积
        db dot(const Point a) {
            return x * a.x + y * a.y;
        }
        // 向量叉积
        db cross(const Point a) {
            return x * a.y - y * a.x;
        }
        // 向量与 a 向量的夹角
        db ang(Point a) {
            return acos((a.dis() * dis()) / dot(a));
        }
        // 向量在 b 向量上的投影
        db projection(Point b) {
            if(dcmp(dis()) == 0) return 0;
            if(dcmp(b.dis()) == 0) return dis();
            return cos(ang(b)) * dis();
        }
        // 向量逆时针旋转 rad 弧度
        Point Rotate(double rad) {
            return Point(x * cos(rad) - y * sin(rad), x * sin(rad) + y * cos(rad));
        }
    
    };
    typedef Point Vector;
    
    class Line {
    public:
        Point s, e;
        Line(Point s, Point e) : s(s), e(e) {}
        // 点 p 在有向线段 se 的左边返回 1, 右边返回 -1
        int toLeftTest(Point p) {
            if((e - s).cross(p - s) > 0) return 1;
            else if((e - s).cross(p - s) < 0) return -1;
            return 0;
        }
        // 直线与直线位置关系 0-重合 1-平行 2-相交
        int linecrossline (Line l) {
            if(dcmp((e - s).cross(l.e - l.s)) == 0) {
                if(dcmp((l.s - e).cross(l.e - s)) == 0) {
                    return 0;
                }
                return 1;
            }
            return 2;
        }
        // 直线与直线交点
        Point crosspoint(Line l) {
    		double a1 = (l.e - l.s).cross(s - l.s);
    		double a2 = (l.e - l.s).cross(e - l.s);
            double x = (s.x * a2 - e.x * a1) / (a2 - a1);
            double y = (s.y * a2 - e.y * a1) / (a2 - a1);
            if(dcmp(x) == 0) x = 0;
            if(dcmp(y) == 0) y = 0;
    		return Point(x, y);
    	}
    };
    
    // 凸包
    typedef vector<Point> Polygon;
    Polygon Andrew(vector<Point> p) {
        int n = p.size(), cnt = 0;
        Polygon ans(2 * n);
        sort(p.begin(), p.end());
        for (int i = 0; i < n; ++i) {
            while (cnt >= 2 && (ans[cnt - 1] - ans[cnt - 2]).cross(p[i] - ans[cnt - 2]) < eps) {
                --cnt;
            }
            ans[cnt++] = p[i];
        }
        int t = cnt + 1;
        for (int i = n - 1; i > 0; --i) {
            while (cnt >= t && (ans[cnt - 1] - ans[cnt - 2]).cross(p[i - 1] - ans[cnt - 2]) < eps) {
                --cnt;
            }
            ans[cnt++] = p[i - 1];
        }
        ans.resize(cnt - 1);
        return ans;
    }
    
    // 判断点在线段上
    bool OnSegment(Point p, Point a1, Point a2) {
        return dcmp((a1 - p).cross(a2 - p)) == 0 && dcmp((a1 - p).dot(a2 - p)) < 0;
    }
    
    // 判断线段相交
    bool Intersection(Point a1, Point a2, Point b1, Point b2) {
        double c1 = (a2 - a1).cross(b1 - a1), c2 = (a2 - a1).cross(b2 - a1),
                c3 = (b2 - b1).cross(a1 - b1), c4 = (b2 - b1).cross(a2 - b1);
        return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
    }
    
    // 判断点在凸包内
    int isPointInPolygon(Point p, vector<Point> s) {
        int wn = 0, cc = s.size();
        for (int i = 0; i < cc; i++) {
            Point p1 = s[i];
            Point p2 = s[(i + 1) % cc];
            if (p1 == p || p2 == p || OnSegment(p, p1, p2)) return -1;
            int k = dcmp((p2 - p1).cross(p - p1));
            int d1 = dcmp(p1.y - p.y);
            int d2 = dcmp(p2.y - p.y);
            if (k > 0 && d1 <= 0 && d2 > 0) wn++;
            if (k < 0 && d2 <= 0 && d1 > 0) wn--;
        }
        if (wn != 0) return 1;
        return 0;
    }
    
    // 凸包面积
    double PolygonArea(Polygon p) {
        double ans = 0;
        for(int i = 2; i < p.size() - 1; ++i) {
            ans += abs((p[i] - p[1]).cross(p[i + 1] - p[1]));
        }
        return ans * 0.5;
    }
    

    (更新中)

  • 相关阅读:
    数据库实验2
    jsp 配置MySQL服务器 以及数据的插入和读取
    利用JSP编程技术实现一个简单的购物车程序
    【servlet3.0新特性】Annotation注解配置
    用Servlet实现聊天室设计
    PHP fopen和fwrite函数实现创建html页面
    Django框架 之 view视图
    Django框架 之 URLconf
    Django框架 之 模板语言
    Django框架 之 ORM 常用字段和参数
  • 原文地址:https://www.cnblogs.com/wulitaotao/p/11478653.html
Copyright © 2011-2022 走看看