#! /usr/bin/env python
###############################################################################
#                                                                             #
#   Copyright 2005 University of Cambridge Computer Laboratory.               #
#                                                                             #
#   This file is part of Nprobe.                                              #
#                                                                             #
#   Nprobe is free software; you can redistribute it and/or modify            #
#   it under the terms of the GNU General Public License as published by      #
#   the Free Software Foundation; either version 2 of the License, or         #
#   (at your option) any later version.                                       #
#                                                                             #
#   Nprobe is distributed in the hope that it will be useful,                 #
#   but WITHOUT ANY WARRANTY; without even the implied warranty of            #
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             #
#   GNU General Public License for more details.                              #
#                                                                             #
#   You should have received a copy of the GNU General Public License         #
#   along with Nprobe; if not, write to the Free Software                     #
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA #
#                                                                             #
###############################################################################


from Tkinter import *
	    
tog = 1

##############################################################################


def ccw(x0, y0, x1, y1, x2, y2):

    dx1 = x1-x0
    dy1 = y1-y0
    dx2 = x2-x0
    dy2 = y2-y0

    if dx1*dy2 > dy1*dx2:
	return 1
    if dx1*dy2 < dy1*dx2:
	return -1
    if dx1*dx2 < 0 or dy1*dy2 < 0:
	return -1
    if dx1*dx1 + dy1*dy1 < dx2*dx2 + dy2*dy2:
	return 1

    return 0

##############################################################################



def intersect(x1, y1, x2, y2, x3, y3, x4, y4):

     return ((ccw(x1, y1, x2, y2, x3, y3)*ccw(x1, y1, x2, y2, x4, y4) <= 0) and (ccw(x3, y3, x4, y4, x1, y1)*ccw(x3, y3, x4, y4, x2, y2) <=0))

##############################################################################

def LINE(canv, s):
    p1=s.p1
    p2=s.p2
    #print 'drawing %s%s' % (p1.lab, p2.lab)
    canv.create_line(p1.x, p1.y, p2.x, p2.y, fill='white')
    canv.create_text(p1.x, p1.y, text=p1.lab, font=("ariel", 12), fill='white')
    canv.create_text(p2.x, p2.y, text=p2.lab, font=("ariel", 12), fill='white')

##############################################################################

def inside(x, y, bounds):

    return (bounds[0] <= x <= bounds[1] and bounds[2] <= y <= bounds[3]) 

##############################################################################


def interpx_l(x1, y1, x2, y2, cut):
    
    if x1 == x2:
	return x1
    
    a = long(y1-cut)
    b = long(x2-x1)
    c = long(y1-y2)
    x = int((a*b)/c) + x1
    
    return x 
	
###############################################################################


def interpy_l(x1, y1, x2, y2, cut):
    
    if y2 == y1:
	return y1

    if x2 == x1:
	raise Nodraw
    
    a = long(x2-cut)
    b = long(y1-y2)
    c = long(x2-x1)
    y = int((a*b)/c) + y2
    
    return y 
	
###############################################################################

class Nodraw:

    pass

##############################################################################

def coincident(a1, a2, b1, b2):

    e = []

    if b1 <= a1 <= b2:
	e.append(a1)
    elif abs(a1 - b1) > abs(a1 - b2):
	e.append(b2)
    else:
	e.append(b1)

    if b1 <= a2 <= b2:
	e.append(a2)
    elif abs(a2 - b1) > abs(a2 - b2):
	e.append(b2)
    else:
	e.append(b1)

    return (e[0], e[1])
		  

##############################################################################

