点到线段直线的距离, 直线与直线的关系 直线与线段的关系
2016-03-24 18:29
567 查看
//代码参考与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); }
相关文章推荐
- 随机采样方法
- 1256画8
- 数组
- 教你读懂协方差
- psp
- 《世界是数字的》阅读笔记
- 随笔一感!
- [BZOJ1862][ZJOI2006]GameZ游戏排名系统(平衡树splay)
- JavaScript之基础-5 JavaScript 函数
- redis cluster管理工具redis-trib.rb详解
- 当婚纱摄影邂逅超级表格|流程监控
- Python3.5.1在win7安装numpy、scipy和theano的方法
- ASP.NET中的多线程整理
- 用开发平台快速开发中小企业信息平台
- [BZOJ 3112][ZJOI 2013]防守战线
- Swift实现断点续传,Demo简单易懂,没有太多复杂模块和逻辑,完整体现断点续传的原理
- 关于MySQL常用的一些函数以及一些计算
- JavaScript中对变量和函数声明的提前
- PostMessager来对子父窗体进行跨域
- Linux的并发套接字编程