三维计算几何复习

三维计算几何

 

 声明:

由于本人较弱,并不能保证以下内容的100%正确

欢迎大佬来挑错

 

基本定义

 1 struct Point3{
 2     double x,y,z;
 3     Point3(){
 4         x=y=z=0.0;
 5     }
 6     Point3(double xx,double yy,double zz){
 7         x=xx;y=yy;z=zz;
 8     }
 9 };
10 typedef Point3 Vec3;
11 
12 Vec3 operator + (Vec3 v1,Vec3 v2){
13     return Vec3(v1.x+v2.x,v1.y+v2.y,v1.z+v2.z);
14 }
15 Vec3 operator - (Point3 p1,Point3 p2){
16     return Vec3(p1.x-p2.x,p1.y-p2.y,p1.z-p2.z);
17 }
18 Vec3 operator * (Vec3 v,double p){
19     return Vec3(v.x*p,v.y*p,v.z*p);
20 }
21 Vec3 operator / (Vec3 v,double p){
22     return Vec3(v.x/p,v.y/p,v.z/p);
23 }

 

半平面的表示

Dot(n,p-p0)=0
Ax+By+Cz+D>=0

 

三维点积

1 double Dt(Vec3 v1,Vec3 v2){
2     return v1.x*v2.x+v1.y*v2.y+v1.z*v2.z;
3 }
4 double Getlen(Vec3 v){
5     return sqrt(Dt(v,v));
6 }
7 double Getang(Vec3 v1,Vec3 v2){
8     return Dt(v1,v2)/Getlen(v1)/Getlen(v2);
9 }

 

应用:求夹角

求到平面的距离

求点在平面内的投影

1 double DistanceToPlane(Point3 p,Point3 p0,Vec3 n){
2     return Myabs(Dt(p-p0,n)/Getlen(n));
3 }
4 Point3 GetPlaneProjection(Point3 p,Point3 p0,Vec3 n){
5     return p-n*Dt(p-p0,n)/Getlen(n);
6 }

直线和平面的交点

注意判断分母为0

Point3 LinePlaneIntersection(Point3 p1,Point3 p2,Point3 p0,Vec3 n){
    Vec3 v=p2-p1;
    double t=Dt(n,p0-p1)/Dt(n,p2-p1);
    return p1+v*t;
}

 

 

 

三维叉积

 

 

1 Vec3 Crs(Vec3 v1,Vec3 v2){
2     return Vec3(v1.y*v2.z-v2.y*v1.z,v1.z*v2.x-v2.z*v1.x,v1.x*v2.y-v2.x*v1.y);
3 }
4 double GetS2(Point3 A,Point3 B,Point3 C){
5     return Getlen(Crs(B-A,C-A));
6 }

 

过不共线三点的平面的法向量

Crs(p2-p0,p1-p0)

三角形的有向面积????

求出叉积后取长度

判断点是否在三角形内

1 bool PointInTri(Poitn3 P,Point3 P0,Point3 P1,Point3 P2){
2     double S1=GetS2(P,P0,P1);
3     double S2=GetS2(P,P1,P2);
4     double S3=GetS2(P,P2,P0);
5     return dcmp(S1+S2+S2-GetS2(P0,P1,P2))==0;
6 }

判断线段与三角形相交

 

1 bool TriSegIntersection(Point3 P0,Point3 P1,Point3 P2,Point3 A,Point3 B){
2     Vec3 n=Crs(P1-P0,P2-P0);
3     if(dcmp(Dt(n,B-A))==0)return 0;
4     double t=Dt(n,P0-A)/Dt(n,B-A);
5     if(dcmp(t)<0||dcmp(t-1)>0)return 0;
6     Point3 P=A+(B-A)*t;
7     return PointInTri(P,P0,P1,P2);
8 }

 

点到直线线段的距离

 1 double DistanceToLine(Point3 P,Point3 A,Point3 B){
 2     Vec3 v1=B-A,v2=P-A;
 3     return Getlen(Crs(v1,v2))/Getlen(v1);
 4 }
 5 
 6 double DistanceToSegment(Point3 P,Point3 A,Point3 B){
 7     //(A!=B)
 8     Vec3 v1=B-A,v2=P-A,v3=P-B;
 9     if(dcmp(Dt(v1,v2))<0)return Getlen(v2);
10     else if(dcmp(Dt(v1,v3))>0)return Getlen(v3);
11     else return DistanceToLine(P,A,B);
12 }

 

四面体的体积

四面体的带符号体积

1 double Volume6(Point3 A,Point3 B,Point3 C,Point3 D){
2     return Dt(D-A,Crs(B-A,C-A));
3 }

计算有向面积时注意多边形的储存顺序

 

三维凸包

(我的模板是假的,注意四点共面的情况)

暴力法 O(n4)

枚举每三个点组成的有向三角形

判断是否所有点都在同侧

从而判断是否是凸包的一个面

判断在三角形的哪一侧需要一次叉积和一次点积(也可以理解为一次混合积)

posted @ 2018-04-26 17:26  ws_zzy  阅读(488)  评论(0编辑  收藏  举报