1. 程式人生 > >已知三維空間兩條直線,如何計算兩條直線距離最近的位置的中點

已知三維空間兩條直線,如何計算兩條直線距離最近的位置的中點

-------------------------------------------------------
--	2018-01-18   建立人:Ruo_Xiao
--	開發環境:Matlab 2010
--	郵箱:[email protected]
--------------------------------------------------------
--	2018-10-22  修改人:Ruo_Xiao
--	內容:修正計算P6的X的錯誤。
--------------------------------------------------------
--	2018-10-25  修改人:Ruo_Xiao
--	內容:
--	1、修改Matlab程式;
--	2、增加測試程式;
--	3、增加Cpp程式。
--------------------------------------------------------

假設:
這裡寫圖片描述P1和P2是直線L1上的兩個點,P3和P4是直線L2上的兩個點。

一、思路

1、由P1和P2計算出直線L1的方向向量D1和方程,P3和P4計算出直線L2的方向向量D2和方程。
2、由兩直線的方向向量計算法向量N。
3、N和P1可以確定平面Plane1,N和P3可以確定平面Plane2。
4、N和P1可以確定直線L3,L3和Plane2的交點為P5。
5、P5和D1可以確定直線方程L4,L4和L2的交點就是L1和L2兩條直線最短距離上的一個點P6。
6、N和P6可以算出法線L5。
7、L5和L1的交點就是就是L1和L2兩條直線最短距離上的一個點P7。
7、中點座標為P = (P6 + P7)/2。

二、計算公式

1、直線L1的方向向量D1:
這裡寫圖片描述
2、直線L2的方向向量D2:
這裡寫圖片描述
3、直線L1的方程:
這裡寫圖片描述
4、直線L2的方程:
這裡寫圖片描述
5、D1和D2的法向量N:
這裡寫圖片描述
6、平面Plane2的方程:
這裡寫圖片描述
7、直線L3的方程:
這裡寫圖片描述
8、L3和Plane2的交點P5:
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
9、P5和D1組成的直線方程L4:
這裡寫圖片描述
10、L4和L2的交點P6:
在這裡插入圖片描述
在這裡插入圖片描述
這裡寫圖片描述

12、法線N的方程:
這裡寫圖片描述
13、法線N和L1的交點P7:
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
14、中點座標:
這裡寫圖片描述

三、原始碼

function [CrossPt,P6,P7] = CalCrossPt(P11,P12,P21,P22)
x1 = P11(1); y1 = P11(2);z1 = P11(3);
x2 = P12(1); y2 = P12(2);z2 = P12(3);
x3 = P21(1); y3 = P21(2);z3 = P21(3);
x4 = P22(1); y4 = P22(2);z4 = P22(3);

a1 = x2 - x1;  b1 = y2 - y1;  c1 = z2 - z1;
a2 = x4 - x3;  b2 = y4 - y3;  c2 = z4 - z3;

a3 = b1*c2 - c1*b2;
b3 = c1*a2 - a1*c2;
c3 = a1*b2 - b1*a2;

x5 = (a3*x3 + b3^2/a3*x1 - b3*(y1-y3) + c3^2/a3*x1 - c3*(z1 - z3))/(a3 + b3^2/a3 + c3^2/a3);
y5 = b3/a3*(x5 - x1)+y1;
z5 = c3/a3*(x5 - x1)+z1;

x6 = (b1/a1*x5 - y5 - b2/a2*x3 + y3)/(b1/a1 - b2/a2);
y6 = b1/a1*(x6 - x5) + y5;
z6 = c1/a1*(x6 - x5) + z5;

x7 = (b3/a3*x6 - y6 - b1/a1*x1 + y1)/(b3/a3 - b1/a1);
y7 = b3/a3*(x7 - x6) + y6;
z7 = c3/a3*(x7 - x6) + z6;

P6 = [x6 , y6 , z6];
P7 = [x7 , y7 , z7];

CrossPt = [(x6+x7)/2 , (y6+y7)/2 , (z6+z7)/2];
end
clear;
clc;

