计算几何模板整理

基础知识:

二维的:

//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 
}
2-D

三维的:

//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;
}
3-D

旋转卡壳:待补

半平面交:待补

posted @ 2020-02-06 17:12  passione  阅读(112)  评论(0编辑  收藏  举报