def endpoints(x0, y0, x1, y1, bounds):
    
    xl = bounds[0]
    xr = bounds[1]
    yt = bounds[2]
    yb = bounds[3]
    
    if x0 == xl == x1 or x0 == xr == x1:
	yy1, yy2 = coincident(y0, y1, yt, yb)
	return(x1, yy1, x1, yy2)
    elif y0 == yt == y1 or y0 == yb == y1:
	xx1, xx2 = coincident(x0, x1, xl, xr)
	return(xx1, y1, xx2, y1) 
	
	

    elif inside(x0, y0, bounds):
	if inside(x1, y1, bounds):
	    return (x0, y0, x1, y1)
	if intersect(x0, y0, x1, y1, xl, yt, xl, yb):
	    return (x0, y0, xl, interpy_l(x0, y0, x1, y1, xl))
	elif intersect(x0, y0, x1, y1, xr, yt, xr, yb):
	    return (x0, y0, xr, interpy_l(x0, y0, x1, y1, xr))
	elif intersect(x0, y0, x1, y1, xr, yt, xl, yt):
	    return (x0, y0, interpx_l(x0, y0, x1, y1, yt), yt)
	elif intersect(x0, y0, x1, y1, xr, yb, xl, yb):
	    return (x0, y0, interpx_l(x0, y0, x1, y1, yb), yb)
    elif inside(x1, y1, bounds):
	if intersect(x0, y0, x1, y1, xl, yt, xl, yb):
	    return (x1, y1, xl, interpy_l(x0, y0, x1, y1, xl))
	elif intersect(x0, y0, x1, y1, xr, yt, xr, yb):
	    return (x1, y1, xr, interpy_l(x0, y0, x1, y1, xr))
	elif intersect(x0, y0, x1, y1, xr, yt, xl, yt):
	    return (x1, y1, interpx_l(x0, y0, x1, y1, yt), yt)
	elif intersect(x0, y0, x1, y1, xr, yb, xl, yb):
	    return (x1, y1, interpx_l(x0, y0, x1, y1, yb), yb)
    else:
	inters = []
	if intersect(x0, y0, x1, y1, xl, yt, xl, yb):
	    inters.append((xl, interpy_l(x0, y0, x1, y1, xl)))
	if intersect(x0, y0, x1, y1, xr, yt, xr, yb):
	    inters.append((xr, interpy_l(x0, y0, x1, y1, xr)))
	if intersect(x0, y0, x1, y1, xr, yt, xl, yt):
	    inters.append((interpx_l(x0, y0, x1, y1, yt), yt))
	if intersect(x0, y0, x1, y1, xr, yb, xl, yb):
	    inters.append((interpx_l(x0, y0, x1, y1, yb), yb))

	if len(inters):
	    return (inters[0][0], inters[0][1], inters[1][0], inters[1][1])
	else:
	    raise Nodraw()
		  

##############################################################################






class point:
    def __init__(self, (lab, x, y)):
	self.lab = lab
	self.x=x
	self.y=y

##############################################################################



class line:
    def __init__(self, (p1, p2)):
	self.p1=p1
	self.p2=p2

##############################################################################

def draw_all():
    
    for s in sides:
	LINE(c, s)
	
	for l in lines:
	    LINE(c, l)

##############################################################################


def mouse_1_down(event):

    for s in sides:
	LINE(c, s)
	    
    for l in lines:
	try:
	    x1, y1, x2, y2 = endpoints(l.p1.x, l.p1.y, l.p2.x, l.p2.y, [boxl, boxr, boxt, boxb])
	    c.create_line(x1, y1, x2, y2, fill='red', tag='bound')
	except Nodraw:
	    pass

##############################################################################


def mouse_2_down(event):

    root.destroy()

##############################################################################


def mouse_3_down(event):

    c.delete('bound')

##############################################################################


boxl = 100
boxr = 200
boxt = 100
boxb = 200

vertices = []

ver = [('A',boxl,boxt),
       ('B',boxr,boxt),
       ('C',boxr,boxb),
       ('D',boxl,boxb),]

for v in ver:
    vertices.append(point(v))

C=point(('C',200,200))
D=point(('D',100,200))
E=point(('E',50,75))
F=point(('F', 50,250))
G=point(('G',150,75))
H=point(('H',150, 250))
I=point(('I',50,50))
J=point(('J',250,50))
K=point(('K',125,125))
L=point(('L',150, 50))
M=point(('M',50, 125))
N=point(('N',225,150))
O=point(('O',175, 125))
P=point(('P',125,175))
Q=point(('Q',100, 150))
R=point(('R',100,275))
S=point(('S',200,125))
T=point(('T',200,175))

## ends = []

## for e in en:
##     ends.append(point(e))
	  

sides = []
sides.append(line((vertices[0], vertices[1])))
sides.append(line((vertices[1], vertices[2])))
sides.append(line((vertices[2], vertices[3])))
sides.append(line((vertices[3], vertices[0])))

lines = []
lines.append(line((E,F)))
lines.append(line((G,H)))
lines.append(line((I,J)))
lines.append(line((M,J)))
lines.append(line((M,N)))
lines.append(line((F,K)))
lines.append(line((O,P)))
lines.append(line((P,G)))
lines.append(line((P,H)))
lines.append(line((O,G)))
lines.append(line((Q,R)))
lines.append(line((T,S)))

root = Tk()
root.geometry('400x400')
c = Canvas(root)
c.pack(fill=BOTH, expand = 1)
c.configure(bg='black')

Widget.bind(c, "<1>", mouse_1_down)
Widget.bind(c, "<3>", mouse_3_down)
Widget.bind(c, "<2>", mouse_2_down)

draw_all()

print 'mouse 1 to draw bound lines, mouse 3 to clear, mouse2 to exit....'

    
root.mainloop()
