已知空间中有直线lineA和直线lineB,求两直线间最近的两点和距离。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class TwoLineMinDis : MonoBehaviour
{[SerializeField]private Vector3[] _lineA = new Vector3[2];[SerializeField]private Vector3[] _lineB = new Vector3[2];void Update(){#region 推算过程/** 假设_lineA上垂足点为 Pa,距离起点的距离为X,Pa=_lineA[0]+dirA*X;* 假设_lineB上垂足点为 Pb,距离起点的距离为Y,Pb=_lineB[0]+dirB*Y;* 则垂足向量为dirAB,dirAB=Pb-Pa, dirAB=_lineB[0]+dirB*Y-_lineA[0]-dirA*X;* 垂足向量dirAB垂直于_lineA和_lineB* dirAB.dirA=0 dirAB.dirB=0* (_lineB[0]+dirB*Y-_lineA[0]-dirA*X).dirA=0* (_lineB[0]+dirB*Y-_lineA[0]-dirA*X).dirB=0* _lineB[0].dirA+dirB.dirA*Y-lineA[0].dirA-dirA.dirA*X=0* _lineB[0].dirB+dirB.dirB*Y-lineA[0].dirB-dirA.dirB*X=0* X=(_lineB[0].dirA+dirB.dirA*Y-lineA[0].dirA)/dirA.dirA* Y=(_lineA[0].dirB+dirA.dirB*X-_lineB[0].dirB)/dirB.dirB;* * _lineA和_lineB存在三种情况 1.空间垂直 2.空间平行 3.空间不平行也不垂直* 1.空间垂直 则dirA.dirB=0* _lineB[0].dirA+dirB.dirA*Y-lineA[0].dirA-dirA.dirA*X=0* _lineB[0].dirB+dirB.dirB*Y-lineA[0].dirB-dirA.dirB*X=0* _lineB[0].dirA-lineA[0].dirA-dirA.dirA*X=0* _lineB[0].dirB+dirB.dirB*Y-lineA[0].dirB=0* X=(_lineB[0].dirA-_lineA[0].dirA)/dirA.dirA* Y=(_lineA[0].dirB-_lineB[0].dirB)/dirB.dirB;* 2.空间平行 则dirA.dirB=1* 取_lineA的起点为垂足,则X=0 * _lineB[0].dirB+dirB.dirB*Y-lineA[0].dirB=0* Y=(_lineA[0].dirA-_lineB[0].dirA)/dirB.dirA* Y=(_lineA[0].dirB-_lineB[0].dirB)/dirB.dirB* * 3.空间不平行也不垂直* _lineB[0].dirA+dirB.dirA*Y-lineA[0].dirA-dirA.dirA*X=0* _lineB[0].dirB+dirB.dirB*Y-lineA[0].dirB-dirA.dirB*X=0* X=(_lineB[0].dirA+dirB.dirA*Y-lineA[0].dirA)/dirA.dirA* Y=(_lineA[0].dirB+dirA.dirB*X-_lineB[0].dirB)/dirB.dirB;* * dirB.dirB(_lineA[0].dirA - _lineB[0].dirA) + dirA.dirB(_lineB[0].dirB-_lineA[0].dirB)* X= ———————————————————————————————————————————* dirA.dirB * dirA.dirB - dirA.dirA * dirB.dirB* dirA.dirA(_lineA[0].dirB - _lineB[0].dirB) + dirA.dirB(_lineB[0].dirA-_lineA[0].dirA)* Y= ———————————————————————————————————————————* dirA.dirA * dirB.dirB - dirA.dirB * dirA.dirB*/#endregionVector3 dirLineA = _lineA[1] - _lineA[0];Vector3 dirLineB = _lineB[1] - _lineB[0];Vector3 posLineA = Vector3.zero;Vector3 posLineB = Vector3.zero;float dot = Vector3.Dot(dirLineA, dirLineB);//两向量空间垂直if (dot == 0){posLineA = _lineA[0] + dirLineA * (Vector3.Dot(_lineB[0], dirLineA) - Vector3.Dot(_lineA[0], dirLineA)) / Vector3.Dot(dirLineA, dirLineA);posLineB = _lineB[0] + dirLineB * (Vector3.Dot(_lineA[0], dirLineB) - Vector3.Dot(_lineB[0], dirLineB)) / Vector3.Dot(dirLineB, dirLineB);}//两向量空间平行else if (dot == 1){posLineA = _lineA[0];posLineB = _lineB[0] + dirLineB * (Vector3.Dot(_lineA[0], dirLineA) - Vector3.Dot(_lineB[0], dirLineA)) / Vector3.Dot(dirLineB, dirLineA);}//两向量不平行也不垂直else{posLineA = _lineA[0] + dirLineA * (Vector3.Dot(dirLineB, dirLineB) * (Vector3.Dot(_lineA[0], dirLineA) - Vector3.Dot(dirLineA, _lineB[0])) + Vector3.Dot(dirLineA, dirLineB) * (Vector3.Dot(_lineB[0], dirLineB) - Vector3.Dot(_lineA[0], dirLineB)))/ (Vector3.Dot(dirLineA, dirLineB) * Vector3.Dot(dirLineA, dirLineB) - Vector3.Dot(dirLineA, dirLineA) * Vector3.Dot(dirLineB, dirLineB));posLineB = _lineB[0] + dirLineB * (Vector3.Dot(dirLineA, dirLineA) * (Vector3.Dot(_lineA[0], dirLineB) - Vector3.Dot(_lineB[0], dirLineB)) + Vector3.Dot(dirLineA, dirLineB) * (Vector3.Dot(_lineB[0], dirLineA) - Vector3.Dot(_lineA[0], dirLineA)))/ (Vector3.Dot(dirLineA, dirLineA) * Vector3.Dot(dirLineB, dirLineB) - Vector3.Dot(dirLineA, dirLineB) * Vector3.Dot(dirLineA, dirLineB));}if (Vector3.Dot(posLineA - _lineA[0], dirLineA) < 0){posLineA = _lineA[0]; //起点到目标点方向 和 线的方向不一致,则点在线段外面}else if (Vector3.Dot(posLineA - _lineA[1], dirLineA) > 0){posLineA = _lineA[1];//终点到目标点方向 和 线的方向一致,则点在线段外面}if (Vector3.Dot(posLineB - _lineB[0], dirLineB) < 0){posLineB = _lineB[0]; //起点到目标点方向 和 线的方向不一致,则点在线段外面}else if (Vector3.Dot(posLineB - _lineB[1], dirLineB) > 0){posLineB = _lineB[1];//终点到目标点方向 和 线的方向一致,则点在线段外面}Debug.DrawLine(_lineA[0], _lineA[1], Color.red);Debug.DrawLine(_lineB[0], _lineB[1], Color.red);Debug.DrawLine(posLineA, posLineB, Color.yellow);}
}