Coordinates of a Point on a Line That is Closest to an External Point

Test Problem

Find the point (coordinates) that defines the shortest distance from a point to a line.

image missing

Test Code

#!/usr/bin/python3
# ====================================================================
# coordinates of a point on a line that is closest to an external point
# ====================================================================
# From: stackoverflow.com/questions/47481774/
# getting-point-on-line-segment-that-is-closest-to-another-point
# ====================================================================

# --------------------------------------------------------------------
# ---- calculate closest point
# --------------------------------------------------------------------

def closest_point(a,b,p):
    
    ab = (b[0]-a[0],b[1]-a[1])

    ap = (p[0]-a[0],p[1]-a[1])

    sqr_ab = ab[0]*ab[0] + ab[1]*ab[1]

    # ---- t is the interpolation parameter between A and B. If it
    # ---- is 0, then the point projects onto A. If it is 1, it
    # ---- projects onto B. Fractional values represent points in
    # ---- between.

    t = (ap[0]*ab[0] + ap[1]*ab[1]) / sqr_ab

    # ---- If you want to restrict the projection to the line segment,
    # ---- clamp t
    # ---- if t < 0:
    # ----     t = 0
    # ---- elif t > 1:
    # ----     t = 1

    return (a[0]+t*ab[0],a[1]+t*ab[1])


# --------------------------------------------------------------------
# ---- main
# --------------------------------------------------------------------

if __name__ == '__main__':

    print()
    print('Point tests')
    print()

    print('test 1 - initial test')

    p1 = (5,1)
    p2 = (3,3)
    p  = (2,6)
    cp = closest_point(p1,p2,p)
    print(cp)
    
    print('test 2 - reverse direction')

    p1 = (3,3)
    p2 = (5,1)
    p  = (2,6)
    cp = closest_point(p1,p2,p)
    print(cp)
    
    print('test 3 - point is on the line')

    p1 = (5,1)
    p2 = (3,3)
    p  = (4,2)
    cp = closest_point(p1,p2,p)
    print(cp)

    print('test 4 - point is between p1 and p2')

    p1 = (5,1)
    p2 = (3,3)
    p  = (5,3)
    cp = closest_point(p1,p2,p)
    print(cp)

    print('test 5 - initial test with negative x')

    p1 = (-5,1)
    p2 = (-3,3)
    p  = (-2,6)
    cp = closest_point(p1,p2,p)
    print(cp)
    
    print('test 6 - slope 0 degrees')

    p1 = (6,1)
    p2 = (3,1)
    p  = (1,2)
    cp = closest_point(p1,p2,p)
    print(cp)

    print('test 7 - slope 90 degrees')

    p1 = (-1,1)
    p2 = (-1,3)
    p  = (1,4)
    cp = closest_point(p1,p2,p)
    print(cp)