最基础最重要的概念——叉积,说到叉积就要聊聊行列式。
行列式的代数意义与Cramer法则联系密切,先来个简单的例子,
消除x2得到这样的结果:
. 行列式
正是那个分母,其计算和叉积一样。
行列式的几何意义更加丰富,面积,体积……如上面的那个行列式就是向量为
的叉积。也就是他们构成的平面的有向面积。
推广到三阶就是在x,y,z轴向量方向上的有向体积。
故在三维空间中,向量
的叉积应该是(参照上图)。几何意义是对应平面的垂直向量,于是乎很多的问题得到了解决:
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
const double eps=1e-7;
struct point{
double x,y,z;
point(){}
point(double p1,double p2,double p3){
x=p1; y=p2; z=p3;
}
};
// 叉积
point xmulti(point p1,point p2){
return point(p1.y*p2.z-p1.z*p2.y,p1.z*p2.x-p1.x*p2.z,p1.x*p2.y-p1.y*p2.x);
}
// 点积
double dmulti(point p1,point p2){
return p1.x*p2.x+p1.y*p2.y+p1.z*p2.z;
}
// 向量之差
point sub(point p1,point p2){
return point(p1.x-p2.x,p1.y-p2.y,p1.z-p2.z);
}
// 向量长度
double len(point p){
return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
}
// 四点共面
bool Plane4(point p1,point p2,point p3,point p4){
point v=xmulti(sub(p2,p3),sub(p2,p4));
if(fabs(dmulti(sub(p1,p2),v))<eps) return 1;
return 0;
}
// 两直线平行
bool parallel(point p1,point p2,point q1,point q2){
point v1=sub(p1,p2);
point v2=sub(q1,q2);
if(len(xmulti(v1,v2))<eps) return 1;
return 0;
}
// 求解交点
point intersc(point p1,point p2,point p3,point p4){
point ans=p1; //面积比
double t=len(xmulti(sub(p1,p3),sub(p4,p3)))/len(xmulti(sub(p2,p1),sub(p4,p3)));
ans.x+=(p2.x-p1.x)*t;
ans.y+=(p2.y-p1.y)*t;
ans.z+=(p2.z-p1.z)*t;
return ans;
}
线与面:
// ----判断线面相交----
// 判断两点在平面同侧 点积等于0表示在平面上
bool same_side(point p1,point p2,point s1,point s2,point s3){
point v=xmulti(sub(s1,s2),sub(s2,s3)); //平面法向量
return dmulti(v,sub(s1,p1))*dmulti(v,sub(s1,p2))>eps;
}
// 判断线和平面平行
bool paral(point p1,point p2,point s1,point s2,point s3){
return dmulti(sub(p1,p2),xmulti(sub(s1,s2),sub(s2,s3)))<eps;
}
// 求线面交点
point Line_Plane(point p1,point p2,point s1,point s2,point s3){
point vec=xmulti(sub(s1,s2),sub(s2,s3));
double bi=dmulti(vec,sub(s1,p1))/dmulti(vec,sub(p2,p1)); //三菱锥体积之比
vec.x=p1.x+(p2.x-p1.x)*bi;
vec.y=p1.y+(p2.y-p1.y)*bi;
vec.z=p1.z+(p2.z-p1.z)*bi;
return vec;
}
面与面:
// 判断两平面是否平行
struct plane{
point s1,s2,s3;
plane(point p1,point p2,point p3):s1(p1),s2(p2),s3(p3){}
point getv(){
point v=xmulti(sub(s1,s2),sub(s2,s3));
return v;
}
};
//判断面面平行
bool Plane_paral(plane S1,plane S2){
point v1=S1.getv(),v2=S2.getv();
return len(xmulti(v1,v2))<eps;
}
// 判断两平面垂直
bool Plane_vert(plane S1,plane S2){
point v1=S1.getv(),v2=S2.getv();
return fabs(dmulti(v1,v2))<eps;
}
//面面相交的交点
struct line{
point p1,p2;
line():p1(),p2(){};
line(point _p1,point _p2):p1(_p1),p2(_p2){}
};
bool same_side(point p1,point p2,plane S){
point v=xmulti(sub(S.s1,S.s2),sub(S.s2,S.s3)); //平面法向量
return dmulti(v,sub(S.s1,p1))*dmulti(v,sub(S.s1,p2))>eps;
}
bool paral(point p1,point p2,plane S){
return dmulti(sub(p1,p2),xmulti(sub(S.s1,S.s2),sub(S.s2,S.s3)))<eps;
}
point Line_Plane(point p1,point p2,plane S){
point vec=xmulti(sub(S.s1,S.s2),sub(S.s2,S.s3));
double bi=dmulti(vec,sub(S.s1,p1))/dmulti(vec,sub(p2,p1)); //三菱锥体积之比
vec.x=p1.x+(p2.x-p1.x)*bi;
vec.y=p1.y+(p2.y-p1.y)*bi;
vec.z=p1.z+(p2.z-p1.z)*bi;
return vec;
}
line Plane_interc(plane S1,plane S2){
point p1,p2; //写得有些恶心
if(same_side(S1.s1,S1.s2,S2)
&& paral(S1.s1,S1.s2,S2))
p1=Line_Plane(S1.s2,S1.s3,S2);
else p1=Line_Plane(S1.s1,S1.s2,S2);
if(same_side(S1.s3,S1.s1,S2)
&& paral(S1.s3,S1.s1,S2))
p2=Line_Plane(S1.s2,S1.s3,S2);
else p2=Line_Plane(S1.s3,S1.s1,S2);
line res(p1,p2);
return res;
}
点到线:
设直线是P1P2,线外的一个点P3,求点到直线投影点
关键的两个向量是p3-p,p2-p1,他们满足(p3-p)(p2-p1)=0 (点积) (1)
设相关比例u,满足p=p1+(p2-p1)u (2)
将(2)带入(1)有:
那么P的坐标用(2)即可求出
至于距离,用面积解决。
// 距离方
double dis2(point p1,point p2){
return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z);
}
// 向量之差
point sub(point p1,point p2){
return point(p1.x-p2.x,p1.y-p2.y,p1.z-p2.z);
}
// 向量长度
double len(point p){
return sqrt(p.x*p.x+p.y*p.y+p.z*p.z);
}
// 投影点
point toLineP(point p,line L){
point V31=sub(p,L.p1);
point V21=sub(L.p2,L.p1);
double u=dmulti(V31,V21)/dis2(L.p1,L.p2);
point res(L.p1);
res.x+=(L.p2.x-L.p1.x)*u;
res.y+=(L.p2.y-L.p1.y)*u;
res.z+=(L.p2.z-L.p1.z)*u;
return res;
}
// 点到线的距离
double toLineDis(point p,line L){
return len(xmulti(sub(L.p1,p),sub(L.p1,L.p2)))/sqrt(dis2(L.p1,L.p2));
}
点到面的距离:
借助法向量可以发现,距离即是op'。op'的距离也即是
struct plane{
point s1,s2,s3;
plane(point p1,point p2,point p3):s1(p1),s2(p2),s3(p3){}
point getv(){
point v=xmulti(sub(s1,s2),sub(s2,s3));
return v;
}
};
double pToPlane(point p,plane S){
point v=xmulti(sub(S.s1,S.s2),sub(S.s2,S.s3));
return fabs(dmulti(v,sub(S.s1,p))/len(v));
}
-------------
先到这里。。。
在以后的时间里,还得继续查看它们有哪些错误。。