Perpendicular on a line segment from a given point

后端 未结 9 1516
小鲜肉
小鲜肉 2020-12-02 11:52

I want to calculate a point on a given line that is perpendicular from a given point.

I have a line segment AB and have a point C outside line segment. I want to ca

相关标签:
9条回答
  • 2020-12-02 11:57

    Since you're not stating which language you're using, I'll give you a generic answer:

    Just have a loop passing through all the points in your AB segment, "draw a segment" to C from them, get the distance from C to D and from A to D, and apply pithagoras theorem. If AD^2 + CD^2 = AC^2, then you've found your point.

    Also, you can optimize your code by starting the loop by the shortest side (considering AD and BD sides), since you'll find that point earlier.

    0 讨论(0)
  • 2020-12-02 11:58

    Proof: Point D is on a line CD perpendicular to AB, and of course D belongs to AB. Write down the Dot product of the two vectors CD.AB = 0, and express the fact D belongs to AB as D=A+t(B-A).

    We end up with 3 equations:

     Dx=Ax+t(Bx-Ax)
     Dy=Ay+t(By-Ay)
    (Dx-Cx)(Bx-Ax)+(Dy-Cy)(By-Ay)=0
    

    Subtitute the first two equations in the third one gives:

    (Ax+t(Bx-Ax)-Cx)(Bx-Ax)+(Ay+t(By-Ay)-Cy)(By-Ay)=0
    

    Distributing to solve for t gives:

    (Ax-Cx)(Bx-Ax)+t(Bx-Ax)(Bx-Ax)+(Ay-Cy)(By-Ay)+t(By-Ay)(By-Ay)=0
    

    which gives:

    t= -[(Ax-Cx)(Bx-Ax)+(Ay-Cy)(By-Ay)]/[(Bx-Ax)^2+(By-Ay)^2]
    

    getting rid of the negative signs:

    t=[(Cx-Ax)(Bx-Ax)+(Cy-Ay)(By-Ay)]/[(Bx-Ax)^2+(By-Ay)^2]
    

    Once you have t, you can figure out the coordinates for D from the first two equations.

     Dx=Ax+t(Bx-Ax)
     Dy=Ay+t(By-Ay)
    
    0 讨论(0)
  • 2020-12-02 12:00

    Here is a python implementation based on Corey Ogburn's answer from this thread.
    It projects the point q onto the line segment defined by p1 and p2 resulting in the point r.
    It will return null if r falls outside of line segment:

    def is_point_on_line(p1, p2, q):
    
        if (p1[0] == p2[0]) and (p1[1] == p2[1]):
            p1[0] -= 0.00001
    
        U = ((q[0] - p1[0]) * (p2[0] - p1[0])) + ((q[1] - p1[1]) * (p2[1] - p1[1]))
        Udenom = math.pow(p2[0] - p1[0], 2) + math.pow(p2[1] - p1[1], 2)
        U /= Udenom
    
        r = [0, 0]
        r[0] = p1[0] + (U * (p2[0] - p1[0]))
        r[1] = p1[1] + (U * (p2[1] - p1[1]))
    
        minx = min(p1[0], p2[0])
        maxx = max(p1[0], p2[0])
        miny = min(p1[1], p2[1])
        maxy = max(p1[1], p2[1])
    
        is_valid = (minx <= r[0] <= maxx) and (miny <= r[1] <= maxy)
    
        if is_valid:
            return r
        else:
            return None
    
    0 讨论(0)
  • 2020-12-02 12:04

    Here i have converted answered code from "cuixiping" to matlab code.

    function Pr=getSpPoint(Line,Point)
    % getSpPoint(): find Perpendicular on a line segment from a given point
    x1=Line(1,1);
    y1=Line(1,2);
    x2=Line(2,1);
    y2=Line(2,1);
    x3=Point(1,1);
    y3=Point(1,2);
    
    px = x2-x1;
    py = y2-y1;
    dAB = px*px + py*py;
    
    u = ((x3 - x1) * px + (y3 - y1) * py) / dAB;
    x = x1 + u * px;
    y = y1 + u * py;
    
    Pr=[x,y];
    
    end
    
    0 讨论(0)
  • 2020-12-02 12:08

    What you are trying to do is called vector projection

    0 讨论(0)
  • 2020-12-02 12:14

    There is a simple closed form solution for this (requiring no loops or approximations) using the vector dot product.

    Imagine your points as vectors where point A is at the origin (0,0) and all other points are referenced from it (you can easily transform your points to this reference frame by subtracting point A from every point).

    In this reference frame point D is simply the vector projection of point C on the vector B which is expressed as:

    // Per wikipedia this is more efficient than the standard (A . Bhat) * Bhat
    Vector projection = Vector.DotProduct(A, B) / Vector.DotProduct(B, B) * B
    

    The result vector can be transformed back to the original coordinate system by adding point A to it.

    0 讨论(0)
提交回复
热议问题