线段与三维点之间的最短距离(3D)

问题描述 投票:0回答:3

我一直在MATLAB中构建一个程序,它描述了如何在2D(Shortest distance between a point and a line segment)中找到点和线段之间的最短距离。我需要一个与之前回答的问题基本相同的功能,但是在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
matlab 3d geometry distance line-segment
3个回答
3
投票

只需将AB以及P定义为列向量。然后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)

所以你只需要使用我在这里发布的第三行和第五行代码,如果我没有弄错,你就可以去了。


1
投票

C ++我不确定它是正确的答案,但有时它工作)测试数据:Pnt = [1 1 1]; S1 = [0 0 0]; S2 = [0 3 3]; ANS = 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;
}

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
© www.soinside.com 2019 - 2024. All rights reserved.