ソースコード
現状のソースコードです。どこまで作ったのか今やわかりませんが。
- # -*- coding: utf-8 -*-
- # 線画作成ツール
- # Work check : Python3.8
- # Update : 2022/2/11
-
- import tkinter as tk
- import tkinter.filedialog as fd
- import math
- import os
- import pickle
-
- debug=False
-
- class Mat(object):
- debug=False
- def __init__(self,lst=None,shape=None):
- debug=self.debug
- if lst and shape :
- if debug :print("*1")
- r,c=shape
- if len(lst)!= r*c: raise "shape not match"
- self.lst=lst[:]
- self.shape=shape[:]
- elif not lst and shape :
- if debug :print("*2")
- r,c=shape
- self.lst=list(range(r*c))
-
- if debug :print("%s (%s,%s)"%(self.lst,r,c))
- self.shape=shape[:]
- elif lst and not shape :
- if debug :print("*3")
-
- self.shape=(len(lst),1)
- self.lst=lst[:]
- else :
- if debug :print("*4")
- self.lst=[]
- self.shape=[0,0]
- self.rows,self.cols=self.shape
- def __eq__(self,b):
- try :
- return self.shape==b.shape and self.lst==b.lst
- except :
- return False
-
- def reshape( self,*shape):
- #print "@reshape"
- if not shape : raise "reshape error"
- c=self.copy()
- rows,cols=self.shape
- l=rows*cols
- if l!=len(self.lst) : raise "shape not match"
- c.shape=shape[:]
- return c
- def append(self,x):
- if not len(x) != self.cols :
- raise "cols not match"
- self.lst.append(x)
- self.rows+=1
- self.shape=(self.rows,self.cols)
- def copy(self):
- return Mat(self.lst[:],self.shape[:])
- def __iter__(self):
- return iter(self.lst)
- def __getitem__(self,idx):
- if type(idx)==int :
- #print "*"
- r=idx
- return Mat([self.lst[r*self.cols+c] for c in range(self.cols)])
- else :
- r,c=idx
- return self.lst[r*self.cols+c]
- def _calc(self,b,fnc):
- a=self
- t=type(b)
- if t==int or t==float :
- c=Mat(shape=self.shape)
-
- for i in range(a.rows):
- for j in range(a.cols):
- c[i,j]=fnc(a[i,j],b)
- return c
- elif not isinstance(b,Mat):
- raise "add : type missmatch"
- if a.shape!=b.shape :
- raise "add : shape not match"
- c=Mat(shape=a.shape)
- for i in range(a.rows):
- for j in range(a.cols):
- c[i,j]=fnc(a[i,j],b[i,j])
- return c
- def __add__(self,b):
- return self._calc(b,lambda x,y : x+y)
- def __sub__(self,b):
- return self._calc(b,lambda x,y : x-y)
- def __mul__(self,b):
- return self._calc(b,lambda x,y : x*y)
- def __div__(self,b):
- return self._calc(b,lambda x,y : x/y)
-
- def dot(self,b):
- return dot(self,b)
-
- def __setitem__(self,idx,val):
- r,c=idx
- self.lst[r*self.cols+c]=val
- def __repr__(self):
- return repr(self.lst)
-
- def __len__(self):
- return len(self.lst)
- def _set_shape(self,sh):
- self.rows,self.cols=sh
- def _get_shape(self):
- return self.rows,self.cols
-
- Mat.shape=property(Mat._get_shape,Mat._set_shape)
-
- def dot(a,b):
- rows_b,cols_b=b.shape
- rows_a,cols_a=a.shape
- if cols_a!=rows_b : raise "shape not match"
- cols_c=cols_b
- rows_c=rows_a
- c=Mat(shape=(rows_c,cols_c))
- for i in range(cols_b):
-
- for j in range(rows_a):
- v=0
- for u in range(cols_a):
- v_=a[j,u]*b[u,i]
- s=""
- s+= "a%s%s (%s)"%(j,u,a[j,u])
- s+= "* b %s%s (%s)"%(u,i,b[u,i])
- s+= "=(%s)"%(v_)
- if debug:
- print(s, end=' ')
- v+=v_
- c[j,i]=v
- if debug:
- print("= %s "%v)
- if debug: print()
- if debug: print(c)
- return c
-
- array=Mat
-
- H= [2,-2,1,1,
- -3,3,-2,-1,
- 0,0,1,0,
- 1,0,0,0]
-
- H=array(H)
- H=H.reshape(4,4)
-
- def spline( plist,step=4,smooth=0.5 ):
-
- loop= plist[:2]==plist[-2:]
-
- plist=array(plist)
- l=len(plist)
- plist=plist.reshape(l//2,2)
- points,dm=plist.shape
- plist_=plist
- pl=plist
- p0 =plist[0]
-
- fstep=float(step+1)
- tlist=[]
- for tt in range(step+2):
-
- t=tt/fstep
- a=array([t**3.,t**2.,t,1.])
- a=a.reshape(1,4)
- tlist.append(dot(a,H))
- tstart=0
- for i in range(points-1) :
- if i==0 :
- if loop:
-
- v1=(plist[1]-plist[-2])*smooth
- else :
- v=(plist[1]-plist[0])
- v1=v*smooth
-
- else :
- v1=(plist[i+1]-plist[i-1])*smooth
- if i==points-2 :
- if loop:
-
- v2=(plist[1]-plist[-2])*smooth
- else :
- v2=(plist[-1]-plist[-2])*smooth
-
- else :
- v2=(plist[i+2]-plist[i])*smooth
- p1=list(plist[i])
- p2=list(plist[i+1])
- v1=list(v1)
- v2=list(v2)
- for t in tlist[tstart:]:
- G=array( p1+p2+v1+v2)
- G=G.reshape(4,2)
- P=dot(t,G)
- #print t.shape,G.shape,P.shape
- #print t,G,P
- yield [x for x in P]
-
- tstart=1
-
- class Curve:
- canvas = tk.Canvas
- def __init__(self,anc_list):
- self.anc_list = anc_list
- return
-
- def get_bezier(self,interval=10):
- ls = []
- for a in self.anc_list:
- ls.append([a.x,a.y,a.width])
- ls = self._divide_point(ls)
- b_ls = ls[1]
- t_ls = ls[0]
- t_ls.reverse()
- b_ls = self._change_to_bezier_point(b_ls)
- t_ls = self._change_to_bezier_point(t_ls)
- steps = self._calculate_steps(b_ls,interval)
- """ testing round edge
- b_start_x = b_ls[0][0][0]
- b_start_y = b_ls[0][0][1]
- b_end_x = b_ls[-1][-1][0]
- b_end_y = b_ls[-1][-1][1]
- t_start_x = t_ls[0][0][0]
- t_start_y = t_ls[0][0][1]
- t_end_x = t_ls[-1][-1][0]
- t_end_y = t_ls[-1][-1][1]
- #end_edge = _round_edge_point(b_end_x,b_end_y,t_start_x,t_start_y)
- #start_edge= _round_edge_point(t_end_x,t_end_y,b_start_x,b_start_y)
- """
- b_ls = self._calculate_point(b_ls,steps)
- steps.reverse()
- t_ls = self._calculate_point(t_ls,steps)
-
- #pointList = start_edge+ls[0]+end_edge+ls[1]
- pointList = b_ls+t_ls
- #print pointList
- return pointList
-
- def get_spline(self):
- ls = []
- for a in self.anc_list:
- ls.append([a.x,a.y,a.width])
- ls = self._divide_point(ls)
- b_ls = ls[1]
- t_ls = ls[0]
- t_ls.reverse()
- plist = []
- r = [b_ls,t_ls]
- for pl in r:
- ls = []
- for x,y in pl:
- ls.append(x)
- ls.append(y)
- ls = spline(ls,10)
- p = []
- for x,y in ls:
- p.append(x)
- p.append(y)
- plist = plist+p
- return plist
-
- def _divide_point(self,ls):
- """
- argument anc_list and devide pointlist to
- top pointlist and bottom pointlist
- """
- top_p_ls = []
- bottom_p_ls = []
- for i in range(0,len(ls)):
- #degree d
- if i == 0:
- a1 = ls[i]
- a2 = ls[i+1]
- x = a2[0]-a1[0]
- y = a2[1]-a1[1]
- d=math.acos(x/math.sqrt(x*x+y*y))
- if a2[1] < a1[1]:
- d = math.pi+math.pi-d
- d = d + 90/math.pi/2
-
- elif i == len(ls)-1:
- a0 = ls[i-1]
- a1 = ls[i]
- x = a1[0]-a0[0]
- y = a1[1]-a0[1]
- d=math.acos(x/math.sqrt(x*x+y*y))
- if a1[1] < a0[1]:
- d = math.pi+math.pi-d
- d = d + 90/math.pi/2
-
- else:
- a0 = ls[i-1]
- a1 = ls[i]
- a2 = ls[i+1]
- x1 = a0[0]-a1[0]
- y1 = a0[1]-a1[1]
- x2 = a2[0]-a1[0]
- y2 = a2[1]-a1[1]
- d1 = math.acos(x1/math.sqrt(x1*x1+y1*y1))
- d2 = math.acos(x2/math.sqrt(x2*x2+y2*y2))
-
- if a0[1] < a1[1]:
- d1 = math.pi + math.pi-d1
- if a2[1] < a1[1]:
- d2 = math.pi + math.pi-d2
- #print "d1="+str(d1)+" "+"d2="+str(d2)
- if d1<d2:
- d = (d1+d2)/2 + math.pi
- else:
- d = (d1+d2)/2
- #point
- a = ls[i]
- px = a[2] * math.cos(d)
- py = a[2] * math.sin(d)
- a_t = [a[0]-px,a[1]-py]
- top_p_ls.append(a_t)
- a_b = [a[0]+px,a[1]+py]
- bottom_p_ls.append(a_b)
-
- return [top_p_ls,bottom_p_ls]
-
- def _change_to_bezier_point(self,anc_point_list):
- """
- argument point_list by create with width_point
- return point_list of bezier contorol point
- [[first,second,third,fourth],...]
- """
- ls = anc_point_list
- if len(ls) < 2:
- return False
- num = len(ls)-1
- last = len(ls)-2
- bezier_point_list = []
- for i in range(1,num):
- point = []
- #first point
- if i == 1:
- p = [ls[i-1][0],ls[i-1][1]]
- else:
- px = (ls[i-1][0] + ls[i][0])/2
- py = (ls[i-1][1] + ls[i][1])/2
- p = [px,py]
- point.append(p)
-
- #second point
- if i == 1:
- px = (ls[i-1][0] + ls[i][0])/2
- py = (ls[i-1][1] + ls[i][1])/2
- p = [px,py]
- else:
- px = ls[i-1][0]*1/4 + ls[i][0]*3/4
- py = ls[i-1][1]*1/4 + ls[i][1]*3/4
- p = [px,py]
- point.append(p)
-
- #third point
- if i == num-1:
- px = (ls[i][0] + ls[i+1][0])/2
- py = (ls[i][1] + ls[i+1][1])/2
- p = [px,py]
- else:
- px = ls[i][0]*3/4 + ls[i+1][0]*1/4
- py = ls[i][1]*3/4 + ls[i+1][1]*1/4
- p = [px,py]
- point.append(p)
-
- #fourth point
- if i == num-1:
- p = [ls[i+1][0],ls[i+1][1]]
- else:
- px = (ls[i][0] + ls[i+1][0])/2
- py = (ls[i][1] + ls[i+1][1])/2
- p = [px,py]
- point.append(p)
- bezier_point_list.append(point)
-
- #print bezier_point_list
- return bezier_point_list
-
- def _change_to_bezier_point2(self,anc_point_list):
- """
- argument point_list by create with width_point
- return point_list of bezier contorol point
- [[first,second,third,fourth],...]
- """
- ls = anc_point_list
- if len(ls) < 2:
- return False
- num = len(ls)-1
- last = len(ls)-2
- bezier_point_list = []
- for i in range(1,num):
- point = []
- #first point
- p = [ls[i-1][0],ls[i-1][1]]
- point.append(p)
-
-
- #second point
- if i == 1:
- r1 = math.atan2(ls[i+1][1]-ls[i][1],ls[i+1][0]-ls[i][0])
- print("r1: "+str(r1))
- r2 = math.atan2(ls[i][1]-ls[i-1][1],ls[i][0]-ls[i-1][0])
- print("r2: "+str(r2))
- r1 = (r1+r2)/2 + math.pi
- print("r1: "+str(r1))
- r2 = math.atan2(ls[i][1]-ls[i-1][1],ls[i][0]-ls[i-1][0])
- print("r2: "+str(r2))
- r = (r1+r2)/2
- print("r: "+str(r))
- d = math.sqrt((ls[i][0]-ls[i-1][0])**2+(ls[i][1]-ls[i-1][0])**2)
- d = d/2
- print("--------")
- else:
- r1 = math.atan2(ls[i+1][1]-ls[i][1],ls[i+1][0]-ls[i][0])
- r2 = math.atan2(ls[i][1]-ls[i-1][1],ls[i][0]-ls[i-1][0])
- r = (r1+r2)/2 + math.pi
- d = math.sqrt((ls[i][0]-ls[i-1][0])**2+(ls[i][1]-ls[i-1][0])**2)
- d = d/4
- px = ls[i][0] + d * math.cos(r)
- py = ls[i][1] + d * math.sin(r)
- p = [px,py]
- point.append(p)
- self.canvas.create_oval(px-2,py-2,px+2,py+2,fill="green")
-
- #third point
- if i == last:
- r1 = math.atan2(ls[i-2][1]-ls[i+1][1],ls[i-2][0]-ls[i+1][0])
- r2 = math.atan2(ls[i][1]-ls[i-1][1],ls[i][0]-ls[i-1][0])
- r1 = (r1+r2)/2-math.pi
- r2 = math.atan2(ls[i-1][1]-ls[i][1],ls[i-1][0]-ls[i][0])
- r = (r1+r2)/2
- d = math.sqrt((ls[i+1][0]-ls[i][0])**2+(ls[i+1][1]-ls[i][0])**2)
- d = d/2
- px = ls[i][0] + d * math.cos(r)
- py = ls[i][1] + d * math.sin(r)
- p = [px,py]
- else:
- r1 = math.atan2(ls[i+1][1]-ls[i][1],ls[i+1][0]-ls[i][0])
- r2 = math.atan2(ls[i-1][1]-ls[i][1],ls[i-1][0]-ls[i][0])
- r = (r1+r2)/2
- d = math.sqrt((ls[i+1][0]-ls[i][0])**2+(ls[i+1][1]-ls[i][0])**2)
- d = d/4
- px = ls[i][0] + d * math.cos(r)
- py = ls[i][1] + d * math.sin(r)
- p = [px,py]
- point.append(p)
- self.canvas.create_oval(px-2,py-2,px+2,py+2,fill="red")
-
- #fourth point
- p = [ls[i+1][0],ls[i+1][1]]
- point.append(p)
-
- bezier_point_list.append(point)
-
- #print bezier_point_list
- return bezier_point_list
- return
-
- def _calculate_steps(self,bezier_point_list,interval=5):
- """
- calculate step num from distance of anc_list
- return list of that
- """
- on_point_list = []
- for p in bezier_point_list:
- on_point_list.append([p[0],p[3]])
-
- step_list = []
- for p in on_point_list:
- sx = p[0][0]
- sy = p[0][1]
- ex = p[1][0]
- ey = p[1][1]
- distance = math.sqrt((ex-sx)**2+(ey-sy)**2)
- step = int(distance/interval)
- if step < 1:
- step = 1
- step_list.append(step)
- return step_list
-
- def _calculate_point(self,bezier_point_list,steps=15):
- """Using calculate_bezier within point_list"""
- n = 0
- ls = []
- for point in bezier_point_list:
- px = [point[0][0],point[1][0],point[2][0],point[3][0]]
- py = [point[0][1],point[1][1],point[2][1],point[3][1]]
- px = self.__calculate_bezier(px,steps[n])
- py = self.__calculate_bezier(py,steps[n])
- n += 1
- ll = []
- for j in range(len(px)-1):
- tl = [px[j],py[j],px[j+1],py[j+1]]
- ll= ll + tl
- ls = ls + ll
- return ls
-
- def __calculate_bezier(self,p, steps = 15):
- """
- Calculate a bezier curve from 4 control points and return a
- list of the resulting points.
-
- The function uses the forward differencing algorithm described here:
- http://www.niksula.cs.hut.fi/~hkankaan/Homepages/bezierfast.html
- """
- t = 1.0 / steps
- temp = t*t
-
- f = p[0]
- fd = 3 * (p[1] - p[0]) * t
- fdd_per_2 = 3 * (p[0] - 2 * p[1] + p[2]) * temp
- fddd_per_2 = 3 * (3 * (p[1] - p[2]) + p[3] - p[0]) * temp * t
-
- fddd = fddd_per_2 + fddd_per_2
- fdd = fdd_per_2 + fdd_per_2
- fddd_per_6 = fddd_per_2 * (1.0 / 3)
-
- points = []
- for x in range(steps):
- points.append(f)
- f = f + fd + fdd_per_2 + fddd_per_6
- fd = fd + fdd + fddd_per_2
- fdd = fdd + fddd
- fdd_per_2 = fdd_per_2 + fddd_per_2
- points.append(f)
- return points
-
- def _round_edge_point(self,x1,y1,x2,y2,steps=5):
- cx = (x1+x2)/2
- cy = (y1+y2)/2
- radian = math.atan2((y2-y1),(x2-x1))
- radius = math.sqrt((x2-cx)**2+(y2-cy)**2)
- d = math.pi/2/steps
- ls = []
- for i in range(1,steps+1):
- if d >0:
- x = cx + radius*math.cos(radian+d*i)
- y = cy + radius*math.sin(radian+d*i)
- else:
- x = cx + radius*math.cos(radian-d*i)
- y = cy + radius*math.sin(radian-d*i)
- x = cx + radius*math.cos(radian+d*i)
- y = cy + radius*math.sin(radian+d*i)
- ls.append(x)
- ls.append(y)
- print(ls)
- return ls
-
- class BaseMethod():
-
- def _set_base_var(self):
- #coord
- self.mx = None #set by _set_mouse_coord()
- self.my = None
- self.sx = None #set by _set_start_coord()
- self.sy = None
- self.cx = None #set by _set_center_coord()
- self.cy = None
- #put selectingObj & Anc
- self.selecting_objs = []
- self.selecting_ancs = []
- self.editing_objs = []
- self.editing_ancs = []
- self.undo_list = []
- self.msg = tk.StringVar() #set by _set_message()
-
- def _save_init_info(self):
- self.init = []
- for a in self.selecting_ancs:
- ls = [a.x,a.y,a.width]
- self.init.append(ls)
-
- def _load_init_info(self):
- n = 0
- for a in self.selecting_ancs:
- [a.x,a.y,a.width] = self.init[n]
- n += 1
-
- def _draw_criterion_line(self):
- x = self.mx
- y = self.my
- width = self.canvas.winfo_width()
- height = self.canvas.winfo_height()
- tag = "Border"
- self.canvas.delete(tag)
- self.canvas.create_line(0,y,width,y,width=1,tags=tag,
- fill="black",stipple="gray50")
- self.canvas.create_line(x,0,x,height,width=1,tags=tag,
- fill="black",stipple="gray50")
- return
-
- def _draw_adjusting_line(self):
- tag = "Border"
- self.canvas.delete(tag)
- self.canvas.create_line(self.cx,self.cy,self.mx,self.my,
- tags=tag,stipple="gray50",width=1)
-
- def _draw_selecting_border(self):
- tag = "Border"
- self.canvas.delete(tag)
- self.canvas.create_rectangle(self.sx,self.sy,self.mx,self.my,
- fill="",width=1,stipple="gray50",
- tags=tag)
-
-
- def _set_center_coord(self,anc_list):
- if len(anc_list) < 1:
- return False
- if self.mode == "ObjMode":
- a = anc_list[0]
- [max_x,min_x,max_y,min_y] = [a.x,a.x,a.y,a.y]
- for a in anc_list:
- if max_x < a.x: max_x=a.x
- if min_x > a.x: min_x=a.x
- if max_y < a.y: max_y=a.y
- if min_y > a.y: min_y=a.y
- #print [max_x,min_x,max_y,min_y]
- self.cx = (max_x+min_x)/2
- self.cy = (max_y+min_y)/2
- return True
- else:
- [x,y,c] = [0,0,0]
- for a in anc_list:
- x += a.x
- y += a.y
- c += 1
- self.cx = x/c
- self.cy = y/c
- return True
-
- def _set_start_coord(self,event):
- for o in self.obj_list:
- for a in o.anc_list:
- [a.sx,a.sy] = [event.x,event.y]
-
- def _set_mouse_coord(self,event):
- self.mx = event.x
- self.my = event.y
-
- def _set_selecting_items(self):
- self.selecting_objs = []
- self.selecting_ancs = []
-
- if self.mode == "ObjMode":
- for o in self.obj_list:
- if o.selected:
- self.selecting_objs.append(o)
- for a in o.anc_list:
- self.selecting_ancs.append(a)
- return
-
- if self.mode == "EditMode":
- for o in self.editing_objs:
- self.selecting_objs.append(o)
- for a in o.anc_list:
- if a.selected:
- self.selecting_ancs.append(a)
- return
-
- def _set_editing_item(self):
- self.editing_objs = []
- self.editing_ancs = []
- if self.mode == "ObjMode":
- for o in self.obj_list:
- self.editing_objs.append(o)
- for a in o.anc_list:
- self.editing_ancs.append(a)
- return
-
- if self.mode == "EditMode":
- for o in self.obj_list:
- if o.editable:
- self.editing_objs.append(o)
- for a in o.anc_list:
- self.editing_ancs.append(a)
- return
-
- def _set_message(self,msg):
- self.msg.set(msg)
- #print self.msg.get()
-
-
- class ObjMethod(BaseMethod):
-
- def _set_obj_var(self):
- return
-
- def select_one_obj(self,event=None):
- for o in self.selecting_objs:
- o.deselect()
- if self.is_under_image:
- self.canvas.delete("under")
- id = self.canvas.find_closest(self.mx,self.my)
- id = id[0]
- for o in self.editing_objs:
- if o.id == id:
- o.select()
- msg = "selected! "+o.tag
- self._set_message(msg)
- if self.is_under_image:
- self._view_under_image()
- self._set_selecting_items()
-
- def select_some_obj(self,event=None):
- if self.is_under_image:
- self.canvas.delete("under")
- id = self.canvas.find_closest(self.mx,self.my)
- id = id[0]
- for o in self.editing_objs:
- if o.id == id:
- o.select_switch()
- if self.is_under_image:
- self.under_image()
- self._set_selecting_items()
-
- def create(self,event=None):
- #deselect all
- for o in self.obj_list:
- o.deselect()
- #create obj
- obj = DrawingObject()
- #print self.line_type.get()
- if self.line_type.get() == "SubLine1":
- obj.color = "#CC3300"
- elif self.line_type.get() == "SubLine2":
- obj.color = "#0033CC"
- self.obj_list.append(obj)
- self.editing_objs.append(obj)
- self._set_selecting_items()
- #print self.editing_objs
- print("create new object! tag="+str(obj.tag))
- self.change_mode()
- self.add()
-
- def destroy(self):
- newList = []
- for o in self.obj_list:
- if o.selected == False:
- newList.append(o)
- else:
- o.canvas.delete(o.tag)
- self._set_message("delete! "+o.tag)
- del o
- self.obj_list = newList
- self.editing_objs = self.obj_list[:]
- self._set_selecting_items()
-
- def duplicate(self):
-
- count = len(self.selecting_objs)
- #print count
- #del self.editing_objs[:]
- for i in range(count):
- obj = DrawingObject()
- self.obj_list.append(obj)
- new_obj = self.obj_list[-1]
- src_obj = self.selecting_objs[i]
- for a in src_obj.anc_list:
- anc = DrawingAnchor(a.x,a.y)
- anc.width = a.width
- anc.hide()
- new_obj.anc_list.append(anc)
- new_obj.editable = False
- new_obj.selected = True
- new_obj.redraw()
- src_obj.selected = False
- src_obj.redraw()
-
- #self.editing_objs[:] = self.obj_list[:]
- self._set_editing_item()
- self._set_selecting_items()
- self._set_message("duplicate!")
- self.drag()
-
- def _save_obj_undo(self):
- if len(self.undo_list) > 20:
- self.undo_list.pop(0)
- data = []
- for o in self.obj_list:
- data.append(o.get_data())
- self.undo_list.append(data)
- #print data
- return
-
- def _load_obj_undo(self):
- try:
- data = self.undo_list[-1]
- except:
- return False
- i = 0
- for d in data:
- try:
- obj = self.obj_list[i]
- except:
- obj = DrawingObject()
- obj.set_data(d)
- i += 1
- self.undo_list[-1]
- return True
-
-
- class EditMethod(BaseMethod):
-
- def _set_edit_var(self):
- return
-
- def select_one_anc(self,event=None):
- closest_anc = self._find_closest_anc()
- for a in self.editing_ancs:
- if a is closest_anc:
- a.select()
- else:
- a.deselect()
- self._set_selecting_items()
- self._set_message("selected! "+a.tag)
-
- def select_some_anc(self,event=None):
- anc = self._find_closest_anc()
- anc.select_switch()
- self._set_selecting_items()
- self._set_message("selected! "+anc.tag)
-
- def _find_closest_anc(self):
- min_d = float('inf')
- closest_anc = None
- for a in self.editing_ancs:
- d = (a.x-self.mx)**2 +(a.y-self.my)**2
- if d < min_d:
- min_d = d
- closest_anc = a
- if closest_anc is None:
- print('find_closest_anc error')
- return closest_anc
-
- def add(self,event=None):
- #print main.editingObj
- if not len(self.editing_objs) == 1:
- self._set_message("please select only one Obj")
- return False
- for obj in self.editing_objs:
- for anc in obj.anc_list:
- if anc.x == self.mx and anc.y == self.my:
- self._set_message('cannot add same place')
- return False
- anc = DrawingAnchor(self.mx,self.my)
- obj = self.editing_objs[-1]
- #print obj
- anc.show()
- obj.anc_list.append(anc)
- self.editing_ancs.append(anc)
- #print obj.anc_list
- self.redraw()
- self.rebind()
- self._save_edit_undo()
- self._set_message("add anchor! "+str(anc.tag))
-
- def delete(self):
- for o in self.editing_objs:
- new_anc_list = []
- for a in o.anc_list:
- a.hide()
- if a.selected == False:
- new_anc_list.append(a)
- o.anc_list = new_anc_list
-
- del self.editing_ancs[:]
- for o in self.editing_objs:
- for a in o.anc_list:
- if a.selected == False:
- self.editing_ancs.append(a)
-
- self.rebind()
- self._set_message("delete!")
-
- def cut_in(self):
- editObj = self.editing_objs[-1]
-
- for i in range(len(self.editing_ancs)):
- a = self.editing_ancs[i]
- if a.selected == True:
- no=i
- a1 = self.editing_ancs[no]
- a2 = self.editing_ancs[no-1]
- if a2.selected == False:
- self._set_message("please select 2 nearless ancour...")
- return
- anc = DrawingAnchor(0,0)
- anc.x = (a1.x+a2.x)/2
- anc.y = (a1.y+a2.y)/2
- anc.show()
- editObj.anc_list.insert(no,anc)
- self.editing_ancs.insert(no,anc)
- self.redraw()
- self.rebind()
- self._save_edit_undo()
- self._set_message("cut in!")
-
- def reverse(self):
- for o in self.editing_objs:
- o.anc_list.reverse()
- self._save_edit_undo()
- self._set_message("reverse!")
-
- def _save_edit_undo(self):
- for o in self.selecting_objs:
- if len(o.undo_list) > 10:
- o.undo_list.pop(0)
- data = []
- for a in o.anc_list:
- data.append(a.get_data())
- o.undo_list.append(data)
- #print data
- return
-
- def _load_edit_undo(self):
- for o in self.selecting_objs:
- try:
- data = o.undo_list[-1]
- except:
- return False
- i = 0
- for d in data:
- try:
- anc = o.anc_list[i]
- except:
- anc = DrawingAnchor(0,0)
- anc.set_data(d)
- i += 1
- o.undo_list.pop(-1)
- return True
-
- class ViewMethod(BaseMethod):
-
- def _set_view_var(self):
- self.is_under_image = False
-
- def scroll(self,event):
- for o in self.obj_list:
- for a in o.anc_list:
- [a.sx,a.sy] = [event.x,event.y]
- self.unbind()
- self.canvas.bind("<ButtonRelease-2>", self._finish_scroll)
- self.canvas.bind("<B2-Motion>", self._scrolling)
-
- def _scrolling(self,event):
- for o in self.obj_list:
- for a in o.anc_list:
- self.canvas.move(a.tag, event.x-a.sx ,event.y-a.sy)
- a.x = a.x + event.x - a.sx
- a.y = a.y + event.y - a.sy
- a.sx = event.x
- a.sy = event.y
- o.redraw()
-
- def _finish_scroll(self,event):
- self.rebind()
- self.repaint_all()
-
- def zooming(self,event):
- self.cx = self.canvas.winfo_width()/2
- self.cy = self.canvas.winfo_height()/2
- self.value = math.sqrt((self.cx-event.x)**2+(self.cy-event.y)**2)
- radian = []
- distance = []
- for o in self.obj_list:
- for a in o.anc_list:
- dx = a.x-self.cx
- dy = a.y-self.cy
- radian.append(math.atan2(dy,dx))
- distance.append(math.sqrt(dx*dx + dy*dy))
- self.radian = radian
- self.distance = distance
- self.unbind()
- self.unbind()
- self.canvas.bind("<B2-Motion>", self._zooming)
- self.canvas.bind("<ButtonRelease-2>", self.finish_zooming)
-
- def _zooming(self,event):
- value = math.sqrt((self.cx-event.x)**2+(self.cy-event.y)**2)-self.value
- value = value/self.value + 1.0
- radian = self.radian
- d = self.distance
- n = 0
- for o in self.obj_list:
- for a in o.anc_list:
- a.x = self.cx + value * d[n] * math.cos(radian[n])
- a.y = self.cy + value * d[n] * math.sin(radian[n])
- print(round(value,3))
- n += 1
- o.redraw()
- return
-
- def _finish_zooming(self,event):
- self.rebind()
-
- def zoom(self,event): #By MouseWheel
- self.cx = self.canvas.winfo_width()/2
- self.cy = self.canvas.winfo_height()/2
- #print event.delta/100.0
- if event.delta>0:
- value = event.delta/100.0
- else:
- value = 2.0 + event.delta/100.0
- if value < 0:
- value = 0.2
- print(value)
- for o in self.obj_list:
- for a in o.anc_list:
- dx = a.x-self.cx
- dy = a.y-self.cy
- r = math.atan2(dy,dx)
- d = math.sqrt(dx*dx + dy*dy)
- a.x = self.cx + value * d * math.cos(r)
- a.y = self.cy + value * d * math.sin(r)
- o.redraw()
- if self.is_under_image:
- self.canvas.scale(self.test,self.cx,self.cy,100,100)
- return
-
- def turn_over(self):
- width = self.canvas.winfo_width()
- for o in self.obj_list:
- for a in o.anc_list:
- a.x = width-a.x
- o.redraw()
- self._set_message("trun over!")
-
- def view_all(self):
- #find max&min
- canvas_width = self.canvas.winfo_width()
- canvas_height= self.canvas.winfo_height()
- a = self.editing_ancs[0]
- [min_x,min_y,max_x,max_y] = [a.x,a.y,a.x,a.y]
- for a in self.editing_ancs:
- if a.x < min_x:
- min_x = a.x
- if a.x > max_x:
- max_x = a.x
- if a.y < min_y:
- min_y = a.y
- if a.y > max_y:
- max_y = a.y
- self._zoomToRange(max_x,max_y,min_x,min_y,0.9)
- return
-
- def zoom_by_border(self):
- self.unbind()
- self.canvas.bind("<Motion>",self._ready_zoomBB)
- self.canvas.bind("<ButtonPress-1>",self._start_zoomBB)
- self.canvas.bind("<ButtonPress-2>",self.finish)
- self.canvas.bind("<ButtonPress-3>",self._start_zoomBB)
- self._draw_criterion_line()
-
- def _ready_zoomBB(self,event):
- self._set_mouse_coord(event)
- self._draw_criterion_line()
-
- def _start_zoomBB(self,event):
- self.sx = event.x
- self.sy = event.y
- self.unbind()
- self.canvas.bind("<B1-Motion>",self._bordering)
- self.canvas.bind("<B2-Motion>",self._bordering)
- self.canvas.bind("<B3-Motion>",self._bordering)
- self.canvas.bind("<ButtonRelease-1>",self.finish_zoomBB)
- self.canvas.bind("<ButtonRelease-2>",self.finish_zoomBB)
- self.canvas.bind("<ButtonRelease-3>",self.finish_zoomBB)
-
- def finish_zoomBB(self,event):
- self.canvas.delete("Border")
- self._zoomToRange(self.sx,self.sy,event.x,event.y)
- self.rebind()
- return
-
- def _zoomToRange(self,x1,y1,x2,y2,rate_rev=1):
- canvas_width = self.canvas.winfo_width()
- canvas_height= self.canvas.winfo_height()
- if x1 > x2:
- max_x = x1
- min_x = x2
- else:
- max_x = x2
- min_x = x1
- if y1 > y2:
- max_y = y1
- min_y = y2
- else:
- max_y = y2
- min_y = y1
- #value of revise to center
- canvas_center = [canvas_width/2,
- canvas_height/2]
- draw_center = [(max_x+min_x)/2,
- (max_y+min_y)/2]
- revise_value = [canvas_center[0]-draw_center[0],
- canvas_center[1]-draw_center[1]]
- #calucurate value of revise scale
- rate_x = float(canvas_width / (max_x-min_x))
- rate_y = float(canvas_height/ (max_y-min_y))
- if rate_x<rate_y:
- rate = rate_x
- else:
- rate = rate_y
- rate = rate * rate_rev
- print(rate)
- for o in self.obj_list:
- for a in o.anc_list:
- #revise coord
- a.x = a.x+revise_value[0]
- a.y = a.y+revise_value[1]
- #revise scale
- dx = a.x-canvas_center[0]
- dy = a.y-canvas_center[1]
- radian = math.atan2(dy,dx)
- distance = math.sqrt(dx*dx + dy*dy)
- a.x = canvas_center[0] + rate * distance * math.cos(radian)
- a.y = canvas_center[1] + rate * distance * math.sin(radian)
- o.redraw()
-
- def under_image(self,event=None):
- if self.is_under_image:
- self.canvas.delete("under")
- self.is_under_image = False
- else:
- self._view_under_image()
- self.is_under_image = True
-
- def _view_under_image(self):
- #x = int(self.canvas.cget('width'))/2
- #y = int(self.canvas.cget('height'))/2
- x = self.canvas.winfo_width()/2
- y = self.canvas.winfo_height()/2
- try:
- self.test=self.canvas.create_image(x,y,image=self.u_img,tags="under")
- except:
- self._set_message("please select image...")
- self.canvas.tag_lower("under")
-
- def select_under_image(self,event=None):
- fTyp=[('GIF;JPG','*.gif;*.jpg;')]
- fname = fd.askopenfilename(filetypes=fTyp)
- self.u_img = tk.PhotoImage(file=fname)
- self._view_under_image()
- self.is_under_image = True
-
- class CommonMethod(ObjMethod,EditMethod):
-
- def _set_com_var(self):
- #flags
- self.showed_subwindow = False
- return
-
- def _ready(self,event):
- self._set_mouse_coord(event)
- self._draw_criterion_line()
-
- def _bordering(self,event):
- self._set_mouse_coord(event)
- self._draw_selecting_border()
-
- def _start(self):
- if len(self.selecting_ancs)==0:
- self._set_message("please select item...")
- return False
- self._set_center_coord(self.selecting_ancs)
- self._save_init_info()
- self.unbind()
- self.canvas.bind("<Button-1>",self.finish)
- self.canvas.bind("<Button-3>",self.cancel)
- return True
-
- def finish(self,event=None):
- self.canvas.delete("Border")
- self._save_undo()
- self.redraw()
- self.rebind()
- self._set_message("done")
-
- def cancel(self,event=None):
- self._load_init_info()
- self.finish(event)
- self._set_message("cancel")
-
- def drag(self):
- if not self._start():
- return
- for a in self.selecting_ancs:
- [a.sx,a.sy] = [self.mx,self.my]
- self.canvas.bind("<Motion>",self._dragging)
-
- def _dragging(self,event):
- self._set_mouse_coord(event)
- for a in self.selecting_ancs:
- self.canvas.move(a.tag,self.mx-a.sx,self.my-a.sy)
- a.x = a.x + self.mx - a.sx
- a.y = a.y + self.my - a.sy
- a.sx = self.mx
- a.sy = self.my
- self.redraw()
- self._set_message("dragging")
-
- def rotate(self):
- if not self._start():
- return
- self.r = math.atan2(self.mx-self.cx,self.my-self.cy)
- radian = []
- distance = []
- for a in self.selecting_ancs:
- dx = a.x-self.cx
- dy = a.y-self.cy
- radian.append(math.atan2(dy,dx))
- distance.append(math.sqrt(dx*dx + dy*dy))
- self.radian = radian
- self.distance = distance
- self.canvas.bind("<Motion>",self._rotating)
- self._draw_adjusting_line()
-
- def _rotating(self,event):
- self._set_mouse_coord(event)
- r = math.atan2(self.mx-self.cx,self.my-self.cy)
- r = self.r-r
- radian = self.radian
- d = self.distance
- n = 0
- for a in self.selecting_ancs:
- a.x = self.cx + d[n] * math.cos(radian[n]+r)
- a.y = self.cy + d[n] * math.sin(radian[n]+r)
- n += 1
- self._draw_adjusting_line()
- self._set_message("rotate "+str(round(math.degrees(r),2)))
- self.redraw()
-
- def resize(self):
- if not self._start():
- return
- self.sx,self.sy = self.mx,self.my
- self.value = math.sqrt((self.cx-self.mx)**2+
- (self.cy-self.my)**2)
- radian = []
- distance = []
- for a in self.selecting_ancs:
- dx = a.x-self.cx
- dy = a.y-self.cy
- radian.append(math.atan2(dy,dx))
- distance.append(math.sqrt(dx*dx + dy*dy))
- self.radian = radian
- self.distance = distance
- self.canvas.bind("<Motion>",self._resizing)
- self._draw_adjusting_line()
-
- def _resizing(self,event):
- self._set_mouse_coord(event)
- value = math.sqrt((self.cx-self.mx)**2+
- (self.cy-self.my)**2)-self.value
- value = value/self.value + 1.0
- radian = self.radian
- d = self.distance
- n = 0
- for a in self.selecting_ancs:
- a.x = self.cx + value * d[n] * math.cos(radian[n])
- a.y = self.cy + value * d[n] * math.sin(radian[n])
- n += 1
- num ='%3.3lf' % value
- self._set_message("resize "+num)
- self._draw_adjusting_line()
- self.redraw()
-
- def rewidth(self):
- if not self._start():
- return
- self.value = math.sqrt((self.cx-self.mx)**2+
- (self.cy-self.my)**2)
- self.width_ls =[]
- for a in self.selecting_ancs:
- a.swidth = a.width
- self.canvas.bind("<Motion>",self._rewidthing)
- self._draw_adjusting_line()
-
- def _rewidthing(self,event):
- self._set_mouse_coord(event)
- value = math.sqrt((self.cx-self.mx)**2+
- (self.cy-self.my)**2)-self.value
- value = value/self.value + 1.0
- n = 0
- for a in self.selecting_ancs:
- a.width = value * a.swidth
- if a.width < 0.1:
- a.width = 0.1
- n += 1
- num ='%03lf' % value
- self._set_message("rewidth "+num)
- self._draw_adjusting_line()
- self.redraw()
-
- def mirror(self):
- self._set_center_coord(self.selecting_ancs)
- self.unbind()
- self.window.bind("<KeyPress>",self._mirrored)
- self._set_message("select axis (x,y)")
-
- def _mirrored(self,event):
- if event.keysym == "x":
- width = self.cx*2
- for a in self.selecting_ancs:
- a.x = width-a.x
- elif event.keysym == "y":
- width = self.cy*2
- for a in self.selecting_ancs:
- a.y = width-a.y
- else:
- return
-
- self.rebind()
- self.redraw()
- self._set_message("mirrored!")
-
- def select_all(self):
- if self.mode == "ObjMode":
- items = self.editing_objs
- elif self.mode == "EditMode":
- items = self.editing_ancs
- flag = True
- for item in items:
- if item.selected:
- flag = False
- if flag:
- for item in items:
- item.select()
- else:
- for item in items:
- item.deselect()
- self._set_selecting_items()
- return
-
- def select_by_border(self):
- self.unbind()
- self.canvas.bind("<Motion>",self._ready)
- self.canvas.bind("<ButtonPress-1>",self._start_selecting)
- self.canvas.bind("<ButtonPress-2>",self.finish)
- self.canvas.bind("<ButtonPress-3>",self._start_selecting)
- self._draw_criterion_line()
- self._set_message("Border select")
-
- def _start_selecting(self,event):
- self.sx = event.x
- self.sy = event.y
- self.unbind()
- self.canvas.bind("<B1-Motion>",self._bordering)
- self.canvas.bind("<B3-Motion>",self._bordering)
- self.canvas.bind("<ButtonRelease-1>",self._select_in_rect)
- self.canvas.bind("<ButtonRelease-2>",self._select_in_rect)
- self.canvas.bind("<ButtonRelease-3>",self._select_in_rect)
-
- def _select_in_rect(self,event):
- n=0
- tag = "Border"
- self.canvas.delete(tag)
- if self.mode == "ObjMode":
- items = self.editing_objs
- s = " Obj"
- elif self.mode == "EditMode":
- items = self.editing_ancs
- s = " Anc"
- ls = self.canvas.find_overlapping(self.sx,self.sy,self.mx,self.my)
- for item in items:
- for id in ls:
- if id == item.id:
- if event.num == 1:
- item.select()
- n+=1
- elif event.num == 2:
- item.deselect()
- elif event.num == 3:
- item.deselect()
- self._set_selecting_items()
- self._set_message("selected! "+str(n)+s)
- self.redraw()
- self.rebind()
- return
-
- def redraw(self):
- if self.mode == "EditMode":
- for o in self.editing_objs:
- o.redraw()
-
- elif self.mode == "ObjMode":
- for o in self.selecting_objs:
- o.redraw()
-
- def repaint_all(self):
- for o in self.obj_list:
- o.redraw()
-
- def show_draw_type_window(self):
- if not self.showed_subwindow:
- import functools
- f = tk.Frame(self.canvas,bg="gray")
- tk.Label(f,text="Draw Type",bg="gray").pack(anchor=tk.NW)
- draw_type = ['Original','Polygon','Spline','Arrow']
- for dt in draw_type:
- b = tk.Button(f,text=dt,relief=tk.FLAT,
- command=functools.partial(self.change_draw_type,dt))
- b.pack(anchor=tk.NW,fill=tk.X,pady=1,padx=2)
- f.pack()
- self.canvas.create_window(self.mx,self.my,window=f,anchor=tk.NW,
- tags="window")
- self.showed_subwindow = True
- self.window_box = (self.mx-10,self.my-10,self.mx+70,self.my+130)
- #self.canvas.create_rectangle(self.window_box)
- self.canvas.bind("<Motion>",self._hide_popup)
-
- def change_draw_type(self,draw_type):
- for o in self.selecting_objs:
- o.change_type(draw_type)
- self.del_popup()
- self.redraw()
- print(draw_type)
-
- def _hide_popup(self,event):
- self._set_mouse_coord(event)
- if (self.window_box[0] > self.mx or
- self.window_box[1] > self.my or
- self.window_box[2] < self.mx or
- self.window_box[3] < self.my):
- self.del_popup()
-
- def del_popup(self):
- self.canvas.delete("window")
- del self.window_box
- self.showed_subwindow = False
- self.canvas.bind("<Motion>",self._set_mouse_coord)
-
- def undo(self):
- flag = False
- if self.mode == "EditMode":
- if self._load_edit_undo():
- flag = True
- elif self.mode == "ObjMode":
- if self._load_obj_undo():
- flag = True
- if flag:
- self._set_editing_item()
- self._set_selecting_items()
- self.redraw()
- self._set_message("undo!")
- else:
- self._set_message("No more step to undo...")
- return
-
- def _save_undo(self):
- if self.mode == "ObjMode":
- self._save_obj_undo()
- elif self.mode == "EditMode":
- self._save_edit_undo
-
- class DrawingMethod(ViewMethod,CommonMethod):
-
- def set_vars(self):
- self._set_base_var()
- self._set_obj_var()
- self._set_edit_var()
- self._set_com_var()
- self._set_view_var()
-
- def change_mode(self,event=None):
- if self.mode == "EditMode":
- self.change_to_obj_mode()
- else:
- self.change_to_edit_mode()
- self._set_selecting_items()
-
- def change_to_obj_mode(self):
- #check
- if len(self.editing_ancs) < 2:
- print("please add Anc more than 2...")
- return False
- #change
- for o in self.editing_objs:
- o.select()
- o.editable = False
- self.editing_ancs = []
- self.editing_objs = []
- for o in self.obj_list:
- self.editing_objs.append(o)
- for a in o.anc_list:
- self.editing_ancs.append(a)
- self.mode = "ObjMode"
- self.redraw()
- self.rebind()
- print("Object Mode!")
- return
-
- def change_to_edit_mode(self):
- #check
- ls = []
- for o in self.selecting_objs:
- o.editable = True
- ls.append(o)
- if len(ls) == 0:
- self._set_message("please select more than one object...")
- return False
- #change
- self.editing_objs = ls
- self.editing_ancs = []
- for o in self.editing_objs:
- for a in o.anc_list:
- self.editing_ancs.append(a)
- self.mode = "EditMode"
- self.rebind()
- self.redraw()
- print("Edit Mode!")
- return
-
- class IOMethod:
-
- def open(self):
- #select file
- fTyp=[('All','*.*;')]
- fname = fd.askopenfilename(filetypes=fTyp)
- fname=open(fname,"rb")
- data=pickle.load(fname)
- fname.close()
- self.obj_list = []
- #clean canvas
- for o in self.obj_list:
- o.select()
- self._set_selecting_items()
- self.destroy()
- ls = self.canvas.find_all()
- for id in ls:
- self.canvas.delete(id)
- del self.obj_list[:]
- del self.editing_ancs[:]
- #open
- for obj_data in data:
- o = DrawingObject()
- o.set_data(obj_data)
- self.obj_list.append(o)
- self.editing_objs.append(o)
- for a in o.anc_list:
- self.editing_ancs.append(a)
- self.repaint_all()
- print("open!",fname)
-
- def save(self):
- fname = fd.asksaveasfilename()
- data = []
- for o in self.obj_list:
- data.append(o.get_data())
- fname=file(fname,"wb")
- pickle.dump(data,fname)
- fname.close()
- print("save!", fname)
-
- def import_(self,event=None):
- #not yet
- pass
-
- def export(self,event=None):
- self._export_raster_img()
-
- def _export_postscript(self):
- self.canvas.postscript(file="output.ps")
-
- def _export_raster_img(self):
- #now testing
- from PIL import Image, ImageDraw
-
- filename = fd.asksaveasfilename()
- #width = int(self.canvas.cget('width'))
- #height = int(self.canvas.cget('height'))
- width = self.canvas.winfo_width()
- height= self.canvas.winfo_height()
- image = Image.new("RGB", (width, height),(255, 255, 255))
- draw = ImageDraw.Draw(image)
- for obj in self.obj_list:
- ls = Curve(obj.anc_list)
- draw.polygon(ls,fill="black")
- try:
- image.save(filename)
- except KeyError:
- filename = filename + ".png"
- image.save(filename)
- finally:
- print("saved!")
- return
-
- class MainCanvas(DrawingMethod,IOMethod):
- #setting data
- window = None
- canvas = None
- mode = "ObjMode"
-
- #property data
- obj_list = []
-
- #editting data
- selecting_ancs = []
- selecting_objs = []
- editing_objs = []
- editing_ancs = []
-
- def __init__(self, window):
- self.window = window
- self.set_vars()
- self.rebind()
-
- def rebind(self):
- self.unbind()
-
- if self.mode == "ObjMode":
- self.canvas.bind("<ButtonPress-1>", self.create)
- self.canvas.bind("<ButtonPress-3>", self.select_one_obj)
- self.canvas.bind("<Shift-ButtonPress-3>", self.select_some_obj)
- elif self.mode == "EditMode":
- self.canvas.bind("<ButtonPress-1>", self.add)
- self.canvas.bind("<ButtonPress-3>", self.select_one_anc)
- self.canvas.bind("<Shift-ButtonPress-3>", self.select_some_anc)
- self.canvas.bind("<B2-Motion>", self.scroll)
- self.canvas.bind("<Motion>",self._set_mouse_coord)
- self.window.bind("<KeyPress>",self.press_key)
- self.window.bind("<Control-KeyPress>",self.press_ctrl_key)
- self.window.bind("<MouseWheel>",self.zoom)
-
- def unbind(self):
- self.canvas.unbind("<ButtonPress-1>")
- self.canvas.unbind("<ButtonPress-2>")
- self.canvas.unbind("<ButtonPress-3>")
- self.canvas.unbind("<B1-Motion>")
- self.canvas.unbind("<B2-Motion>")
- self.canvas.unbind("<B3-Motion>")
- self.canvas.unbind("<ButtonRelease-1>")
- self.canvas.unbind("<ButtonRelease-2>")
- self.canvas.unbind("<ButtonRelease-3>")
- self.window.unbind("<KeyPress>")
- self.window.unbind("<KeyRelease>")
-
- if self.mode == "EditMode":
- for a in self.editing_ancs:
- self.canvas.tag_unbind(a.tag,"<ButtonPress-3>")
-
- def press_key(self,event):
- self._set_start_coord(event)
-
- if event.keysym == "Tab":
- self.change_mode()
- elif event.keysym == "C":
- self.view_all()
- elif event.keysym == "a":
- self.select_all()
- elif event.keysym == "b":
- self.select_by_border()
- elif event.keysym == "g":
- self.drag()
- elif event.keysym == "s":
- self.resize()
- elif event.keysym == "r":
- self.rotate()
- elif event.keysym == "w":
- self.rewidth()
- elif event.keysym == "U":
- self.under_image()
- elif event.keysym == "z":
- self.zoom_by_border()
- elif event.keysym == "m":
- self.mirror()
- elif event.keysym == "d":
- self.show_draw_type_window()
-
- if self.mode == "ObjMode":
-
- if event.keysym == "D":
- self.duplicate()
- elif event.keysym == "h":
- self.turn_over()
- elif event.keysym == "x":
- self.destroy()
-
- elif self.mode == "EditMode":
-
- if event.keysym == "R":
- self.reverse()
- elif event.keysym == "k":
- self.cut_in()
- elif event.keysym == "x":
- self.delete()
-
- self.redraw()
- return
-
- def press_ctrl_key(self,event):
-
- if event.keysym == "e":
- self.export_raster_img()
- elif event.keysym == "o":
- self.open()
- elif event.keysym == "s":
- self.save()
- elif event.keysym == "u":
- self.select_under_image()
- elif event.keysym == "z":
- self.undo()
- return
-
- class DrawingObject:
-
- #setting
- canvas = None
- color = "black"
- select_color= "orange"
-
- #editing data
- selected = True
- editable = True
-
- #property data
- anc_list = []
- undo_list = []
-
- def __init__(self):
- self.tag = "obj_"+str(id(self))
- #have to format
- self.anc_list = []
-
- def __del__(self):
- print("bye",self.tag)
-
- def get_data(self):
- anc_list = []
- for a in self.anc_list:
- anc_data = a.get_data()
- anc_list.append(anc_data)
- return [anc_list,
- self.tag,
- self.selected,
- self.editable]
-
- def set_data(self,data):
- del self.anc_list[:]
- t = [0,0]
- for anc_data in data[0]:
- anc = DrawingAnchor(0,0)
- anc.set_data(anc_data)
- if t[0]==anc.x and t[1]==anc.y:
- print("error "+ anc.tag)
- else:
- self.anc_list.append(anc)
- t = [anc.x,anc.y]
- self.tag = data[1]
- self.selected = data[2]
- self.editable = data[3]
-
- def select_switch(self,event=None):
- if self.selected == True:
- self.deselect()
- else:
- self.select()
-
- def select(self):
- self.selected = True
- self.redraw()
-
- def deselect(self):
- self.editable = False
- self.selected = False
- self.redraw()
-
- def redraw(self):
- self.canvas.delete(self.tag)
- width = self.canvas.winfo_width()
- height = self.canvas.winfo_height()
- min_x,min_y = 9999,9999
- max_x,max_y = 0,0
-
- for a in self.anc_list:
- a.hide()
- if a.x < min_x: min_x = a.x
- if a.x > max_x: max_x = a.x
- if a.y < min_y: min_y = a.y
- if a.y > max_y: max_y = a.y
- if not (a.x < 0 or a.x > width or
- a.y < 0 or a.y > height):
- if self.editable:
- a.redraw()
- if (min_x > width or max_x < 0 or
- min_y > height or max_y < 0):
- return
-
- if self.editable:
- self._draw_line()
- self._draw_curve(self.tag,self.color)
- else:
- if self.selected == True:
- #self._drawHighLight()
- self._draw_curve(self.tag,self.select_color)
- else:
- self._draw_curve(self.tag,self.color)
-
- def change_type(self,draw_type):
- if draw_type == "Original":
- self._draw_curve = self._bezier
- elif draw_type == "Spline":
- self._draw_curve = self._spline
- elif draw_type == "Polygon":
- self._draw_curve = self._polygon
- elif draw_type == "Arrow":
- self._draw_curve = self._arrow
- else:
- self._draw_curve = self._bezier
-
- def _draw_curve(self,tag,color):
- self._bezier(tag,color)
-
- def _draw_line(self):
- if len(self.anc_list) < 2:
- return
- ls = []
- tag = self.tag
- for a in self.anc_list:
- ls.append(a.x)
- ls.append(a.y)
- self.canvas.create_line(ls,fill="red",width=1,tags=tag)
-
- def _spline(self,tag,color):
- if len(self.anc_list) < 2:
- return
- width = self.anc_list[0].width*2
- ls = []
- for a in self.anc_list:
- ls.append(a.x)
- ls.append(a.y)
- id = self.canvas.create_line(ls,width=width,fill=color,
- tags=tag, smooth=True)
- self.id = id
- return
-
- def _bezier(self,tag,color):
- if len(self.anc_list) < 3:
- self._spline(self.tag,color)
- return
- bl = Curve(self.anc_list)
- bl.canvas = self.canvas
- ls = bl.get_spline()
- self.id = self.canvas.create_polygon(ls,fill=color,tags=tag)
- """
- try:
- ls = calcuCurve.get_bezierList(self.anc_list,15)
- id = self.canvas.create_polygon(ls,fill=color,
- tags=tag)
- self.id = id
- except ZeroDivisionError:
- print "ZeroDivisionError... please move anc"
- return
- """
-
- def _polygon(self,tag,color):
- ls = []
- for a in self.anc_list:
- ls.append([a.x,a.y,a.width])
- ls = calcuCurve.width_point(ls)
- #print ls
- ls[1].reverse()
- ls = ls[0]+ls[1]
- lss = []
- for l in ls:
- lss.append(l[0])
- lss.append(l[1])
- self.id = self.canvas.create_polygon(lss,width=0,fill=color,
- tags=tag, smooth=True)
- return
-
- def _arrow(self,tag,color):
- if len(self.anc_list) < 2:
- return
- else:
- width = self.anc_list[0].width*2
- ls = []
- for a in self.anc_list:
- ls.append(a.x)
- ls.append(a.y)
- id = self.canvas.create_line(ls,width=width,fill=color,
- tags=tag, smooth=True,arrow='last')
- self.id = id
-
-
- class DrawingAnchor:
-
- canvas = None
- selected = False
-
- def __init__(self,x,y):
- self.x = x
- self.y = y
- self.sx = x
- self.sy = y
- self.width = 1.0
- self.tag = "anc_"+str(id(self))
- self.stag= self.tag+"_selecting"
-
- def __del__(self):
- print("bye",self.tag)
-
- def get_data(self):
- return [self.x,
- self.y,
- self.width,
- self.tag,
- self.selected]
-
- def set_data(self,data):
- self.x = data[0]
- self.y = data[1]
- self.sx = data[0]
- self.sy = data[1]
- self.width = data[2]
- self.tag = data[3]
- self.stag = self.tag+"_selecting"
- self.selected = data[4]
-
- def select_switch(self):
- if self.selected == True:
- self.deselect()
- else:
- self.select()
-
- def select(self):
- self.selected = True
- self.redraw()
-
- def deselect(self):
- self.selected = False
- self.redraw()
-
- def redraw(self):
- self.hide()
- self.show()
-
- def show(self):
- if self.selected == True:
- self._draw_select()
- self._draw_anc()
-
- def hide(self):
- self.canvas.delete(self.tag)
- self.canvas.delete(self.tag+"_selecting")
-
- def _draw_anc(self):
- fill = "white"
- if self.selected:
- fill = "red"
- id =self.canvas.create_oval(self.x-2,self.y-2,self.x+2,self.y+2,
- outline="red",width=1,
- tags = self.tag,fill=fill)
- self.id = id
-
- def _draw_select(self):
- size = 10
- self.canvas.create_oval(self.x-size,self.y-size,
- self.x+size,self.y+size,
- tags=self.stag,fill="yellow",outline="")
- self.canvas.tag_lower(self.stag)
-
-
- class DrawApp(tk.Tk):
-
- def __init__(self):
- super().__init__()
-
- self.canvas = tk.Canvas(self, bg="white")
- self.canvas.pack(fill=tk.BOTH,expand=True)
- DrawingAnchor.canvas = self.canvas
- DrawingObject.canvas = self.canvas
- Curve.canvas = self.canvas
- MainCanvas.canvas = self.canvas
-
- self.main = MainCanvas(self)
- self.set_gui()
- self.main.msg = self.msg
- self.main.line_type = self.line_type
-
- def set_gui(self):
-
- frame = tk.Frame(self)
- frame.pack(fill=tk.BOTH)
- self.base_menu = tk.Frame(frame)
- self.message_menu = tk.Frame(frame)
-
- #option_menu
- LINES = ["MainLine", "SubLine1", "SubLine2"]
- self.line_type = tk.StringVar()
- self.line_type.set(LINES[0])
- b = tk.OptionMenu(self.base_menu, self.line_type, *LINES)
- b.pack(side=tk.LEFT)
-
- #menu
- file_btn = tk.Menubutton(self.base_menu,text='File')
- menu = tk.Menu(file_btn,tearoff=False)
- menu.add_command(label='Open...',command=self.main.open)
- menu.add_command(label='Save...',command=self.main.save)
- menu.add_command(label='Import', command=self.main.import_)
- menu.add_command(label='Export', command=self.main.export)
- file_btn.configure(menu=menu)
- file_btn.pack(side=tk.LEFT)
-
- view_btn = tk.Menubutton(self.base_menu,text='View')
- menu = tk.Menu(view_btn,tearoff=False)
- menu.add_command(label='Zoom')
- menu.add_command(label='View All')
- menu.add_command(label='Backgraund Image...',
- command=self.main.select_under_image)
- view_btn.configure(menu=menu)
- view_btn.pack(side=tk.LEFT)
-
- option_btn = tk.Menubutton(self.base_menu,text='Option')
- menu = tk.Menu(option_btn,tearoff=False)
- menu.add_command(label='Setting')
- option_btn.configure(menu=menu)
- option_btn.pack(side=tk.LEFT)
-
- #make_message(self):
- self.msg = tk.StringVar()
- m = tk.Label(self.base_menu,textvariable=self.msg,fg='#666666')
- m.pack(side=tk.RIGHT)
-
- self.base_menu.pack(side=tk.LEFT,fill=tk.X)
- self.message_menu.pack_forget()
-
- def main():
- app = DrawApp()
- app.mainloop()
-
-
- if __name__ == '__main__':
- main()
-