点到线段直线的距离, 直线与直线的关系 直线与线段的关系

//代码参考与kuangbin的模板

#include<bits/stdc++.h>
using namespace std;


const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int maxp = 1010;

int sgn(double x) { //判断
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    return 1;
}
//
inline double sqr(double x) {
    return x*x;
}
//
struct point {
    double x, y;
    point() {};
    //
    point(double _x, double _y) {
        x = _x;
        y = _y;
    }
    //
    void input() {
        scanf("%lf %lf", &x, &y);
    }
    void output() {
        printf("%.2f %.2f\n", x, y);
    }
    //
    bool operator == (point b) const {
        return sgn(x - b.x) && sgn(y - b.y) == 0;
    }
    //操作符重载
    bool operator < (point b) const {
        return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
    }
    //点积
    double operator *(const point &b)const {
        return x * b.x + y * b.y;
    }
    //叉积
    double operator ^(const point &b) const {
        return x*b.y - y * b.x;
    }
    //重载减号
    point operator -(const point &b) const {
        return point(x - b.x, y - b.y);
    }
    //重载加号
    point operator +(const point &b) const {
        return point(x + b.x, y + b.y);
    }
    //
    point operator *(const double k) const {
        return point(x * k, y * k);
    }
    //
    point operator /(const double k) const {
        return point(x / k, y / k);
    }

    //
    double distance(point b) {
        return hypot(x-b.x, y-b.y);
    }

    double len() {
        return hypot(x, y);
    }
    //
    double len2() {
        return x*x + y*y;
    }
};

struct line {
    point s, e;
    line() {};
    line(point _s, point _e) {
        s = _s;
        e = _e;
    }
    //
    bool operator == (line v) {
        return (s == v.s) && (e == v.e);
    }
    //根据一个点和倾斜角 angle 确定直线, 0 《= angle 《 pi
    line(point p, double angle) {
        s = p;
        if(sgn(angle - pi/2) == 0) {
            e = (s + point (0, 1));
        } else {
            e = (s + point(1, tan(angle)));
        }
    }
    //ax + by + c = 0
    line (double a, double b, double c) {
        if(sgn(a) == 0) {
            s = point(0, -c/b);
            e = point(1, -c/b);
        } else if(sgn(b) == 0) {
            s = point(-c/a, 0);
            e = point(-c/a, 1);
        } else {
            s = point(0, -c/b);
            e = point(1, (-c-a)/b);
        }
    }
    void input() {
        s.input();
        e.input();
    }
    void adjust() {
        if(e < s) swap(s,e);
    }
    //求线段长度
    double length() {
        return s.distance(e);
    }
    //返回线段倾斜角0《= angle 《=pi
    double angle() {
        double k = atan2(e.y - s.y, e.x - s.x);
        if(sgn(k) < 0 ) k += pi;
        if(sgn(k - pi) == 0) k -= pi;
        return k;
    }
    //点和直线的关系  1, 在左侧, 2.在右侧 3.在直线上
    int relation(point p) {
        int c = sgn((p-s)^(e-s));
        if(c < 0) return 1;
        if(c > 0) return 2;
        if(c == 0) return 3;
    }
    //点在线段上的判断
    bool point_on_seg(point p) {
        return sgn((p - s)^(e - s)) == 0 && sgn((p - s) * (p - e)) <= 0;
    }
    //两向量平行 (对应直线平行或者重合
    bool parallel(line v) {   //差集为0
        return sgn((e - s)^(v.e - v.s)) == 0;
    }
    //两线段相交的判断 0, 不相交 1.非规范相交  2.规范相交
    int seg_cross_seg(line v) {
        int d1 = sgn((e - s) ^ (v.s - s));
        int d2 = sgn((e - s) ^ (v.e - s));
        int d3 = sgn((v.e - v.s) ^ (s-v.s));
        int d4 = sgn((v.e - v.s) ^ (e-v.s));
        if((d1 ^ d2) == -2 &&(d3 ^ d4) == -2) return 2;
        return (d1 == 0 && sgn((v.s - s) * (v.s - e)) <= 0) ||
               (d2 == 0 && sgn((v.e - s) * (v.e - e)) <= 0) ||
               (d3 == 0 && sgn((s - v.s) * (s - v.e)) <= 0) ||
               (d4 == 0 && sgn((s - v.e) * (e - v.e)) <= 0);
    }
    //直线和线段判断相交  0。 不相交 1.非规范相交  2.规范相交
    int line_cross_seg(line v){
        int d1 = sgn((e-s)^(v.s-s));
        int d2 = sgn((e-s)^(v.e-s));
        if( (d1^d2) == -2) return 2;
        return (d1 == 0 || d2 == 0);
    }

    //两直线关系  0 平行 1 重合 2 相交
    int line_cross_line(line v){
          if((*this).parallel(v))
            return v.relation(s) == 3;
          return 2;
    }

    //求两条直线的焦点 前提应该保证两条直线不平行或者重合

    point cross_point(line v){
         double a1 = (v.e - v.s) ^ (s - v.s);
         double a2 = (v.e - v.s) ^ (e - v.s);
         return point((s.x*a2 - e.x*a1)/(a2-a1), (s.y*a2-e.y*a1) / (a2 - a1));
    }
    //点到直线的距离
    double dis_point_to_line(point p) {
        return fabs((p - s) ^ (e - s)) / length();
    }
    //点到线段的距离
    double dis_point_to_seg(point p) {
        if(sgn((p - s) * (e - s)) < 0 || ((p - e) * (s - e)) < 0)
            {
                return min(p.distance(s), p.distance(e));
            }
        return dis_point_to_line(p);
    }
    //返回线段到线段的距离,  前提两线段不相交 相交距离就是0了。
    double dis_seg_to_seg(line v){
        return min(min(dis_point_to_seg(v.s), dis_point_to_seg(v.e)), min(v.dis_point_to_seg(s), v.dis_point_to_seg(e)));
    }
    //返回点p在直线上的投影
    point line_prog(point p){
        return s + (((e-s)*((e-s)*(p-s)))/((e-s).len2()));
    }
    //返回点p在直线上的对称点
    point symmetry_point(point p){
      point q = line_prog(p);
      return point(2 * q.x - p.x, 2 * q.y - p.y);
    }

};


int main() {
   // freopen("in.txt", "r",stdin);
    point A,B,C,D;
    int n;
    scanf("%d", &n);
    A.input();
    double maxx = -1;
    double minn = 1e9;
    B.input();
    D = B;
    line x;
    maxx = max(maxx, A.distance(B));
    for(int i = 0; i < n - 1; i++) {
        C.input();
        maxx = max(maxx, A.distance(C));
        x.s = C;
        x.e = B;
        minn = min(minn, x.dis_point_to_seg(A));
        B = C;
    }
    x.s = C;
    x.e = D;
    minn = min(minn, x.dis_point_to_seg(A));
    printf("%.7f\n", (maxx * maxx - minn * minn) * pi);



}



相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页