- db dis_pt_seg(const pt p, const pt s, const pt t)
 求点- p到线段- st的距离
- pt pt_projline(const pt p, const pt s, const pt t)
 求点- p到线段- st的垂足
- bool pt_on_seg(pt p, pt s, pt t)
 判断点- p是否在线段- st上(包括端点)
- bool parallel(line a, line b)
 判断直线- a和- b是否平行
- bool iscross_seg(pt a, pt b, pt c, pt d)
 判断线段- ab和线段- cd是否相交
- bool line_make_pt(line a, line b, pt &res)
 判断直线- a和- b是否有交点,有则保存在- res中
- line move_d(line a, const db &len)
 将直线- a沿法向量平移- len
namespace Line {
    struct line {
        pt a, b;
        line() {}
        line(pt x, pt y) : a(x), b(y) {}
        void input() {
            a.input(); b.input();
        }
    };
    db dis_pt_seg(const pt p, const pt s, const pt t) {
        if (cmp(dot(p - s, t - s)) < 0) return (p - s).norm();
        if (cmp(dot(p - t, s - t)) < 0) return (p - t).norm();
        return fabs(det(s - p, t - p) / dist(s, t));
    }
    pt pt_projline(const pt p, const pt s, const pt t) {
        db r = dot(t - s, p - s) / dot(t - s, t - s);
        return s + r * (t - s);
    }
    bool pt_on_seg(pt p, pt s, pt t) {
        return !cmp(det(p - s, t - s)) && cmp(dot(p - s, p - t)) <= 0;
    }
    bool parallel(line a, line b) {
        return !cmp(det(a.a - a.b, b.a - b.b));
    }
    bool iscross_seg(pt a, pt b, pt c, pt d) {
        return min(a.x, b.x) <= max(c.x, d.x) &&
            max(a.x, b.x) >= min(c.x, d.x) &&
            min(a.y, b.y) <= max(c.y, d.y) &&
            max(a.y, b.y) >= min(c.y, d.y) &&
            det(a - c, d - c) * det(d - c, b - c) >= 0 &&
            det(c - a, b - a) * det(b - a, d - a) >= 0;
    }
    bool line_make_pt(line a, line b, pt &res) {
        if (parallel(a, b)) return false;
        db s1 = det(a.a - b.a, b.b - b.a), s2 = det(a.b - b.a, b.b - b.a);
        res = (s1 * a.b - s2 * a.a) / (s1 - s2);
        return true;
    }
    line move_d(line a, const db &len) {
        pt d = a.b - a.a;
        d = d / d.norm();
        d = rotate_point(d, pi/2);
        return line(a.a + d * len, a.b + d * len);
    }
}