Другие результаты сбивают с толку, многословны и неполны, ИМО. Итак, вот мои два цента - также потенциально запутанные и многословные.
Если вы уверены, что ваши линии не параллельны или параллельны, вам нужно следующее:
% Let each point be def as a 3x1 array
% Let points defining first line be : p1, q1
% Let points defining second line be : p2, q2
L = p1-p2;
M = p1-q1;
N = p2-q2;
A = [M N];
T = pinv(A)*L;
h = p1-T(1)*(p1-q1); % h is a 3x1 array representing the actual pt of intersection
Да, псевдообратная Мура-Пенроуза - мощная вещь. Объяснение этого подхода таково: вы хотите найти весовые коэффициенты или коэффициенты масштабирования «векторов направления» (M и N - векторы направления), которые линейно объединяют M и N, чтобы получить L.
Полное описание представлено ниже. Он представляет простую схему обнаружения исключений, и их обработка остается за пользователем. (Минимальное расстояние между двумя линейными алгоритмами взято из Википедии; сравнение направляющих косинусов (DCS) для проверки ориентации вектора является общеизвестным.)
% Let each point be def as a 3x1 array
% Let points defining first line be : p1, q1
% Let points defining second line be: p2, q2
% There are two conditions that prevent intersection of line segments/lines
% in L3 space. 1. parallel 2. skew-parallel (two lines on parallel planes do not intersect)
% Both conditions need to be identified and handled in a general algorithm.
% First check that lines are not parallel, this is done by comparing DCS of
% the line vectors
% L, M, N ARE DIRECTION VECTORS.
L = p1-p2;
M = p1-q1;
N = p2-q2;
% Calculate a normalized DCS for comparison. If equal, it means lines are parallel.
MVectorMagnitude = sqrt(sum(M.*M,2)); % The rowsum is just a generalization for N-D vectors.
NVectorMagnitude=sqrt(sum(N.*N,2)); % The rowsum is just a generalization for N-D vectors.
if isequal(M/MVectorMagnitude,N/NVectorMagnitude) % Compare the DCS for equality
fprintf('%s\n', 'lines are parallel. End routine')
end;
% Now check that lines do not exist on parallel planes
% This is done by checking the minimum distance between the two lines. If there's a minimum distance, then the lines are skew.
a1 = dot(M,L); b1 = dot(M,M); c1 = dot(M,N);
a2 = dot(N,L); b2 = dot(N,M); c2 = dot(N,N);
s1 = -(a1*c2 - a2*c1)/(b1*c2-b2*c1);
s2 = -(a1*b2 - a2*b1)/(b1*c2-b2*c1);
Sm = (L + s1*M - s2*N);
s = sqrt(sum(Sm.*Sm,2));
if ~isequal(s,0) % If the minimum distance between two lines is not zero, then the lines do not intersect
fprintf('%s\n','lines are skew. End routine')
end;
% Here's the actual calculation of the point of intersection of two lines.
A = [M N];
T = pinv(A)*L;
h = p1-T(1)*(p1-q1); % h is a 3x1 array representing the actual pt of intersection.
Таким образом, подход pinv даст вам результаты, даже если ваши векторы M и N перекошены (но не параллельны, потому что inv (A'.A) должен существовать). Вы можете использовать это, чтобы определить минимальное расстояние между двумя параллельными линиями или между двумя параллельными плоскостями - для этого определите k = p2+T(2)*(p2-q2)
, и тогда требуемое расстояние будет h-k. Также обратите внимание, что h и k - это точки на линиях, которые находятся ближе всего друг к другу. Линии IFF перекошены.
Таким образом, использование псевдообратного и проекционного пространств дает нам краткий алгоритм для:
- Определение точки пересечения двух прямых (не параллельных и не косых)
- Определение минимального расстояния между двумя линиями (не параллельно)
- Определение точек, ближайших друг к другу на двух наклонных линиях.
Лаконичность - это не то же самое, что экономия времени. Многое зависит от вашей точной реализации функции pinv - MATLAB использует svd
, что решает проблему с допуском. Кроме того, некоторые результаты будут только приблизительно точными в более высоких измерениях и более высоких порядках определения метрики измерения (или векторных норм). Помимо реализации, не зависящей от очевидного измерения, она может использоваться в статистическом регрессионном анализе и алгебраически максимизировать вероятность точечных оценок.