计算几何模板整理
基础知识:
二维的:
//2-D int my(double A){//处理应精度比大小不准确的问题 if(fabs(A)<eps)return 0; if(A<0)return -1; if(A>0)return 1; return 0; } struct Point{//点 double x,y; }point[N]; Point operator +(Point A,Point B){//加 return (Point){A.x+B.x,A.y+B.y}; } Point operator -(Point A,Point B){//减 return (Point){A.x-B.x,A.y-B.y}; } Point operator *(Point A,double B){//数乘 return (Point){A.x*B,A.y*B};//结果为向量 } double operator ^(Point A,Point B){//叉乘 return A.x*B.y-A.y*B.x;//结果为z轴向量(这里简化成标量了) } double operator *(Point A,Point B){//点乘 return A.x*B.x+A.y*B.y;//结果为标量 } double len(Point A,Point B){//两点间距离 double X=A.x-B.x; double Y=A.y-B.y; return sqrt(X*X+Y*Y); } struct Line{//线 int num[2];//起点终点 double theta;//斜率 double len(){//线的长度 double A=point[num[0]].x-point[num[1]].x; double B=point[num[0]].y-point[num[1]].y; return sqrt(A*A+B*B); } }line[N]; double len(Point X,Line Y){ double A=point[Y.num[1]].x-point[Y.num[0]].x; double B=point[Y.num[0]].y-point[Y.num[1]].y; double C1=point[Y.num[1]].y*point[Y.num[0]].x; double C2=point[Y.num[0]].y*point[Y.num[1]].x; double C=C1-C2; return fabs(A*X.y-B*X.x+C)/sqrt(A*A+B*B); } Point inter(Line A,Line B){//求交点 Point x=point[A.num[0]]-point[B.num[0]]; Point y=point[A.num[1]]-point[A.num[0]]; Point z=point[B.num[1]]-point[B.num[0]]; double k=(z^x)/(y^z); return point[A.num[0]]+y*k; } bool cmp(Line A,Line B){//按斜率排序 if(my(A.theta-B.theta)<0)return 1; if(my(A.theta-B.theta)>0)return 0;//斜率小的在前面 if(my(A.theta-B.theta)==0)return my((A.num[1]-A.num[0])^(B.num[1]-A.num[0]))>0; //斜率一样时将点靠外的优先排在前面 return 0; } bool judge(Line A,Line l1,Line l2){//判断A是否在l1l2之内 Point o=inter(l1,l2); return (my((point[A.num[1]]-point[A.num[0]])^(o-point[A.num[0]]))<0);//在l1l2之内返回1 }
三维的:
//3-D int my(double A){//处理应精度比大小不准确的问题 if(fabs(A)<eps)return 0; if(A<0)return -1; if(A>0)return 1; return 0; } struct Point{//点 double x,y,z; void shake(){//微小扰动(防止四点共面) double Rand=(rand()/RAND_MAX-0.5)*eps; x+=Rand;y+=Rand;z+=Rand; } double len(){//从原点到点的向量的长度 return sqrt(x*x+y*y+z*z); } }point[N]; Point operator +(Point A,Point B){//加 return (Point){A.x+B.x,A.y+B.y,A.z+B.z}; } Point operator -(Point A,Point B){//减 return (Point){A.x-B.x,A.y-B.y,A.z-B.z}; } Point operator ^(Point A,Point B){//叉乘-结果为向量 return (Point){A.y*B.z-A.z*B.y,A.z*B.x-A.x*B.z,A.x*B.y-A.y*B.x}; } double operator *(Point A,Point B){//点乘-结果为标量 return A.x*B.x+A.y*B.y+A.z*B.z; } struct Plane{//面 int num[3];//三点确定一个面,逆时针记录下三个点 Point legal(){//面的法向量 Point A=point[num[1]]-point[num[0]]; Point B=point[num[2]]-point[num[0]]; return A^B; } double S(){//面的面积 return legal().len()/2.0; } }plane[N]; double len(Point A,Plane B){//点到面的距离 Point legal=B.legal(); return legal*(A-point[B.num[0]])/legal.len(); } bool see(Point A,Plane B){//点到多面体的面可不可视 return my(B.legal()*(A-point[B.num[0]]))>=0; }
旋转卡壳:待补
半平面交:待补