计算几何 - 模板

1. 功能概要

计算几何模板实现了如下功能(将会不断更新)。

1.1 点/向量

  • ==比较
  • 排序比较
  • 向量减法、加法
  • 向量叉积
  • 向量点积
  • 向量长度

1.2 直线/线段

  • 通过 ax + by + c = 0 构建直线
  • 线段长度
  • 求两直线交点

2. 代码实现

// 计算几何模板
const double EPS = 1e-8;
const double PI = acos(-1.0);

// 浮点数符号判定
int sgn(double x) {
    if (fabs(x) < EPS)
        return 0;
    if (x < 0)
        return -1;
    return 1;
}

// 点/向量
struct Point {
    double x, y;

    Point() : x(0), y(0) {}

    Point(double _x, double _y) : x(_x), y(_y) {}

    // ==比较
    bool operator==(const Point &other) const {
        return sgn(x - other.x) == 0 && sgn(y - other.y) == 0;
    }

    // 排序比较
    bool operator<(const Point &other) const {
        return sgn(x - other.x) == 0 ? sgn(y - other.y) < 0 : x < other.x;
    }

    // 向量减法
    Point operator-(const Point &other) const {
        return {x - other.x, y - other.y};
    }

    // 向量加法
    Point operator+(const Point &other) const {
        return {x + other.x, y + other.y};
    }

    // 叉积
    double operator^(const Point &other) const {
        return x * other.y - y * other.x;
    }

    // 点积
    double operator*(const Point &other) const {
        return x * other.x + y * other.y;
    }

    // 向量长度
    double len() const {
        return hypot(x, y);
    }
};

typedef Point Vector;

// 直线/线段
struct Line {
    Point src, dest;

    Line() {}

    Line(const Point &_src, const Point &_dest) : src(_src), dest(_dest) {}

    // 通过 ax + by + c = 0 构建直线
    Line(double a, double b, double c) {
        if (sgn(a) == 0) {
            src = {0, -c / b};
            dest = {1, -c / b};
        } else if (sgn(b) == 0) {
            src = {-c / a, 0};
            src = {-c / a, 1};
        } else {
            src = {0, -c / b};
            dest = {1, (-c - a) / b};
        }
    }

    // 线段长度
    double len() const {
        return (dest - src).len();
    }

    // 求两直线交点
    // 注:要保证两直线不平行、不重合
    Point crossPoint(const Line& other) const {
        double a1 = (other.dest - other.src) ^ (src - other.src);
        double a2 = (other.dest - other.src) ^ (dest - other.src);
        return {
            (src.x * a2 - dest.x * a1) / (a2 - a1),
            (src.y * a2 - dest.y * a1) / (a2 - a1),
        };
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值