模板 - 几何基础
2014-07-13 23:28
387 查看
部分函数已验证是正确的,还没有完全验证所有的函数有没有写正确
#include <bits/strc++.h> using namespace std; const double eps = 1e-10; int dcmp(double x){//等于0 0;大于0 1;小于0 -1 if(fabs(x)<eps) return 0; else return x<0 ? -1 : 1; } struct Point{ double x,y; Point(double x=0,double y=0):x(x),y(y) {} } typedef Point Vector; //向量的+-*/ Vector operator + (Vector A,Vector B){ return Vector(A.x+B.x,A.y+B.y);} Vector operator - (Point A,Point B){ return Vector(A.x-B.x,A.y-B.y);} Vector operator * (Vector A,double p){ return Vector(A.x*p,A.y*p);} Vector operator / (Vector A,double p){ return Vector(A.x/p,A.y/p);} //坐标的比较 bool operator < (const Point& a,const Point& b){ return (a.x<b.x || (a.x == b.x && a.y < b.y)); } bool operator == (const Point& a,const Point& b){ return (dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0); } //点积 double Dot(Vector A,Vector B){ return A.x*B.x + A.y*B.y; } //向量的长度 double Length(Vector A){ return sqrt(Dot(A,A));} //两个向量的夹角 double Angle(Vector A,Vector B){ return acos(Dot(A,B)/(Length(A)*Length(B))); } //叉积 double Cross(Vector A,Vector B){ return A.x*B.y - A.y*B.x; } //三点组成的三角形的有向面积的两倍 double Area2(Point A,Point B,Point C){return Cross(B-A,C-A);} //向量旋转 rad:弧度 Vector Rotate(Vector A,double rad){ return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad)); } //获得向量的单位法线(左转90度) Vector Normal(Vector A){ double L = Length(A); if(dcmp(L)==0) return Vector(0,0); retrun Vector(-A.y/L,A.x/L); } //得到两条直线的交点 //Point P=P0+tv 可表示在直线上的所有点 v=(B-A) 直线上的两点 //当表示为线段的时候0<=t<=1 //当表示成射线的时候t>0 //需要注意的是:两直线P+vt1,Q+wt2有唯一一个交点。Cross(v,w)!=0 Point GetLineIntersection(Point P,Vector v,Point Q ,Vector w){ Vector u = P-Q; double t = Cross(w,u) / Cross(v,w); return P+v*t; } //点到直线的距离 double DistanceToLine(Point P,Point A,Point B){ Vector ba = A-B, bc = C-B; return fabs(Cross(ba,bc)/Length(ba)); //不去绝对值的意思是有向距离 } //点到线段的距离 //情况一:点的投影在线段上-->点到直线的距离 //情况二:点的投影不在线段上-->点到离它比较近的端点 //用点积判断,用点积和叉积来计算 double DistanceToSegment(Point P,Point A,Point B){ if(A==B) return Length(P,A); Vector ab = B-A , ap = P-A , bp = P-B; if(dcmp(Dot(ab,ap))<0) return Length(ap); else if(dcmp(Dot(ab,bp))>0) return Length(bp); else return DistanceToLine(P,A,B); } //求点在直线上面的投影 Point GetLineProjectection(Point P ,Point A,Point B){ Vector v = B-A; return A+v*(Dot(v,P-A)/Dot(v,v)); } //判断线段是否相交(不包括端点) bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2){ double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1); double c3 = Cross(b2-b1,a1-b1), c4 = Cross(b2-b1,a2-b1); return (dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0); } //判断点是否在线段上(排除在端点上的情况) //保证p在向量a1a2的方向上 && p不在a1a2或者a2a1的延长线上 bool OnSegment(Point p,Point a1,Point a2){ return (dcmp(Cross(a1-p,a2-p))==0 && dcmp(Dos(a1-p,a2-p))<0); } //求凸包面积,p[]里面的点需要根据一定方向排序(顺时针或者逆时针) double ConvexPolygonArea(Point* p,int n){ double area=0; for(int i=0;i < n-1;i++){ area += Cross(p[i]-p[0],p[i+1]-p[0]); } return area; } //返回凸包的顶点个数,ch数组保存了凸包顶点 //输入的点不能有重复 //两个while循环的判定条件里面的<表示允许凸包的边上有点,<=表示凸包的边上不允许有点 //需要的话用dcmp()提高精度 int ConvexHull(Point* p,int n,Point* ch){ sort(p,p+n); int m=0; for(int i=0;i<n;i++){ while(m > 1 && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]) <=0) m--; ch[m++] = p[i]; } int k=m; for(int i=n-2;i>=0;i--){ while(m > k && Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2]) <=0) m--; ch[m++] = p[i]; } if(n > 1) m--; //去掉起始点 return m; }
相关文章推荐
- ACM计算几何模板——二维几何基础(基本运算,点和线,多边形)
- 【几何】-几何基础大模板(更新中)
- 计算几何基础与一般模板:POJ 3675&&ZOJ 1450&&POJ 1375
- 计算几何基础模板
- 基础几何基本概念and公式and模板
- 计算几何 || 二维基础模板
- 二维几何基础模板(三)
- 二维几何模板 - 二维几何基础
- 计算几何基础模板(不间断更新)
- 计算几何基础模板(2014.10.6一直沿用)
- 二维几何基础模板(一)
- 二维几何基础模板(二)
- 计算几何基础(模板)
- 几何模板总结(一):二维基础
- 二维几何基础(模板)
- 《训练指南》大白 二维几何基础 基本公式(模板)
- 计算几何基础模板 以后还会更新
- 计算几何 - 二维几何基础 (模板)
- 几何模板
- asp.net控件开发基础(16) --------服务器模板控件