Purpose: I recently wrote C++ code and encountered some basic algorithms. Such as calculating the distance from a vertex to a plane.
The previous article has introduced the plane and its mathematical expression:
geometric expression P lane PlaneP l a n e : plane normal vectorN = ( n 0 n 1 n 2 ) N=\begin{pmatrix} n_0 \\ n_1 \\ n_2 \end{pmatrix}N=⎝⎛n0n1n2⎠⎞, and a vertex P 0 = ( x 0 y 0 z 0 ) P_0=\begin{pmatrix} x_0 \\ y_0 \\ z_0 \end{pmatrix}P0=⎝⎛x0y0z0⎠⎞
Vertex expression: P 1 = ( x 1 y 1 z 1 ) P_1=\begin{pmatrix} x_1 \\ y_1 \\ z_1 \end{pmatrix}P1=⎝⎛x1y1z1⎠⎞
Calculate P 1 P_1P1To plane P lane PlanePlane distance . _ _ _
P lane PlaneThe expression of P l a n e can be transformed inton 0 ( x − x 0 ) + n 1 ( y − y 0 ) + n 2 ( z − z 0 ) = 0 n_0(x-x_0)+n_1(y-y_0 )+n_2(z-z_0)=0n0(x−x0)+n1(y−y0)+n2(z−z0)=0 , calculaten 0 x + n 1 y + n 2 z + d = 0 n_0x+n_1y+n_2z+d=0n0x+n1y+n2z+d=0其中 d = − n 0 x 0 − n 1 y 0 − n 2 z 0 = − N T ⋅ P 0 d=-n_0x_0-n_1y_0-n_2z_0=-N^T \cdot P_0 d=−n0x0−n1y0−n2z0=−NT⋅P0
The derivation formula is as follows:
Calculate the red vertex P 1 P_1P1To the blue plane P lane PlanePlane distance . _ _ _ The yellow vertex is a point P 0 P_0on the planeP0. Vertex-to-plane distance definition: the distance of its point perpendicular to the plane (indicated by the gray line segment in the figure).
Based on the vertical triangle algorithm, the length of the gray line segment is dist distdist
d i s t = ∥ P 0 − P 1 ∥ ⋅ c o s ( θ ) ( 1 ) dist=\lVert P_0-P_1 \rVert \cdot cos(\theta) \space \space (1) dist=∥P0−P1∥⋅c o s ( θ ) ( 1 )
increaseθ \thetaθ are two vectorsP 0 P 1 P_0P_1P0P1and plane normal vector NNFor example ,
cos ( θ ) = ∣ NT ⋅ ( P 0 − P 1 ) ∣ ∥ P 0 − P 1 ∥ ⋅ ∥ N ∥ ( 2 ) cos(\theta) = \cfrac {|N^T \cdot (P_0-P_1)|}{\lVert P_0-P_1 \rVert \cdot \lVert N \rVert} \space \space(2)c o s ( i )=∥P0−P1∥⋅∥N∥∣NT⋅(P0−P1)∣ ( 2 )
Substituting formula (2) into formula (1) can be obtained as follows:
dist = ∣ NT ⋅ ( P 0 − P 1 ) ∣ ∥ N ∥ ( 3 ) dist=\cfrac {|N^T \cdot (P_0 -P_1)|}{ \lVert N \rVert} \space \space (3)dist=∥N∥∣NT⋅(P0−P1)∣ ( 3 )
Put the vectorP 0 = ( x 0 y 0 z 0 ) P_0=\begin{pmatrix} x_0 \\ y_0 \\ z_0 \end{pmatrix}P0=⎝⎛x0y0z0⎠⎞, P 1 = ( x 1 y 1 z 1 ) P_1=\begin{pmatrix} x_1 \\ y_1 \\ z_1 \end{pmatrix} P1=⎝⎛x1y1z1⎠⎞, N = ( n 0 n 1 n 2 ) N=\begin{pmatrix} n_0 \\ n_1 \\ n_2 \end{pmatrix} N=⎝⎛n0n1n2⎠⎞The equation
dist = ∣ NT ⋅ P 0 − NT ⋅ P 1 ∣ ∥ N ∥ = ∣ − d − NT ⋅ P 1 ∣ ∥ N ∥ = ∣ NT ⋅ P 1 + d ∣ ∥ N ∥ ( 4 ) dist=\cfrac {|N^T \cdot P_0 - N^T \cdot P_1|}{ \lVert N \rVert}=\cfrac {|-d - N^T \cdot P_1|}{ \lVert N \rVert} =\cfrac {|N^T \cdot P_1 + d|}{ \lVert N \rVert} \space \space (4)dist=∥N∥∣NT⋅P0−NT⋅P1∣=∥N∥∣−d−NT⋅P1∣=∥N∥∣NT⋅P1+d∣ (4)
The above vector form can be rewritten into an algebraic form:
dist = ∣ n 0 x 1 + n 1 y 1 + n 2 z 1 + d ∣ n 0 2 + n 1 2 + n 2 2 ( 5 ) dist = \cfrac {|n_0x_1 + n_1y_1+n_2z_1+d|}{\sqrt{n_0^2+n_1^2+n_2^2}} \space \space (5)dist=n02+n12+n22∣n0x1+n1y1+n2z1+d∣ (5)
The source code is as follows, it is written based on vector mode. It requires you to configure the Eigen library:
float Pnt3d2PlaneDist(Eigen::Vector4f& fn, Eigen::Vector3f& pnt)
{
Eigen::Vector3f n = Eigen::Vector3f(fn[0], fn[1], fn[2]);
float sd = n.norm();
if (sd < 1e-8)
return std::numeric_limits<float>::max();
float sb = std::abs(n.dot(pnt) + fn[3]);
float d = sb / sd;
return d;
}
See the website for details: https://mathinsight.org/distance_point_plane