零散的封装计算几何板子

	struct Pos{  // 点 or 向量,排序到底用atan2还是叉积还是斜率看数据范围,默认叉积
		#define Vec Pos
		double x,y;
		Pos(){}
		Pos(double a,double b):x(a),y(b){}
		void Print(){ cerr<<fixed<<setprecision(2)<<x<<" "<<y<<"\n"; }
		friend Vec operator + (const Vec &a,const Vec &b)	{ return Vec(a.x+b.x,a.y+b.y); 	}
		friend Vec operator - (const Vec &a,const Vec &b)	{ return Vec(a.x-b.x,a.y-b.y); 	}
		friend Vec operator * (const double &b,const Vec &a){ return 	Vec(a.x*b,a.y*b); 	}
		friend double operator * (const Vec &a,const Vec &b){ return 	a.x*b.y-a.y*b.x; 	}
		friend double operator ^ (const Vec &a,const Vec &b){ return 	a.x*b.x+a.y*b.y;	}
		friend double operator / (const Vec &a,const Vec &b){ return 	(b.y-a.y)/(b.x-a.x);}
		friend double operator & (const Vec &a,const Vec &b){ return 	(b-a).Len(); 		}
		double Len()const{ return sqrt(x*x+y*y); }
		bool AboveX()const{
			static int d;
			d=dcmp(Vec(1,0)*(*this));
			if(!d)return dcmp((*this)*Vec(0,1))>0;
			return d>0;
		}
		friend bool operator < (const Vec &A,const Vec &B){
			static bool ab1,ab2;int d;
			ab1=A.AboveX(),ab2=B.AboveX();
			if(ab1!=ab2)return ab1;
			d=dcmp(A*B);
			if(!d)return dcmp(B.Len()-A.Len())>0;
			return d>0;
		}
	};
	
	struct Line{  // 直线
		Pos p;Vec e;
		Line(){}
		Line(Pos _p,Vec _e):p(_p),e(_e){}
		bool operator<(const Line &rhs){ return e<rhs.e; }
		friend Pos Itse(const Line &A,const Line &B){
			double t=((B.p-A.p)*B.e)/(A.e*B.e);
			return A.p+t*A.e;
		}
		friend bool OnRight(const Line &A,const Pos &B){ return dcmp(A.e*(B-A.p))<1; }
		static Line MidLine(const Pos &A,const Pos &B){
		Pos pm=0.5*(A+B);Vec pe=(pm-A);swap(pe.x,pe.y);pe.y=-pe.y;
		if(dcmp((B-A)*pe)<1)pe=-1*pe;
		return Line(pm,pe);
	}
	};
	struct Convex{  // 动态凸包,静态的比较简单就鸽了
		set<Pos>S;
		set<Pos>::iterator Next(set<Pos>::iterator it){ return next(it)==S.end() ? S.begin() : next(it); }
		set<Pos>::iterator Prev(set<Pos>::iterator it){ return it==S.begin() ? prev(S.end()) : prev(it); }
		bool In(Pos A){
			auto it = S.lower_bound(A);
			if(it==S.end())it=S.begin();
			int d=dcmp((A-*it)*(*Prev(it)-*it));
			if(!d)return dcmp((*Prev(it)-*it).Len()-(A-*it).Len())>-1;
			return d>0;
		}
		void Insert(Pos A){
			if(In(A))return;
			auto it = S.lower_bound(A);
			if(it==S.end())it=S.begin();
			S.insert(A);
			while(S.size()>3 && dcmp((*Next(it)-A)*(*it-A))>-1){ it=Next(it);S.erase(Prev(it)); }
			it=Prev(S.find(A));
			while(S.size()>3 && dcmp((A-*it)*(*it-*Prev(it)))>-1){ it=Prev(it);S.erase(Next(it)); }
		}
	};
	struct HalfPlane{ //半平面交
		vector<Line>L;Line q[maxn];Pos P[maxn];int l,r;double S;
		void Push(const Line &x){ L.push_back(x); }
		double Area(){ S=0;for(int i=l;i<r;++i)S+=P[i]*P[i+1]; S+=P[r]*P[l]; S/=2;return S;  }
		bool Sol(){
			sort(L.begin(),L.end());l=1,r=0;
			q[++r]=L.front();
			for(int i=1;i<L.size();++i){
				while(l<r && OnRight(L[i],P[r]))--r;
				while(l<r && OnRight(L[i],P[l+1]))++l;
				q[++r]=L[i];
				if(!dcmp(q[r].e*q[r-1].e)){
					if(OnRight(q[r],q[r-1].p) && dcmp(q[r].e^q[r-1].e)<0)return false;
					--r;
					if(!OnRight(q[r],L[i].p))q[r]=L[i];
				}
				if(l<r)P[r]=Itse(q[r],q[r-1]);
			}
			while(l<r && OnRight(q[l],P[r]))--r;
			if(r-l<=1)return false;
			P[l]=Itse(q[l],q[r]);
			return true;
		}
	};
posted @ 2023-01-06 21:28  Delov  阅读(37)  评论(0编辑  收藏  举报