计算几何模板

计算几何大模板

#include<map>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+100;
const double Pi=3.14159265358979323846,eps=1e-9;
struct Vector{
	double x,y;
	Vector(double xx=0,double yy=0){
		x=xx,y=yy;
	}
};
struct Point{
	double x,y;
	Point(double xx=0,double yy=0){
		x=xx,y=yy;
	}
};
struct Line{
	Point p;
	Vector v;
	double ang;
	Line(Point a=Point(),Vector b=Vector()){
		p=a,v=b;
		ang=atan2(v.y,v.x);
	}
}q[maxn];
int dcmp(double p){return fabs(p)<eps?0:p>0;}
Vector operator + (Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
Vector operator - (Vector a,Vector 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 * (double p,Vector a){return Vector(a.x*p,a.y*p);}
Vector operator / (Vector a,double p){return Vector(a.x/p,a.y/p);}
Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
Point operator + (Point a,Vector b){return Point(a.x+b.x,a.y+b.y);}
Point operator - (Point a,Vector b){return Point(a.x-b.x,a.y-b.y);}
bool operator ==  (Point a,Point b){return a.x==b.x&&a.y==b.y;} 
bool operator < (Point a,Point b){return a.x==b.x?a.y<b.y:a.x<b.x;}
double operator * (Vector a,Vector b){return a.x*b.y-a.y*b.x;}//叉积 b在a左为正 
double operator * (Point a,Point b){return a.x*b.y-a.y*b.x;}//面积计算用到 
bool operator < (Line a,Line b){return dcmp(a.ang-b.ang)==0?dcmp(a.v*(b.p-a.p))>0:(a.ang<b.ang);}
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}//点积 
double len(Vector a){return sqrt(dot(a,a));}//向量长 
double angle(Vector a,Vector b){return acos(dot(a,b)/len(a)/len(b));}//向量夹角 
Vector unit(Vector a){int l=len(a); return Vector(a.x/l,a.y/l);}//单位向量 
Vector rotate(Vector a,double p){return Vector(a.x*cos(p)-a.y*sin(p),a.x*sin(p)+a.y*cos(p));}//转 
Vector normal(Vector a){return rotate(unit(a),Pi/2);}//单位法向量 
double distl(Point p,Point a,Point b){Vector u=p-a,v=b-a; return fabs(u*v)/len(v);}//a到直线bc距离 
double dists(Point p,Point a,Point b){
	if(a==b) return len(a-p);
	Vector v1=b-a,v2=p-a,v3=p-b;
	if(dcmp(dot(v1,v2))<0) return len(v2);
	else if(dcmp(dot(v1,v3))>0) return len(v3);
	return fabs(v1*v2)/len(v1);
}//a到线段bc距离 
bool setment(Point a,Point b,Point c,Point d){
	Vector x=b-a,y=d-c;
	Vector v1=a-c,v2=b-c;
	if(dcmp(y*v1)==dcmp(y*v2)) return 0;
	v1=c-a,v2=d-a;
	if(dcmp(x*v1)==dcmp(x*v2)) return 0;
	return 1;
}//判断两线段是否相交(端点在两侧)
Point glt(Point a,Point b,Point c,Point d){
	Vector v1=b-a,v2=d-c,v3=a-c;
	double t=v2*v3/(v1*v2);
	return a+v1*t;
}//两直线交点 
Point glt(Line a,Line b){Vector v=a.p-b.p; return a.p+b.v*v/(a.v*b.v)*a.v;}//两直线交点 
bool onleft(Line l,Point b){return dcmp(l.v*(b-l.p))>0;}//点在向量左边
bool onright(Line a,Line b,Line t){Point p=glt(a,b); return dcmp(t.v*(p-t.p))<0;} //右边 
int pointin(Point p,Point *a,int n){
	int cnt=0;
	for(int i=1;i<=n;i++){
		if(dcmp(dists(p,a[i],a[i%n+1]))==0) return -1;
		int x=dcmp(a[i].y-p.y),y=dcmp(a[i%n+1].y-p.y);
		double z=(a[i%n+1]-a[i])*(p-a[i]);
		if(x<=0&&y>0&&z>0) cnt++;
		if(y<=0&&x>0&&z<0) cnt--;
	}
	if(cnt) return 1;
	return 0;
} //判断点在多边形内 
double S(Point *p,int n){
	p[n+1]=p[1];
	double ans=0;
	for(int i=1;i<=n;i++)
		ans+=p[i]*p[i+1];
	return fabs(ans)/2;
}//多边形面积 
Point cog(Point *p,int n){
	double x=0,y=0,m=0;
	for(int i=2;i<n;i++){
		double mq=(p[i]-p[1])*(p[i+1]-p[1]);
		x+=mq*(p[i].x+p[i%n+1].x+p[1].x)/3,y+=mq*(p[i].y+p[i%n+1].y+p[1].y)/3,m+=mq;
	}
	return Point(x/m,y/m);
} //重心 
double C(Point *p,int n){
	double ans=0;
	for(int i=1;i<n;i++)
		ans+=len(p[i+1]-p[i]);
	return ans+len(p[1]-p[n]);
}//周长 
void tb(Point *p,int n,Point *q,int &m){
	q[m=1]=p[1];
	if(n==1)
		return;
	sort(p+1,p+n+1);
	for(int i=1;i<=n;i++){
		while(m>1&&dcmp((q[m]-q[m-1])*(p[i]-q[m-1]))<=0)
			m--;
		q[++m]=p[i];
	} 
	int k=m;
	for(int i=n-1;i>1;i--){
		while(m>k&&dcmp((q[m]-q[m-1])*(p[i]-q[m-1]))<=0)
			m--;
		q[++m]=p[i];
	} 
} //凸包

void bpm(Line *b,int &n,Point *p){
	sort(b+1,b+n+1);
	int l=0,r=1,tot=0;
	for(int i=1;i<=n;i++){
		if(b[i].ang!=b[i-1].ang) tot++;
		b[tot]=b[i];
	}
	n=tot,q[0]=b[1],q[1]=b[2];
	for(int i=3;i<=n;i++){
		while(l<r&&onright(q[r],q[r-1],b[i])) r--;
		while(l<r&&onright(q[l],q[l+1],b[i])) l++;
		q[++r]=b[i];
	}
	while(l<r&&onright(q[r],q[r-1],q[l])) r--;
	while(l<r&&onright(q[l],q[l+1],q[r])) l++;
	n=0,q[r+1]=q[l];
	for(int i=l;i<=r;i++)
		p[++n]=glt(q[i],q[i+1]),b[n]=q[i];
}//离线求半平面交
void cut(Line a,Point *p,int &n){
	int cnt=0;
	Point tmp[maxn];
	for(int i=1;i<=n;i++){
		int x=dcmp(a.v*(p[i]-a.p));
		int y=dcmp(a.v*(p[i%n+1]-a.p));
		if(x<=0) tmp[++cnt]=p[i];
		if(x*y<0) tmp[++cnt]=glt(Line(p[i],p[i%n+1]-p[i]),a);
	}
	n=cnt;
	for(int i=1;i<=cnt;i++) p[i]=tmp[i];
}//半平面交加入一个半平面
double kake(Point *p,int n){
	if(n==1) return 0;
	if(n==2) return len(p[1]-p[2]);
	int now=1;
	double ans=0;
	p[n+1]=p[1]; 
	for(int i=1;i<=n;i++){
		while(dcmp(distl(p[now],p[i],p[i+1])-distl(p[now+1],p[i],p[i+1]))<=0)
			now=now%n+1;
		ans=max(ans,dot(p[now]-p[i],p[now]-p[i]));
		ans=max(ans,dot(p[now]-p[i+1],p[now]-p[i+1]));
	}
	return ans;
} //旋转卡壳 
double minl(Point *p,int n,Point *q,int m){
	int x=1,y=1;
	double ans=1e10;
	for(int i=1;i<=n;i++)
		x=p[x].y>p[i].y?i:x;
	for(int i=1;i<=m;i++)
		y=q[y].y<q[i].y?i:y;
	p[n+1]=p[1],q[m+1]=q[1];
	for(int i=1;i<=n;i++){
		int t;
		while((t=dcmp((p[x]-p[x+1])*(q[y+1]-q[y])))<0)
			y=(y+1)%m;
		if(t==0){
			ans=min(ans,dists(p[x],q[y],q[y+1]));
			ans=min(ans,dists(p[x+1],q[y],q[y+1]));
			ans=min(ans,dists(q[y],p[x],p[x+1]));
			ans=min(ans,dists(q[y+1],p[x],p[x+1]));
		}
		else
			ans=min(ans,dists(q[y],p[x],p[x+1]));
		x=(x+1)%n;
	}
	return ans;
}//求两凸壳间最近点对 
int main(){
	return 0; 
}
posted @ 2018-12-04 20:19  nianheng  阅读(163)  评论(0编辑  收藏  举报