% P11 = [-508.697 , 462.178 , -1203.02];
% P12 = [-507.968 , 614.376 , -1203.19];
% P21 = [-348.43 , 796.119 , -1258.63];
% P22 = [-158.094 , 793.653 , -1259.07];

P11 = [-42.4921 , 557.079 , -1421.21];
P12 = [-41.9771 , 546.407 , -1421.21];
P21 = [-177.645 , 238.873 , -1420.34];
P22 = [-344.014 , 238.244 , -1420.41];

 [CrossPt,P6,P7] = CalCrossPt(P11,P12,P21,P22)
 
 X1 = [P11(1),P12(1),P7(1)];
 Y1 = [P11(2),P12(2),P7(2)];
 Z1 = [P11(3),P12(3),P7(3)];

 X2 = [P21(1),P22(1),P6(1)];
 Y2 = [P21(2),P22(2),P6(2)];
 Z2 = [P21(3),P22(3),P6(3)];
 
 plot3(X1,Y1,Z1,'r');
 hold on;
 scatter3(X1,Y1,Z1,'r*');
 hold on;
 plot3(X2,Y2,Z2,'b');
 hold on;
 scatter3(X2,Y2,Z2,'b*');
 hold on;
 scatter3(CrossPt(1),CrossPt(2),CrossPt(3),'ko');
 
 xlabel('X');
 ylabel('Y');
 zlabel('Z');
void Cal3DCrossPt(array<array<double,3>,4> dData , array<double,3> &dR)
{
	double v1[3];
	double v2[3];
	for (size_t i=0;i<3;++i)
	{
		v1[i] = dData[1][i] - dData[0][i];
		v2[i] = dData[3][i] - dData[2][i];
	}
	double x1 = dData[0][0];
	double y1 = dData[0][1];
	double z1 = dData[0][2];

	double x3 = dData[2][0];
	double y3 = dData[2][1];
	double z3 = dData[2][2];

	double a1 = v1[0];
	double b1 = v1[1];
	double c1 = v1[2];

	double a2 = v2[0];
	double b2 = v2[1];
	double c2 = v2[2];

	double a3 = b1*c2 - b2*c1;
	double b3 = c1*a2 - c2*a1;
	double c3 = a1*b2 - a2*b1;

	if (fabs(a3)<=DBL_EPSILON)
	{
		a3 = 0.00001;
	}
	if (fabs(a1)<=DBL_EPSILON)
	{
		a1 = 0.00001;
	}

	if (fabs(a2)<=DBL_EPSILON)
	{
		a2 = 0.00001;
	}

	double x5h = a3*x3 + b3*b3*x1/a3 - b3*(y1 - y3) + c3*c3*x1/a3 - c3*(z1-z3);
	double x51 = a3 + b3*b3/a3 + c3*c3/a3;
	if (fabs(x51)<=DBL_EPSILON)
	{
		x51 = 0.00001;
	}
	double x5 = x5h/x51;

	double y5 = b3*(x5-x1)/a3+y1;
	double z5 = c3*(x5-x1)/a3+z1;

	double x6h = b1*x5/a1 - y5 - b2*x3/a2 + y3;
	double x61 = b1/a1 - b2/a2;
	if (fabs(x61)<=DBL_EPSILON)
	{
		x61 = 0.00001;
	}
	double x6 = x6h/x61;

	double y6 = b1*(x6 - x5)/a1 + y5;
	double z6 = c1*(x6 - x5)/a1 + z5;

	double x7h = b3*x6/a3 - y6 - b1*x1/a1 + y1;
	double x71 = b3/a3 - b1/a1;
	if (fabs(x71)<=DBL_EPSILON)
	{
		x71 = 0.00001;
	}
	double x7 = x7h / x71;

	double y7 = b3*(x7 - x6)/a3 + y6;
	double z7 = c3*(x7 - x6)/a3 + z6;

	double xn = (x6 + x7)/2;
	double yn = (y6 + y7)/2;
	double zn = (z6 + z7)/2;

	dR[0] = xn;
	dR[1] = yn;
	dR[2] = zn;
}

結果:
在這裡插入圖片描述
(SAW:Game Over!)