几何中点/线/多边形模板
----------
#include<vector> #include<list> #include<map> #include<set> #include<deque> #include<queue> #include<stack> #include<bitset> #include<algorithm> #include<functional> #include<numeric> #include<utility> #include<iostream> #include<sstream> #include<iomanip> #include<cstdio> #include<cmath> #include<cstdlib> #include<cctype> #include<string> #include<cstring> #include<cstdio> #include<cmath> #include<cstdlib> #include<ctime> #include<climits> #include<complex> #define mp make_pair #define pb push_back using namespace std; const double eps=1e-8;//精度 const double pi=acos(-1.0);//π const double inf=1e20;//无穷大 const int maxp=1111;//最大点数 /* 判断d是否在精度内等于0 */ int dblcmp(double d) { if (fabs(d)<eps)return 0; return d>eps?1:-1; } /* 求x的平方 */ 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 a)const { return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0; } //判断两点大小 bool operator<(point a)const { return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x; } //点到源点的距离/向量的长度 double len() { return hypot(x,y); } //点到源点距离的平方 double len2() { return x*x+y*y; } //两点间的距离 double distance(point p) { return hypot(x-p.x,y-p.y); } //向量加 point add(point p) { return point(x+p.x,y+p.y); } //向量减 point sub(point p) { return point(x-p.x,y-p.y); } //向量乘 point mul(double b) { return point(x*b,y*b); } //向量除 point div(double b) { return point(x/b,y/b); } //点乘 double dot(point p) { return x*p.x+y*p.y; } //叉乘 double det(point p) { return x*p.y-y*p.x; } //XXXXXXX double rad(point a,point b) { point p=*this; return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p)))); } //截取长度r point trunc(double r) { double l=len(); if (!dblcmp(l))return *this; r/=l; return point(x*r,y*r); } //左转90度 point rotleft() { return point(-y,x); } //右转90度 point rotright() { return point(y,-x); } //绕点p逆时针旋转angle角度 point rotate(point p,double angle) { point v=this->sub(p); double c=cos(angle),s=sin(angle); return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c); } }; /* 线段/直线 */ struct line { point a,b; line(){} line(point _a,point _b) { a=_a; b=_b; } //判断线段相等 bool operator==(line v) { return (a==v.a)&&(b==v.b); } //点p做倾斜角为angle的射线 line(point p,double angle) { a=p; if (dblcmp(angle-pi/2)==0) { b=a.add(point(0,1)); } else { b=a.add(point(1,tan(angle))); } } //直线一般式ax+by+c=0 line(double _a,double _b,double _c) { if (dblcmp(_a)==0) { a=point(0,-_c/_b); b=point(1,-_c/_b); } else if (dblcmp(_b)==0) { a=point(-_c/_a,0); b=point(-_c/_a,1); } else { a=point(0,-_c/_b); b=point(1,(-_c-_a)/_b); } } //读入一个线段 void input() { a.input(); b.input(); } //校准线段两点 void adjust() { if (b<a)swap(a,b); } //线段长度 double length() { return a.distance(b); } //直线倾斜角 0<=angle<180 double angle() { double k=atan2(b.y-a.y,b.x-a.x); if (dblcmp(k)<0)k+=pi; if (dblcmp(k-pi)==0)k-=pi; return k; } //点和线段关系 //1 在逆时针 //2 在顺时针 //3 平行 int relation(point p) { int c=dblcmp(p.sub(a).det(b.sub(a))); if (c<0)return 1; if (c>0)return 2; return 3; } //点是否在线段上 bool pointonseg(point p) { return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0; } //两线是否平行 bool parallel(line v) { return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0; } //线段和线段关系 //0 不相交 //1 非规范相交 //2 规范相交 int segcrossseg(line v) { int d1=dblcmp(b.sub(a).det(v.a.sub(a))); int d2=dblcmp(b.sub(a).det(v.b.sub(a))); int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a))); int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a))); if ((d1^d2)==-2&&(d3^d4)==-2)return 2; return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0|| d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0|| d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0|| d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0); } //线段和直线v关系 int linecrossseg(line v)//*this seg v line { int d1=dblcmp(b.sub(a).det(v.a.sub(a))); int d2=dblcmp(b.sub(a).det(v.b.sub(a))); if ((d1^d2)==-2)return 2; return (d1==0||d2==0); } //直线和直线关系 //0 平行 //1 重合 //2 相交 int linecrossline(line v) { if ((*this).parallel(v)) { return v.relation(a)==3; } return 2; } //求两线交点 point crosspoint(line v) { double a1=v.b.sub(v.a).det(a.sub(v.a)); double a2=v.b.sub(v.a).det(b.sub(v.a)); return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1)); } //点p到直线的距离 double dispointtoline(point p) { return fabs(p.sub(a).det(b.sub(a)))/length(); } //点p到线段的距离 double dispointtoseg(point p) { if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0) { return min(p.distance(a),p.distance(b)); } return dispointtoline(p); } //XXXXXXXX point lineprog(point p) { return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2())); } //点p关于直线的对称点 point symmetrypoint(point p) { point q=lineprog(p); return point(2*q.x-p.x,2*q.y-p.y); } }; /* 多边形 */ struct polygon { int n;//点个数 point p[maxp];//顶点 line l[maxp];//边 //读入一个多边形 void input(int n=4) { for (int i=0;i<n;i++) { p[i].input(); } } //添加一个点 void add(point q) { p[n++]=q; } //取得边 void getline() { for (int i=0;i<n;i++) { l[i]=line(p[i],p[(i+1)%n]); } } struct cmp { point p; cmp(const point &p0){p=p0;} bool operator()(const point &aa,const point &bb) { point a=aa,b=bb; int d=dblcmp(a.sub(p).det(b.sub(p))); if (d==0) { return dblcmp(a.distance(p)-b.distance(p))<0; } return d>0; } }; void norm() { point mi=p[0]; for (int i=1;i<n;i++)mi=min(mi,p[i]); sort(p,p+n,cmp(mi)); } //求凸包存入多边形convex void getconvex(polygon &convex) { int i,j,k; sort(p,p+n); convex.n=n; for (i=0;i<min(n,2);i++) { convex.p[i]=p[i]; } if (n<=2)return; int &top=convex.n; top=1; for (i=2;i<n;i++) { while (top&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0) top--; convex.p[++top]=p[i]; } int temp=top; convex.p[++top]=p[n-2]; for (i=n-3;i>=0;i--) { while (top!=temp&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0) top--; convex.p[++top]=p[i]; } } //判断是否凸多边形 bool isconvex() { bool s[3]; memset(s,0,sizeof(s)); int i,j,k; for (i=0;i<n;i++) { j=(i+1)%n; k=(j+1)%n; s[dblcmp(p[j].sub(p[i]).det(p[k].sub(p[i])))+1]=1; if (s[0]&&s[2])return 0; } return 1; } //点与多边形关系 //0 外部 //1 内部 //2 边上 //3 点上 int relationpoint(point q) { int i,j; for (i=0;i<n;i++) { if (p[i]==q)return 3; } getline(); for (i=0;i<n;i++) { if (l[i].pointonseg(q))return 2; } int cnt=0; for (i=0;i<n;i++) { j=(i+1)%n; int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j]))); int u=dblcmp(p[i].y-q.y); int v=dblcmp(p[j].y-q.y); if (k>0&&u<0&&v>=0)cnt++; if (k<0&&v<0&&u>=0)cnt--; } return cnt!=0; } //线段与多边形关系 //0 无任何交点 //1 在多边形内长度为正 //2 相交或与边平行 int relationline(line u) { int i,j,k=0; getline(); for (i=0;i<n;i++) { if (l[i].segcrossseg(u)==2)return 1; if (l[i].segcrossseg(u)==1)k=1; } if (!k)return 0; vector<point>vp; for (i=0;i<n;i++) { if (l[i].segcrossseg(u)) { if (l[i].parallel(u)) { vp.pb(u.a); vp.pb(u.b); vp.pb(l[i].a); vp.pb(l[i].b); continue; } vp.pb(l[i].crosspoint(u)); } } sort(vp.begin(),vp.end()); int sz=vp.size(); for (i=0;i<sz-1;i++) { point mid=vp[i].add(vp[i+1]).div(2); if (relationpoint(mid)==1)return 1; } return 2; } //直线u切割凸多边形左侧 //注意直线方向 void convexcut(line u,polygon &po) { int i,j,k; int &top=po.n; top=0; for (i=0;i<n;i++) { int d1=dblcmp(p[i].sub(u.a).det(u.b.sub(u.a))); int d2=dblcmp(p[(i+1)%n].sub(u.a).det(u.b.sub(u.a))); if (d1>=0)po.p[top++]=p[i]; if (d1*d2<0)po.p[top++]=u.crosspoint(line(p[i],p[(i+1)%n])); } } //取得周长 double getcircumference() { double sum=0; int i; for (i=0;i<n;i++) { sum+=p[i].distance(p[(i+1)%n]); } return sum; } //取得面积 double getarea() { double sum=0; int i; for (i=0;i<n;i++) { sum+=p[i].det(p[(i+1)%n]); } return fabs(sum)/2; } bool getdir()//1代表逆时针 0代表顺时针 { double sum=0; int i; for (i=0;i<n;i++) { sum+=p[i].det(p[(i+1)%n]); } if (dblcmp(sum)>0)return 1; return 0; } //取得重心 point getbarycentre() { point ret(0,0); double area=0; int i; for (i=1;i<n-1;i++) { double tmp=p[i].sub(p[0]).det(p[i+1].sub(p[0])); if (dblcmp(tmp)==0)continue; area+=tmp; ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp; ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp; } if (dblcmp(area))ret=ret.div(area); return ret; } //点在凸多边形内部的判定 int pointinpolygon(point q) { if (getdir())reverse(p,p+n); if (dblcmp(q.sub(p[0]).det(p[n-1].sub(p[0])))==0) { if (line(p[n-1],p[0]).pointonseg(q))return n-1; return -1; } int low=1,high=n-2,mid; while (low<=high) { mid=(low+high)>>1; if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>=0&&dblcmp(q.sub(p[0]).det(p[mid+1].sub(p[0])))<0) { polygon c; c.p[0]=p[mid]; c.p[1]=p[mid+1]; c.p[2]=p[0]; c.n=3; if (c.relationpoint(q))return mid; return -1; } if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>0) { low=mid+1; } else { high=mid-1; } } return -1; } };
----------