Ключом к нахождению решения является знание того, что линия, образованная двумя точками, которые находятся ближе всего друг к другу, является нормальной к двум лучам.
Первый шаг - найтивектор направления линии, которая образована двумя ближайшими точками.Поскольку вектор является нормальным для обоих лучей, это может быть сделано с помощью Cross product .
rayA
и rayB
, которые являются двумя объектами типа THREE.Ray
:
let Nv = rayA.direction.clone().cross(rayB.direction);
Следующий шаг - найти плоскость для каждого луча, которая включает луч и ближайшую точку на другом луче.План состоит из 2 векторов, в данном случае вектора направления плоскости и nv
.Но нам нужно другое представление плоскости, точкой и нормальным вектором.Дело в происхождении луча.Нормальный вектор снова можно получить с помощью Cross product .для дальнейших вычислений эти векторы должны быть Единичные векторы (длина равна 1), поэтому они нормализуются:
let Na = rayA.direction.clone().cross(Nv).normalize();
let Nb = rayB.direction.clone().cross(Nv).normalize();
Теперь проблема заключается в пересечении луча и плана.ptA
и ptB
являются THREE.Vector3
объектами и ближайшими точками на луче:
let Da = rayA.direction.clone().normalize();
let Db = rayB.direction.clone().normalize();
let da = rayB.origin.clone().sub(rayA.origin).dot(Nb) / Da.dot(Nb);
let db = rayA.origin.clone().sub(rayB.origin).dot(Na) / Db.dot(Na);
let ptA = rayA.origin.clone().add(Da.multiplyScalar(da));
let ptB = rayB.origin.clone().add(Db.multiplyScalar(db));
Объяснение пересечения луча и плоскости:
Луч определяется точкой Ra
и направлением Da
.
Плоскость определяется точкой Rb
и нормальный вектор Nb
.
Нормальное расстояние n
от точки Ra
до плоскости (см. Точечный продукт ):
n = | Rb - Ra | * cos(alpha) = dot(Rb - Ra, Nb)
Из этого следует, что расстояние da
от точки пересечения ptA
до начала луча Ra составляет:
da = n / cos(beta) = n / dot(Da, Nb)
Точка пересечения ptA
составляет:
ptA = Ra + Da * da = Ra + Da * dot(Rb - Ra, Nb) / dot(Da, Nb)