1

我一直在 MATLAB 中构建一个程序,该线程描述了如何在 2D 中找到点和线段之间的最短距离(点和线段之间的最短距离)。我需要一个与之前回答的问题基本相同的函数,但在 3D 而非 2D 和 MATLAB 中。

上一篇文章的答案的热门评论都不是在 MATLAB 中,所以我在理解这段代码的幕后发生的事情时遇到了一些麻烦。也许你们中的一些更聪明或更熟练的人可以帮助我将其转换为 3D MATLAB 代码?

线段将被定义为两个点 S1 (x1,y1,z1) 和 S2 (x2,y2,z2),该点只是一个单一的坐标 Pnt (x3,y3,z3)。

编辑:这里似乎有点混乱。我的意思是线段不是无限的线。我附上了我正在使用的代码。我想补充一点,我修改的这段代码最初是作为上述链接线程中评论的一部分编写的,原作者 Peter Karasev 值得称赞。照原样,代码在 2D 中工作,我在 3 行中进行了评论,这是使其成为 3D 的开始(vz、uz 和 lenSqr)。我的具体问题是,我真的不明白 detP 在数学上发生了什么以及如何使 detP 和随后的 if 语句在 3D 中工作。

输入如上面在原始问题文本中定义的那样。

function r = PointToLineSegment3D( S1, S2, Pnt )
% r = PointToLineSegment3D( S1, S2, Pnt )

vx = S1(1)-Pnt(1);
vy = S1(2)-Pnt(2);
% vz = S1(3)-Pnt(3);

ux = S2(1)-S1(1);
uy = S2(2)-S1(2);
% uz = S2(3)-S1(3);

lenSqr= (ux*ux+uy*uy); % +uz*uz
detP= -vx*ux + -vy*uy;

if( detP < 0 )
    r = norm(S1-Pnt,2);

elseif( detP > lenSqr )
    r = norm(S2-Pnt,2);

else
    r = abs(ux*vy-uy*vx)/sqrt(lenSqr);
end
end
4

3 回答 3

4

只需将Aand定义BP列向量。X然后在线上的任何点AB都有形式

X = A+t*(B-A)

t.

当然,线XP必须垂直于线AB,这意味着相应的标量积必须为零:

0 == (A+t*(B-A) - P)' * (B-A) == (A-P)'*(B-A)+t*norm(B-A)^2

这意味着

t = (A-P)'*(B-A) / norm(B-A)^2

那么这只是计算距离的问题XP,即

d = norm(X-P)

所以

d = norm(A+t*(B-A)-P)

因此,您只需要使用我在此处发布的第三和第五行代码,如果我没记错的话,您就可以开始了。

于 2017-04-11T21:38:02.430 回答
1

C++ 我不确定这是正确的答案,但有时它会起作用)测试数据:Pnt=[1 1 1]; S1=[0 0 0];S2=[0 3 3];答案=1.0

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<vector>
#include<iterator>
#include <iomanip>

using namespace std;
int main()
{

double vx,vy,vz,ux,uy,uz,r=0,lenSqr,detP, c,tmp;
int i;
vector<double>copy;
vector<double>Pnt;
vector<double>S1;
vector<double>S2;

for(i=0; i<9; i++)
{
    cin>>c;
    copy.push_back(c);
}
for(i=0; i<3; i++)
{
    Pnt.insert(Pnt.begin(), copy[i]);
//  cout<<copy[i]<<endl;        
}
    copy.erase(copy.begin(),copy.begin()+3);
    copy.shrink_to_fit();
for(i=0; i<3; i++)
{
    S1.insert(S1.begin(), copy[i]);
}
copy.erase(copy.begin(),copy.begin()+3);
copy.shrink_to_fit();
for(i=0; i<3; i++)
{
    S2.insert(S2.begin(), copy[i]);
    copy.erase(copy.begin());
}
copy.shrink_to_fit();



/*
vector<float>Pnt(3,1.0);
//for(i=0; i<3; i++)
//cout<<Pnt[i];

vector<float>S1(3,0.0);
//for(i=0; i<3; i++)
//cout<<S1[i];

vector<float>S2;
S2.insert(S2.begin(), 3.0);
S2.insert(S2.begin(), 3.0);
S2.insert(S2.begin(), 0.0);

//for(int i=0; i<3; i++)
//cout<<S2[i];
//cout<<endl;   
*/

vx = S1[0]-Pnt[0];
vy = S1[1]-Pnt[1];
vz = S1[2]-Pnt[2];
//cout<<"V: "<<vx<<vy<<vz<<endl;
ux = S2[0]-S1[0];
uy = S2[1]-S1[1];
uz = S2[2]-S1[2];
//cout<<"U: "<<ux<<uy<<uz<<endl;


lenSqr= (ux*ux+uy*uy+uz*uz);
//cout<<"lenSqr "<<lenSqr<<endl;
detP= (-vx*ux ) + (-vy*uy) + (-vz*uz);
//cout<<"detP "<<detP<<endl;



if( detP < 0 )
{
//  r = norm(S1-Pnt,2)
    for(i=0; i<3; i++)
    {       
        tmp=pow((S1[i]-Pnt[i]),2);
        r += tmp;
//      cout<<"r: "<<r;
    }
    r = sqrt(r);
    cout<<fixed<<r;
}

else if( detP > lenSqr )
{
//  r = norm(S2-Pnt,2);
    for(i=0; i<3; i++)
    {       
        tmp=pow((S2[i]-Pnt[i]),2);
        r += tmp;
//      cout<<"r: "<<r;
    }
    r = sqrt(r);
    cout<<fixed<<r;
}
//if(detP <= lenSqr || detP>=0)
else
{
//  r =norm( abs(cross((S2-S1),(S1-Pnt)))/sqrt(lenSqr));
    float i1,j1,k1;

i1 = uz*vy-uy*vz;
j1 = ux*vz-uz*vx;
k1 = uy*vx-ux*vy;
//cout<<"I J k: "<<i1<<j1<<k1<<endl;
r=sqrt(pow(i1,2)+pow(j1,2)+pow(k1,2))/sqrt(lenSqr);
cout<<fixed<<r;
}

return 0;
}
于 2019-02-20T12:23:26.957 回答
0

对于发现此问题的未来用户,这是我为在 MATLAB 中以 3D 工作而编写的代码。这不适用于仅一条线段的无限线。

function r = PointToLineSegment3D( S1, S2, Pnt )
% r = PointToLineSegment3D( S1, S2, Pnt )

vx = S1(1)-Pnt(1);
vy = S1(2)-Pnt(2);
vz = S1(3)-Pnt(3);

ux = S2(1)-S1(1);
uy = S2(2)-S1(2);
uz = S2(3)-S1(3);

lenSqr= (ux*ux+uy*uy+uz*uz)


detP= -vx*ux + -vy*uy + -vz*uz;

if( detP < 0 )
    r = norm(S1-Pnt,2);

elseif( detP > lenSqr )
    r = norm(S2-Pnt,2);

else
    r =norm( abs(cross((S2-S1),(S1-Pnt)))/sqrt(lenSqr));
end
end
于 2017-04-14T15:34:11.500 回答