Purpose: A recent research project encountered the distance from a point to a line, a fundamental algorithm that is very important in spatial geometry, and is therefore documented.
Vector representation of a straight line: L : r → = P 0 → + t N 0 → L:\overrightarrow{r}=\overrightarrow{P_0}+t\overrightarrow{N_0}L:r=P0+tN0;其中 P 0 → = ( x 0 y 0 z 0 ) \overrightarrow{P_0}=\begin{pmatrix} x_0 \\ y_0 \\ z_0 \end{pmatrix} P0=⎝⎛x0y0z0⎠⎞, N 0 → = ( n x 0 n y 0 n z 0 ) \overrightarrow{N_0}=\begin{pmatrix} n_x^0 \\ n_y^0 \\ n_z^0 \end{pmatrix} N0=⎝⎛nx0ny0nz0⎠⎞
Vertex vector representation: P → : ( x 1 y 1 z 1 ) \overrightarrow{P}: \begin{pmatrix} x_1 \\ y_1 \\ z_1 \end{pmatrix}P:⎝⎛x1y1z1⎠⎞。
There are many methods for the distance from a vertex to a straight line. First, a very simple method is introduced, which is obtained based on vector expression.
1) Method 1:
Suppose the vertex P → \overrightarrow{P}PProjected onto the line to get P ′ → \overrightarrow{P'}P′, defined according to the distance from a point to a straight line, ∣ PP ′ → ∣ |\overrightarrow{PP'}|∣PP′∣ is the vertexP → \overrightarrow{P}Pto line LLL distance. As shown below:
The calculation process will be introduced below:
because the vertex P ′ → \overrightarrow{P'}P′On a straight line, it can be expressed as: P ′ → = P 0 → + t ′ N 0 → \overrightarrow{P'}=\overrightarrow{P_0}+t'\overrightarrow{N_0}P′=P0+t′N0,所以:
P P ′ → = ( P 0 → + t ′ N 0 → ) − P → \overrightarrow{PP'}=(\overrightarrow{P_0}+t'\overrightarrow{N_0})-\overrightarrow{P} PP′=(P0+t′N0)−P
Since PP ′ → \overrightarrow{PP'}PP′and straight line LLL is vertical, we can get:PP ′ → T ⋅ N 0 → = 0 \overrightarrow{PP'}^T \cdot \overrightarrow{N_0}=0PP′T⋅N0=0
P P ′ → T ⋅ N 0 → = 0 = > ( P 0 → + t ′ N 0 → − P → ) T ⋅ N 0 → = 0 = > ( t ′ N 0 → + P 0 → − P → ) T ⋅ N 0 → = 0 = > t ′ N 0 → T ⋅ N 0 → = ( P → T − P 0 → T ) ⋅ N 0 → = > t ′ = ( P → T − P 0 → T ) ⋅ N 0 → / ( N 0 → T ⋅ N 0 → ) \overrightarrow{PP'}^T \cdot \overrightarrow{N_0}=0 \\ =>(\overrightarrow{P_0}+t'\overrightarrow{N_0}-\overrightarrow{P})^T \cdot \overrightarrow{N_0}=0 \\ =>(t'\overrightarrow{N_0}+\overrightarrow{P_0}-\overrightarrow{P})^T \cdot \overrightarrow{N_0}=0 \\ =>t'\overrightarrow{N_0}^T \cdot \overrightarrow{N_0}=(\overrightarrow{P}^T-\overrightarrow{P_0}^T)\cdot \overrightarrow{N_0} \\ =>t' = (\overrightarrow{P}^T-\overrightarrow{P_0}^T)\cdot \overrightarrow{N_0} / (\overrightarrow{N_0}^T\cdot \overrightarrow{N_0}) PP′T⋅N0=0=>(P0+t′N0−P)T⋅N0=0=>(t′N0+P0−P)T⋅N0=0=>t′N0T⋅N0=(PT−P0T)⋅N0=>t′=(PT−P0T)⋅N0/(N0T⋅N0)
by t't't′ ComputeP ′ = P 0 → + t ′ N 0 → P'=\overrightarrow{P_0}+t'\overrightarrow{N_0}P′=P0+t′N0
d = ∣ P P ′ → ∣ = ∣ ( P 0 → + t ′ N 0 → ) − P → ∣ d=|\overrightarrow{PP'}|=|(\overrightarrow{P_0}+t'\overrightarrow{N_0})-\overrightarrow{P}| d=∣PP′∣=∣(P0+t′N0)−P∣
Get the distance dd from the point to the lined . The C++ code is as follows:
#include<iostream>
#include<Eigen/Eigen>
#include <vector>
void ComputePntProj2Line3D(Eigen::Vector3d& lpnt, Eigen::Vector3d& ldir, Eigen::Vector3d& pnt, Eigen::Vector3d& proj)
{
//计算pi平面
//std::cerr << "lpnt: "<< lpnt.transpose() <<std::endl;
//std::cerr << "ldir: "<< ldir.transpose() <<std::endl;
//std::cerr << "pnt: "<< pnt.transpose() <<std::endl;
double t = (pnt.dot(ldir) - lpnt.dot(ldir)) / ldir.squaredNorm();
//std::cerr <<"t: " << t <<std::endl;
proj = t * ldir + lpnt;
}
double ComputePnt2Line3D(Eigen::Vector3d& lpnt, Eigen::Vector3d& ldir, Eigen::Vector3d& pnt)
{
//start to compute dist between pnt and line(lpnt, ldir)
Eigen::Vector3d proj;
ComputePntProj2Line3D(lpnt, ldir, pnt, proj);
//std::cerr << "proj: "<< proj.transpose() <<std::endl;
double d = (proj - pnt).norm();
return d;
}
int main(int argc, char** argv)
{
Eigen::Vector3d lp,ld;
ld = Eigen::Vector3d(3.0, 1.0, 1.0);
lp = Eigen::Vector3d(-4.0, -5.0, -1.0);
Eigen::Vector3d p;
p = Eigen::Vector3d(-6.0, 1.0, 21.0);
double dist = ComputePnt2Line3D(lp, ld, p);
std::cerr <<"dist: " << dist <<std::endl;
return 0;
}
Code test:
2) Method 2: (subsequent addition)