Math 在MATLAB中求两个向量的交点
我有一个非常简单的MATLAB问题。找到两个向量的交点最简单的方法是什么。我不熟悉各种各样的MATLAB函数——似乎应该有一个这样的函数Math 在MATLAB中求两个向量的交点,math,matlab,Math,Matlab,我有一个非常简单的MATLAB问题。找到两个向量的交点最简单的方法是什么。我不熟悉各种各样的MATLAB函数——似乎应该有一个这样的函数 例如,如果我有一个从(0,0)到(6,6)的向量和另一个从(0,6)到(6,0)的向量,我需要确定它们在(3,3)处相交。好吧,两条不同的线上确实有两个点,并且你想要找到交点。最简单的方法是找到两条直线的方程,然后计算交点 直线方程由y=mx+b给出,其中m为斜率,b为y截距。对于一条直线,有两个点,这两个点给出了两个方程。所以,你可以解出常数m和b。由此得出
例如,如果我有一个从(0,0)到(6,6)的向量和另一个从(0,6)到(6,0)的向量,我需要确定它们在(3,3)处相交。好吧,两条不同的线上确实有两个点,并且你想要找到交点。最简单的方法是找到两条直线的方程,然后计算交点 直线方程由y=mx+b给出,其中m为斜率,b为y截距。对于一条直线,有两个点,这两个点给出了两个方程。所以,你可以解出常数m和b。由此得出以下两个方程式:
0 = 0*m + 1*b % Using the first point x=y=0 into y=m*x+b
6 = 6*m + 1*b % Using the second point x=y=6
或以矩阵形式:
[ 0 ] = [ 0 1 ]* [ m ]
[ 6 ] [ 6 1 ] [ b ]
对于第一行,可以在MATLAB中通过
C1 = inv([0 1;6 1]*[1;0]; % m=C1(1) and b=C(2)
现在有了两条直线的方程,可以通过求解以下方程组(通过操纵直线方程获得)来求解交点:
剩下的就是以矩阵形式写出上述方程组并求解:
[x] = inv [m_1 -1] * [-b_1]
[y] [m_2 -1] [-b_2]
或使用MATLAB语法:
I = inv([m_1 -1; m_2 -1])*[-b_1;-b_2]; % I is the intersection.
注释
- 根据gnovice的注释,如果直线实际上是线段,则需要检查交点是否在线段的端点之间
- 如果两个斜率相等,m_1=m_2,那么要么没有交点,要么有无限多个交点
x = [0 0; 6 6]; %# Starting points in first row, ending points in second row
y = [0 6; 6 0];
然后,可将上述来源的方程式编码如下:
dx = diff(x); %# Take the differences down each column
dy = diff(y);
den = dx(1)*dy(2)-dy(1)*dx(2); %# Precompute the denominator
ua = (dx(2)*(y(1)-y(3))-dy(2)*(x(1)-x(3)))/den;
ub = (dx(1)*(y(1)-y(3))-dy(1)*(x(1)-x(3)))/den;
现在可以计算两条线的交点:
xi = x(1)+ua*dx(1);
yi = y(1)+ua*dy(1);
对于问题中的示例,上述代码给出了预期的xi=3
和yi=3
。如果要检查交点是否位于直线的端点之间(即,它们是有限的线段),只需检查值ua
和ub
是否都位于0和1之间:
isInSegment = all(([ua ub] >= 0) & ([ua ub] <= 1));
isInSegment=all([ua-ub]>=0)和([ua-ub]对于一般多维解,您实际要做的是解一系列线性系统
首先,您需要将方程简化为线性形式:Ax+By=C
(根据需要展开维度)
有两点:
y - y1 = (y2 - y1) / (x2 - x1) * (x - x1)
y - y1 = (y2 - y1) / (x2 - x1) * x - (y2 - y1) / (x2 - x1) * x1
(y1 - y2) / (x2 - x1) * x + y - y1 = (y1 - y2) / (x2 - x1) * x1
(y1 - y2) / (x2 - x1) * x + y = (y1 - y2) / (x2 - x1) * x1 + y1
(y1 - y2) * x + (x2 - x1) * y = (y1 - y2) * x1 + (x2 - x1) * y1
A = (y1 - y2)
B = (x2 - x1)
C = (y1 - y2) * x1 + (x2 - x1) * y1 = A * x1 + B * y1
例如:
x1 = 0, x2 = 6, y1 = 0, y2 = 6
A1 = (0 - 6) = -6
B1 = (6 - 0) = 6
C1 = A1 * 0 + B1 * 0 = 0
x1 = 0, x2 = 6, y1 = 6, y2 = 0
A2 = (6 - 0) = 6
B2 = (6 - 0) = 6
C2 = A2 * 0 + B2 * 6 = 6 * 6 = 36
然后,形成一个矩阵,B和C列为:
[A1 B1 C1]
[A2 B2 C2]
[-6 6 0]
[ 6 6 36]
现在,使用Matlab函数rref(矩阵)
,简化为梯队形式:
正如您所猜测的,最后一列是您的交点。这可以根据需要扩展到任意多个维度。如果您的简化梯队形式的前面部分具有除单位矩阵以外的其他内容,则向量要么没有唯一的交点,要么没有交点,具体取决于矩阵的形式
dim = 2;
% Do other stuff, ending with rref(matrix)
if (matrix(:,1:dim) == eye(dim))
% Matrix has unique solution.
solution = (matrix(:,dim+1))'
else
% No unique solution.
end
在两个维度中,变化如下:
线性解,表示解是一行形式的x+By=C
:
[ 1 B C]
[ 0 0 0]
无解决方案,表示线没有交叉,其中C2 0
:
[ 1 B C1]
[ 0 0 C2]
在我看来,其他结果令人困惑、冗长且不完整。因此,这是我的两分钱——也可能令人困惑且冗长
如果您确定直线不是倾斜平行或平行的,则只需执行以下操作:
% 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
下面给出了完整的描述。它提供了一个简单的异常检测方案,其处理留给用户。(两行算法之间的最小距离来自维基百科;方向余弦(DC)的比较检查向量姿态是常识。)
因此,即使M和N向量是歪斜的(但不是平行的,因为inv(A'.A)必须存在),pinv方法也会给你结果。你可以用它来确定两条平行线之间或两个平行平面之间的最小距离-为此,定义k=p2+T(2)*(p2-q2)
,则所需距离为h-k。还请注意,当直线倾斜时,h和k是直线上最接近的点
因此,伪逆空间和投影空间的使用为我们提供了一个简洁的算法:
确定两条直线的交点(不平行,也不倾斜)
确定两条线之间的最小距离(不平行)
确定两条斜线上彼此最接近的点
简洁与省时不一样。很大程度上取决于您精确的pinv函数实现-MATLAB使用svd
,它解决了一个公差。此外,一些结果仅在测量度量(或向量规范)的高维和高阶定义中近似准确。除了明显的独立于维度的实现之外,这还可以用于统计回归分析和代数最大化点估计的可能性。您应该在mathoverload上询问这个问题。com@Michael:我想你指的是mathoverflow.net,尽管该网站更倾向于“研究级数学”。像这样简单的问题可能会一直存在(见这篇文章:)此外,这个问题涉及到在Matlab中编程一个解决方案,而不是如何用数学方法解决这个问题。关于如何在Matlab中解决这个问题,请参阅我的答案。向量没有交点,直线有!一个
[ 1 B C1]
[ 0 0 C2]
% 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
% 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.