get closest point to a line

后端 未结 12 1999
逝去的感伤
逝去的感伤 2020-11-28 04:45

I\'d like to have a straight forward C# function to get a closest point (from a point P) to a line-segment, AB. An abstract function may look like this. I\'ve search through

12条回答
  •  长情又很酷
    2020-11-28 05:12

    This answer is based on ideas from projective geometry.

    Compute the cross product (Ax,Ay,1)×(Bx,By,1)=(u,v,w). The resulting vector describes the line connecting A and B: it has the equation ux+vy+w=0. But you can also interpret (u,v,0) as a point infinitely far away in a direction perpendicular to that line. Doing another cross product you get the line joining hat point to P: (u,v,0)×(Px,Py,1). And to intersect that line with the line AB, you do another cross product: ((u,v,0)×(Px,Py,1))×(u,v,w). The result will be a homogenous coordinate vector (x,y,z) from which you can read the coordinates of this closest point as (x/z,y/z).

    Take everything together and you get the following formula:

    {\scriptsize\begin{pmatrix}x\y\z\end{pmatrix}}=\Bigl(\bigl({\scriptsize\begin{pmatrix}1&0&0\0&1&0\0&0&0\end{pmatrix}}(A\times B)\bigr)\times P\Bigr)\times(A\times B)

    Using a computer algebra system, you can find the resulting coordinates to be the following:

    x = ((Ax - Bx)*Px + (Ay - By)*Py)*(Ax - Bx) + (Ay*Bx - Ax*By)*(Ay - By)
    y = -(Ay*Bx - Ax*By)*(Ax - Bx) + ((Ax - Bx)*Px + (Ay - By)*Py)*(Ay - By)
    z = (Ax - Bx)^2 + (Ay - By)^2
    

    As you notice, there are a lot of recurring terms. Inventing (pretty much arbitrary) names for these, you can get the following final result, written in pseudocode:

    dx = A.x - B.x
    dy = A.y - B.y
    det = A.y*B.x - A.x*B.y
    dot = dx*P.x + dy*P.y
    x = dot*dx + det*dy
    y = dot*dy - det*dx
    z = dx*dx + dy*dy
    zinv = 1/z
    return new Point(x*zinv, y*zinv)
    

    Benefits of this approach:

    • No case distinctions
    • No square roots
    • Only a single division

提交回复
热议问题