两个空间三角形相交关系的判断:
分别判断三角形trangle_1 的三条边与三角形trangle_2 的位置关系,三角形trangle_2 的三条边与三角形trangle_1 的位置关系。
--求解三角形trangle_1 的其中一条边的直线方程
--求解三角形trangle_2 所在平面的方程
--根据以上方程求得x,y,z
--判断点(x,y,z)是否在边(线段)上
--判断点(x,y,z)是否在三角形内部
--若都满足,则该边与三角形相交
--若存在三角形的一条边与另一个三角形相交,则两个三角形相交
--若三角形trangle_1 的三条边都不与三角形trangle_2 相交
且三角形trangle_2 的三条边都不与三角形trangle_1 相交
则两个三角形不相交
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
// 3D vector
class Vector3
{
public:
Vector3(float fx, float fy, float fz)
:x(fx), y(fy), z(fz)
{
}
// Subtract
Vector3 operator - (const Vector3& v) const
{
return Vector3(x - v.x, y - v.y, z - v.z) ;
}
// Dot product
float Dot(const Vector3& v) const
{
return x * v.x + y * v.y + z * v.z ;
}
// Cross product
Vector3 Cross(const Vector3& v) const
{
return Vector3(
y * v.z - z * v.y,
z * v.x - x * v.z,
x * v.y - y * v.x ) ;
}
public:
float x, y, z ;
};
bool JudgeIntersection(vector<vector<float>> triangle1, vector<vector<float>> triangle2);
bool EdgeAndTriangle(vector<vector<float>> triangle1, vector<vector<float>> triangle2, int i);
bool PointinTriangle(Vector3 A, Vector3 B, Vector3 C, Vector3 P);
bool JudgeParallel(vector<vector<float>> triangle1,vector<vector<float>> triangle2);
float PointFaceDistance(Vector3 point, vector<vector<float>> triangle);
int main(){
vector<vector<float>> triangle1,triangle2;
// 输入triangle1的顶点坐标: 3*3
triangle1.resize(3);
for(int i=0;i<3;i++)
triangle1[i].resize(3);
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
cin>>triangle1[i][j];
}
}
// 输入triangle2的顶点坐标: 3*3
triangle2.resize(3);
for(int i=0;i<3;i++)
triangle2[i].resize(3);
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
cin>>triangle2[i][j];
}
}
// 判断两个三角形是否相交
bool res1=JudgeIntersection(triangle1,triangle2);
if(res1==true){
cout<<"xiang jiao"<<endl;
}
else{
cout<<"bu xiang jiao"<<endl;
/**
若不相交,则判断是否平行。
平面间的平行关系判断:(利用法向量)
若法向量相等,则平行;否则不平行
若平行,计算距离:
1)取trangle1的一个顶点
2)计算点面距(利用点面距的计算公式)
**/
bool bb=JudgeParallel(triangle1,triangle2);
if(bb){
cout<<"ping xing"<<endl;
float d=PointFaceDistance(Vector3(triangle1[0][0],triangle1[0][1],triangle1[0][2]),triangle2);
cout<<d<<endl;
}
else{
cout<<"bu ping xing"<<endl;
}
}
return 1;
}
/**
两个空间三角形相交关系的判断:
分别判断三角形trangle_1 的三条边与三角形trangle_2 的位置关系,三角形trangle_2 的三条边与三角形trangle_1 的位置关系。
--求解三角形trangle_1 的其中一条边的直线方程
--求解三角形trangle_2 所在平面的方程
--根据以上方程求得x,y,z
--判断点(x,y,z)是否在边(线段)上
--判断点(x,y,z)是否在三角形内部
--若都满足,则该边与三角形相交
--若存在三角形的一条边与另一个三角形相交,则两个三角形相交
--若三角形trangle_1 的三条边都不与三角形trangle_2 相交
且三角形trangle_2 的三条边都不与三角形trangle_1 相交
则两个三角形不相交
**/
bool JudgeIntersection(vector<vector<float>> triangle1,vector<vector<float>> triangle2){
// 判断是否存在triangle2的一条边与triangle1相交
for(int i=0;i<3;i++){
bool res=EdgeAndTriangle(triangle1,triangle2,i);
// 若存在三角形的一条边与另一个三角形相交,则两个三角形相交
if(res==true){
return true;
}
}
// 判断是否存在triangle1的一条边与triangle2相交
for(int i=0;i<3;i++){
bool res=EdgeAndTriangle(triangle2,triangle1,i);
// 若存在三角形的一条边与另一个三角形相交,则两个三角形相交
if(res==true){
return true;
}
}
// 若三角形trangle1 的三条边都不与三角形trangle2 相交
// 且三角形trangle2 的三条边都不与三角形trangle1 相交
// 则两个三角形不相交
return false;
}
// 判断边与三角形是否相交
/**
1、计算三角形triangle2所在面的方程: 三点坐标(x1,y1,z1)、(x2,y2,z2)、(x3,y3,z3)
Ax+By+Cz+D=0
其中:
A=y1z2-y1z3-y2z1+y2z3+y3z1-y3z2
B=-x1z2+x1z3+x2z1-x2z3-x3z1+x3z2
C=x1y2-x1y3-x2y1+x2y3+x3y1-x3y2
D=-x1y2z3+x1y3z2+x2y1z3-x2y3z1-x3y1z2+x3y2z1
2、计算过这两个顶点(x4,y4,z4)和(x5,y5,z5)的直线方程
Px+Qy+R=0 && My+Nz+T=0
其中:
P=y5-y4
Q=-(x5-x4)
R=-((y5-y4)x4-(x5-x4)y4)
M=z5-z4
N=-(y5-y4)
T=-((z5-z4)y4-(y5-y4)z4)
(y2-y1)x-(x2-x1)y=(y2-y1)x1-(x2-x1)y1
(z2-z1)y-(y2-y1)z=(z2-z1)y1-(y2-y1)z1
3、计算交点坐标
y=(A*R/P+C*T/N-D)/(B-A*Q/P-C*M/N);
z=(-T-M*y)/N
x=(-R-Q*y)/P
4、判断交点坐标是否在线段(边)上、且在三角形内
**/
bool EdgeAndTriangle(vector<vector<float>> triangle1,vector<vector<float>> triangle2, int i){
//三角形triangle1的三个顶点
float x1=triangle1[0][0],
y1=triangle1[0][1],
z1=triangle1[0][2],
x2=triangle1[1][0],
y2=triangle1[1][1],
z2=triangle1[1][2],
x3=triangle1[2][0],
y3=triangle1[2][1],
z3=triangle1[2][2];
// 三角形triangle2的一条边的两个顶点
float x4=triangle2[i][0],
y4=triangle2[i][1],
z4=triangle2[i][2],
x5=triangle2[(i+1)%3][0],
y5=triangle2[(i+1)%3][1],
z5=triangle2[(i+1)%3][2];
// 计算交点坐标(x,y,z)
float A=y1*z2-y1*z3-y2*z1+y2*z3+y3*z1-y3*z2,
B=-x1*z2+x1*z3+x2*z1-x2*z3-x3*z1+x3*z2,
C=x1*y2-x1*y3-x2*y1+x2*y3+x3*y1-x3*y2,
D=-x1*y2*z3+x1*y3*z2+x2*y1*z3-x2*y3*z1-x3*y1*z2+x3*y2*z1,
P=y5-y4,
Q=-(x5-x4),
R=-((y5-y4)*x4-(x5-x4)*y4),
M=z5-z4,
N=-(y5-y4),
T=-((z5-z4)*y4-(y5-y4)*z4);
float y=(A*R/P+C*T/N-D)/(B-A*Q/P-C*M/N);
float z=(-T-M*y)/N;
float x=(-R-Q*y)/P;
// 判断(x,y,z)是否在线段上
bool b1;
if(x4>x5){
if(x<=x4&&x>=x5){
b1=true;
}
else{
b1=false;
}
}
else{
if(x<=x5&&x>=x4){
b1=true;
}
else{
b1=false;
}
}
// 判断点(x,y,z)是否在三角形内部
Vector3 v1=Vector3(x,y,z);
Vector3 v2=Vector3(x1,y1,z1);
Vector3 v3=Vector3(x2,y2,z2);
Vector3 v4=Vector3(x3,y3,z3);
bool b2=PointinTriangle(v2,v3,v4,v1);
// 若都满足,则该边与三角形相交
if(b1==true && b2==true){
return true;
}
return false;
}
// 判断点是否在三角形内部
bool PointinTriangle(Vector3 A, Vector3 B, Vector3 C, Vector3 P)
{
Vector3 v0 = C - A ;
Vector3 v1 = B - A ;
Vector3 v2 = P - A ;
float dot00 = v0.Dot(v0) ;
float dot01 = v0.Dot(v1) ;
float dot02 = v0.Dot(v2) ;
float dot11 = v1.Dot(v1) ;
float dot12 = v1.Dot(v2) ;
float inverDeno = 1 / (dot00 * dot11 - dot01 * dot01) ;
float u = (dot11 * dot02 - dot01 * dot12) * inverDeno ;
if (u < 0 || u > 1) // if u out of range, return directly
{
return false ;
}
float v = (dot00 * dot12 - dot01 * dot02) * inverDeno ;
if (v < 0 || v > 1) // if v out of range, return directly
{
return false ;
}
return u + v <= 1 ;
}
// 判断两个三角形是否平行
bool JudgeParallel(vector<vector<float>> triangle1,vector<vector<float>> triangle2){
Vector3 v1_1=Vector3(triangle1[0][0],triangle1[0][1],triangle1[0][2]);
Vector3 v1_2=Vector3(triangle1[1][0],triangle1[1][1],triangle1[1][2]);
Vector3 v1_3=Vector3(triangle1[2][0],triangle1[2][1],triangle1[2][2]);
Vector3 v2_1=Vector3(triangle2[0][0],triangle2[0][1],triangle2[0][2]);
Vector3 v2_2=Vector3(triangle2[1][0],triangle2[1][1],triangle2[1][2]);
Vector3 v2_3=Vector3(triangle2[2][0],triangle2[2][1],triangle2[2][2]);
Vector3 v3=v1_1-v1_2;
Vector3 v4=v1_1-v1_3;
Vector3 v5=v2_1-v2_2;
Vector3 v6=v2_1-v2_3;
Vector3 c1=v3.Cross(v4);
Vector3 c2=v5.Cross(v6);
if(c1.x*c2.y==c1.y*c2.x&&c1.y*c2.z==c1.z*c2.y){
return true;
}
else{
return false;
}
}
// 计算点面距离
float PointFaceDistance(Vector3 point, vector<vector<float>> triangle){
// 三角形的三个点
Vector3 v_1=Vector3(triangle[0][0],triangle[0][1],triangle[0][2]);
Vector3 v_2=Vector3(triangle[1][0],triangle[1][1],triangle[1][2]);
Vector3 v_3=Vector3(triangle[2][0],triangle[2][1],triangle[2][2]);
// 两个边的方向向量
Vector3 v1=v_1-v_2;
Vector3 v2=v_1-v_3;
// 面的法向量
Vector3 n=v1.Cross(v2);
//
Vector3 v3=point-v_1;
//
float n_d=sqrt(n.x*n.x+n.y*n.y+n.z*n.z);
//
float distance=fabs(v3.Dot(n)/n_d);
return distance;
}