Math 在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。由此得出

我有一个非常简单的MATLAB问题。找到两个向量的交点最简单的方法是什么。我不熟悉各种各样的MATLAB函数——似乎应该有一个这样的函数


例如,如果我有一个从(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,那么要么没有交点,要么有无限多个交点


一种解决方案是使用(更新:这是一个internet存档链接,因为该站点已不存在)。首先可以创建两个矩阵:一个用于保存直线端点的x坐标,另一个用于保存y坐标

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.