#/usr/bin/env python

import pygame
from pygame.locals import *

from math import sqrt;
    
def dot(A, B, C):
    AB = [B[0]-A[0],B[1]-A[1]]
    BC = [C[0]-B[0],C[1]-B[1]]
    return AB[0] * BC[0] + AB[1] * BC[1]

def cross(A, B, C):    
    AB = [B[0]-A[0],B[1]-A[1]]
    AC = [C[0]-A[0],C[1]-A[1]]    
    return AB[0] * AC[1] - AB[1] * AC[0]

def distance(A, B):
    d1 = A[0] - B[0]
    d2 = A[1] - B[1]
    return sqrt(d1*d1+d2*d2)

def pointOnLine(P,L):
    x1=L[0][0]   
    y1=L[0][1]
    x2=L[1][0]   
    y2=L[1][1]
    A1 = y2-y1
    B1 = x1-x2
    C1 = A1*x1+B1*y1
    
    x1 = P[0]
    y1 = P[1]
    A2 = -B1
    B2 = A1
    C2 = A2*x1+B2*y1
    
    det = A1*B2 - A2*B1
    x = (B2*C1 - B1*C2)/det
    y = (A1*C2 - A2*C1)/det      
    return (x,y)    

def linePointDist(A, B, C):    
    dot1 = dot(A,B,C)
    if(dot1 > 0):
        # End point B is closest
        return (distance(B,C),tuple(B))
    dot2 = dot(B,A,C)
    if(dot2 > 0): 
        # End point A is closest
        return (distance(A,C),tuple(A))
    
    # Point ON the line is closest
    dist = cross(A,B,C) / distance(A,B)
        
    return (abs(dist),pointOnLine(C,[[A[0],A[1]],[B[0],B[1]]]))
       
def main():

    line = [[100,100],[500,500]]
    point = [200,400]
    mp = None
    calc = True

    # init pygame
    pygame.init()    

    # setup the display
    screen = pygame.display.set_mode((600, 600),1)
    pygame.display.set_caption("Draw line with LEFT mouse, set point position with RIGHT mouse.")

    clock = pygame.time.Clock()

    while 1:
        clock.tick(30)        

        for event in pygame.event.get():
            if event.type == QUIT:
                return
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    return
            elif event.type == MOUSEBUTTONDOWN: 
                if event.button==1:
                    line[0][0] = event.pos[0]   
                    line[0][1] = event.pos[1]   
                    line[1][0] = event.pos[0]   
                    line[1][1] = event.pos[1]   
                    mp = None
                elif event.button==3:
                    point[0] = event.pos[0]  
                    point[1] = event.pos[1]   
                    calc = True
                        
            elif event.type == MOUSEMOTION:
                if event.buttons[0]:
                    line[1][0] = event.pos[0]   
                    line[1][1] = event.pos[1]   
                    calc = True
                elif event.buttons[2]:
                    point[0] = event.pos[0]   
                    point[1] = event.pos[1]  
                    calc = True
                
        if calc:
            (d,mp) =  linePointDist(line[0],line[1],point)
            calc = False

        # clear screen
        screen.fill((255,255,255))           

        if mp:
            pygame.draw.circle(screen, (0,255,0), mp, 5 ,0)
            pygame.draw.line(screen, (0,255,0), point, mp, 1)
        pygame.draw.circle(screen, (0,0,0), point, 5 ,0)
        pygame.draw.line(screen, (0,0,0), line[0], line[1], 1)
                
        pygame.display.flip()
             
 
#this calls the 'main' function when this script is executed
if __name__ == '__main__': main()
