#!/usr/bin/env python
import Tix,math,tkFont

class Punkt:
	def __init__(self,x=0,y=0):
		self.x=x
		self.y=y

	def text(self):
		return "[%9.4f,%9.4f]"%(self.x,self.y)

class Appn(Tix.Frame):
	def in_range_angle(self,sw,ew,w):
		if w<0: w+=360
		if sw <= w <= ew: return True
		sw,ew=sw-360,ew-360
		if sw <= w <= ew: return True
		return False
	def in_range_line(self,x1,y1,x2,y2,xr,yr):
		if x1>x2:
			if not(x1 >= xr >= x2): return False
		else:
			if not(x1<=xr<=x2): return False
		if y1>y2:
			if not(y1 >= yr >= y2): return False
		else:
			if not(y1<=yr<=y2):
				return False
		return True
	def search_int(self,x1,y1,x2,y2,xc,yc,r,sw,ew):
		x0=x1;y0=y1
		norm=math.sqrt((x2-x1)**2+(y2-y1)**2)
		if norm:
			f=(x2-x1)/norm
			g=(y2-y1)/norm
			if f<0: f,g=-f,-g
		root=r**2*(f**2+g**2)-(f*(yc-y0)-g*(xc-x0))**2
		i=[]
		if root==0:
			t=(f*(xc-x0)+g*(yc-y0))/(f**2+g**2)
			x=x0+f*t
			y=y0+g*t
			w=math.degrees(math.atan2(200-y,x-200))
			if self.in_range_line(x1,y1,x2,y2,x,y) \
			and self.in_range_angle(sw,ew,w):
				i.append(Punkt(x0+f*t,y0+g*t))
		elif root>0:
			t=(f*(xc-x0)+g*(yc-y0)+math.sqrt(root))/(f**2+g**2)
			x=x0+f*t
			y=y0+g*t
			w=math.degrees(math.atan2(200-y,x-200))
			if self.in_range_line(x1,y1,x2,y2,x,y) \
			and self.in_range_angle(sw,ew,w):
				i.append(Punkt(x0+f*t,y0+g*t))
			t=(f*(xc-x0)+g*(yc-y0)-math.sqrt(root))/(f**2+g**2)
			x=x0+f*t
			y=y0+g*t
			w=math.degrees(math.atan2(200-y,x-200))
			if self.in_range_line(x1,y1,x2,y2,x,y) \
			and self.in_range_angle(sw,ew,w):
				i.append(Punkt(x0+f*t,y0+g*t))
		return i
	def PushPop(self, event, v, b):
		self.move[v]=b
	def MouseMove(self, event):
		if self.move[0]:
			w=math.atan2(event.y-200,event.x-200)
			newposy=math.sin(w)*140+200
			newposx=math.cos(w)*140+200
			self.c.coords('w1',newposx-4,newposy-4,newposx+4,newposy+4)
			self.c.itemconfig('arc',start=-math.degrees(w))
			w2=w-math.radians(float(self.c.itemcget('arc','extent')))
			newposy=math.sin(w2)*140+200
			newposx=math.cos(w2)*140+200
			self.c.coords('w2',newposx-4,newposy-4,newposx+4,newposy+4)
		if self.move[1]:
			w=math.atan2(event.y-200,event.x-200)
			newposy=math.sin(w)*140+200
			newposx=math.cos(w)*140+200
			self.c.coords('w2',newposx-4,newposy-4,newposx+4,newposy+4)
			w=360-(float(self.c.itemcget('arc','start'))-math.degrees(-w))%360
			self.c.itemconfig('arc',extent=w)
		if self.move[2]:
			w=self.c.coords('line')
			w[0]=event.x;w[1]=event.y
			self.c.coords('l1',event.x-4,event.y-4,event.x+4,event.y+4)
			self.c.coords('line',tuple(w))
		if self.move[3]:
			w=self.c.coords('line')
			w[2]=event.x;w[3]=event.y
			self.c.coords('l2',event.x-4,event.y-4,event.x+4,event.y+4)
			self.c.coords('line',tuple(w))

		l=self.c.coords('line')
		sw=float(self.c.itemcget('arc','start'))
		ew=sw+float(self.c.itemcget('arc','extent'))
		w=self.search_int(l[0],l[1],l[2],l[3],200,200,140,sw,ew) #x1,y1,x2,y2,xc,yc,r
		if len(w)==1:
			self.c.itemconfig('c1',state=Tix.NORMAL)
			self.c.coords('c1',w[0].x-4,w[0].y-4,w[0].x+4,w[0].y+4)
			self.c.itemconfig('c2',state=Tix.HIDDEN)
		elif len(w)==2:
			self.c.itemconfig('c1',state=Tix.NORMAL)
			self.c.coords('c1',w[0].x-4,w[0].y-4,w[0].x+4,w[0].y+4)
			self.c.itemconfig('c2',state=Tix.NORMAL)
			self.c.coords('c2',w[1].x-4,w[1].y-4,w[1].x+4,w[1].y+4)
		else:
			self.c.itemconfig('c1',state=Tix.HIDDEN)
			self.c.itemconfig('c2',state=Tix.HIDDEN)

	def __init__(self,master=None):
		Tix.Frame.__init__(self,master)
		self.pack()
		self.c=Tix.Canvas(width=400,height=400,bg="white")

		self.c.create_arc(60,60,340,340,tag='arc',style=Tix.ARC)
		self.c.create_line(200,200,350,50,tag='line',fill="red")

		self.c.create_oval(340-4,200-4,340+4,200+4,fill="green",tag="w1")
		self.c.create_oval(200-4,60-4,200+4,60+4,fill="lightgreen",tag="w2")

		self.c.create_oval(200-4,200-4,200+4,200+4,fill="blue",tag="l1")
		self.c.create_oval(350-4,50-4,350+4,50+4,fill="lightblue",tag="l2")

		self.c.create_oval(299-4,101-4,299+4,101+4,fill="yellow",tag="c1")
		self.c.create_oval(210-4,200-4,210+4,200+4,fill="yellow",tag="c2",state=Tix.HIDDEN)

		self.c.tag_bind('w1', '<ButtonRelease-1>', lambda e,s=self:s.PushPop(e,0,False))
		self.c.tag_bind('w1', '<Button-1>', lambda e,s=self:s.PushPop(e,0,True))
		self.c.bind("<Motion>",self.MouseMove)
		self.c.tag_bind('w2', '<ButtonRelease-1>', lambda e,s=self:s.PushPop(e,1,False))
		self.c.tag_bind('w2', '<Button-1>', lambda e,s=self:s.PushPop(e,1,True))
		self.c.tag_bind('l1', '<ButtonRelease-1>', lambda e,s=self:s.PushPop(e,2,False))
		self.c.tag_bind('l1', '<Button-1>', lambda e,s=self:s.PushPop(e,2,True))
		self.c.tag_bind('l2', '<ButtonRelease-1>', lambda e,s=self:s.PushPop(e,3,False))
		self.c.tag_bind('l2', '<Button-1>', lambda e,s=self:s.PushPop(e,3,True))
		self.c.pack()
		self.move=[False,False,False,False]

root=Tix.Tk()
app=Appn(master=root)
app.master.title("TEST")
app.mainloop()