Pythonで線画ツールを作る

Python/Tkinterで線画ツールを作ります。



ソースコード

現状のソースコードです。どこまで作ったのか今やわかりませんが。

  1. # -*- coding: utf-8 -*-
  2. # 線画作成ツール
  3. # Work check : Python3.8
  4. # Update : 2022/2/11
  5.  
  6. import tkinter as tk
  7. import tkinter.filedialog as fd
  8. import math
  9. import os
  10. import pickle
  11.  
  12. debug=False
  13.  
  14. class Mat(object):
  15. debug=False
  16. def __init__(self,lst=None,shape=None):
  17. debug=self.debug
  18. if lst and shape :
  19. if debug :print("*1")
  20. r,c=shape
  21. if len(lst)!= r*c: raise "shape not match"
  22. self.lst=lst[:]
  23. self.shape=shape[:]
  24. elif not lst and shape :
  25. if debug :print("*2")
  26. r,c=shape
  27. self.lst=list(range(r*c))
  28.  
  29. if debug :print("%s (%s,%s)"%(self.lst,r,c))
  30. self.shape=shape[:]
  31. elif lst and not shape :
  32. if debug :print("*3")
  33.  
  34. self.shape=(len(lst),1)
  35. self.lst=lst[:]
  36. else :
  37. if debug :print("*4")
  38. self.lst=[]
  39. self.shape=[0,0]
  40. self.rows,self.cols=self.shape
  41. def __eq__(self,b):
  42. try :
  43. return self.shape==b.shape and self.lst==b.lst
  44. except :
  45. return False
  46.  
  47. def reshape( self,*shape):
  48. #print "@reshape"
  49. if not shape : raise "reshape error"
  50. c=self.copy()
  51. rows,cols=self.shape
  52. l=rows*cols
  53. if l!=len(self.lst) : raise "shape not match"
  54. c.shape=shape[:]
  55. return c
  56. def append(self,x):
  57. if not len(x) != self.cols :
  58. raise "cols not match"
  59. self.lst.append(x)
  60. self.rows+=1
  61. self.shape=(self.rows,self.cols)
  62. def copy(self):
  63. return Mat(self.lst[:],self.shape[:])
  64. def __iter__(self):
  65. return iter(self.lst)
  66. def __getitem__(self,idx):
  67. if type(idx)==int :
  68. #print "*"
  69. r=idx
  70. return Mat([self.lst[r*self.cols+c] for c in range(self.cols)])
  71. else :
  72. r,c=idx
  73. return self.lst[r*self.cols+c]
  74. def _calc(self,b,fnc):
  75. a=self
  76. t=type(b)
  77. if t==int or t==float :
  78. c=Mat(shape=self.shape)
  79.  
  80. for i in range(a.rows):
  81. for j in range(a.cols):
  82. c[i,j]=fnc(a[i,j],b)
  83. return c
  84. elif not isinstance(b,Mat):
  85. raise "add : type missmatch"
  86. if a.shape!=b.shape :
  87. raise "add : shape not match"
  88. c=Mat(shape=a.shape)
  89. for i in range(a.rows):
  90. for j in range(a.cols):
  91. c[i,j]=fnc(a[i,j],b[i,j])
  92. return c
  93. def __add__(self,b):
  94. return self._calc(b,lambda x,y : x+y)
  95. def __sub__(self,b):
  96. return self._calc(b,lambda x,y : x-y)
  97. def __mul__(self,b):
  98. return self._calc(b,lambda x,y : x*y)
  99. def __div__(self,b):
  100. return self._calc(b,lambda x,y : x/y)
  101.  
  102. def dot(self,b):
  103. return dot(self,b)
  104.  
  105. def __setitem__(self,idx,val):
  106. r,c=idx
  107. self.lst[r*self.cols+c]=val
  108. def __repr__(self):
  109. return repr(self.lst)
  110.  
  111. def __len__(self):
  112. return len(self.lst)
  113. def _set_shape(self,sh):
  114. self.rows,self.cols=sh
  115. def _get_shape(self):
  116. return self.rows,self.cols
  117.  
  118. Mat.shape=property(Mat._get_shape,Mat._set_shape)
  119.  
  120. def dot(a,b):
  121. rows_b,cols_b=b.shape
  122. rows_a,cols_a=a.shape
  123. if cols_a!=rows_b : raise "shape not match"
  124. cols_c=cols_b
  125. rows_c=rows_a
  126. c=Mat(shape=(rows_c,cols_c))
  127. for i in range(cols_b):
  128.  
  129. for j in range(rows_a):
  130. v=0
  131. for u in range(cols_a):
  132. v_=a[j,u]*b[u,i]
  133. s=""
  134. s+= "a%s%s (%s)"%(j,u,a[j,u])
  135. s+= "* b %s%s (%s)"%(u,i,b[u,i])
  136. s+= "=(%s)"%(v_)
  137. if debug:
  138. print(s, end=' ')
  139. v+=v_
  140. c[j,i]=v
  141. if debug:
  142. print("= %s "%v)
  143. if debug: print()
  144. if debug: print(c)
  145. return c
  146.  
  147. array=Mat
  148.  
  149. H= [2,-2,1,1,
  150. -3,3,-2,-1,
  151. 0,0,1,0,
  152. 1,0,0,0]
  153.  
  154. H=array(H)
  155. H=H.reshape(4,4)
  156.  
  157. def spline( plist,step=4,smooth=0.5 ):
  158.  
  159. loop= plist[:2]==plist[-2:]
  160.  
  161. plist=array(plist)
  162. l=len(plist)
  163. plist=plist.reshape(l//2,2)
  164. points,dm=plist.shape
  165. plist_=plist
  166. pl=plist
  167. p0 =plist[0]
  168.  
  169. fstep=float(step+1)
  170. tlist=[]
  171. for tt in range(step+2):
  172.  
  173. t=tt/fstep
  174. a=array([t**3.,t**2.,t,1.])
  175. a=a.reshape(1,4)
  176. tlist.append(dot(a,H))
  177. tstart=0
  178. for i in range(points-1) :
  179. if i==0 :
  180. if loop:
  181.  
  182. v1=(plist[1]-plist[-2])*smooth
  183. else :
  184. v=(plist[1]-plist[0])
  185. v1=v*smooth
  186.  
  187. else :
  188. v1=(plist[i+1]-plist[i-1])*smooth
  189. if i==points-2 :
  190. if loop:
  191.  
  192. v2=(plist[1]-plist[-2])*smooth
  193. else :
  194. v2=(plist[-1]-plist[-2])*smooth
  195.  
  196. else :
  197. v2=(plist[i+2]-plist[i])*smooth
  198. p1=list(plist[i])
  199. p2=list(plist[i+1])
  200. v1=list(v1)
  201. v2=list(v2)
  202. for t in tlist[tstart:]:
  203. G=array( p1+p2+v1+v2)
  204. G=G.reshape(4,2)
  205. P=dot(t,G)
  206. #print t.shape,G.shape,P.shape
  207. #print t,G,P
  208. yield [x for x in P]
  209.  
  210. tstart=1
  211.  
  212. class Curve:
  213. canvas = tk.Canvas
  214. def __init__(self,anc_list):
  215. self.anc_list = anc_list
  216. return
  217.  
  218. def get_bezier(self,interval=10):
  219. ls = []
  220. for a in self.anc_list:
  221. ls.append([a.x,a.y,a.width])
  222. ls = self._divide_point(ls)
  223. b_ls = ls[1]
  224. t_ls = ls[0]
  225. t_ls.reverse()
  226. b_ls = self._change_to_bezier_point(b_ls)
  227. t_ls = self._change_to_bezier_point(t_ls)
  228. steps = self._calculate_steps(b_ls,interval)
  229. """ testing round edge
  230. b_start_x = b_ls[0][0][0]
  231. b_start_y = b_ls[0][0][1]
  232. b_end_x = b_ls[-1][-1][0]
  233. b_end_y = b_ls[-1][-1][1]
  234. t_start_x = t_ls[0][0][0]
  235. t_start_y = t_ls[0][0][1]
  236. t_end_x = t_ls[-1][-1][0]
  237. t_end_y = t_ls[-1][-1][1]
  238. #end_edge = _round_edge_point(b_end_x,b_end_y,t_start_x,t_start_y)
  239. #start_edge= _round_edge_point(t_end_x,t_end_y,b_start_x,b_start_y)
  240. """
  241. b_ls = self._calculate_point(b_ls,steps)
  242. steps.reverse()
  243. t_ls = self._calculate_point(t_ls,steps)
  244.  
  245. #pointList = start_edge+ls[0]+end_edge+ls[1]
  246. pointList = b_ls+t_ls
  247. #print pointList
  248. return pointList
  249.  
  250. def get_spline(self):
  251. ls = []
  252. for a in self.anc_list:
  253. ls.append([a.x,a.y,a.width])
  254. ls = self._divide_point(ls)
  255. b_ls = ls[1]
  256. t_ls = ls[0]
  257. t_ls.reverse()
  258. plist = []
  259. r = [b_ls,t_ls]
  260. for pl in r:
  261. ls = []
  262. for x,y in pl:
  263. ls.append(x)
  264. ls.append(y)
  265. ls = spline(ls,10)
  266. p = []
  267. for x,y in ls:
  268. p.append(x)
  269. p.append(y)
  270. plist = plist+p
  271. return plist
  272.  
  273. def _divide_point(self,ls):
  274. """
  275. argument anc_list and devide pointlist to
  276. top pointlist and bottom pointlist
  277. """
  278. top_p_ls = []
  279. bottom_p_ls = []
  280. for i in range(0,len(ls)):
  281. #degree d
  282. if i == 0:
  283. a1 = ls[i]
  284. a2 = ls[i+1]
  285. x = a2[0]-a1[0]
  286. y = a2[1]-a1[1]
  287. d=math.acos(x/math.sqrt(x*x+y*y))
  288. if a2[1] < a1[1]:
  289. d = math.pi+math.pi-d
  290. d = d + 90/math.pi/2
  291.  
  292. elif i == len(ls)-1:
  293. a0 = ls[i-1]
  294. a1 = ls[i]
  295. x = a1[0]-a0[0]
  296. y = a1[1]-a0[1]
  297. d=math.acos(x/math.sqrt(x*x+y*y))
  298. if a1[1] < a0[1]:
  299. d = math.pi+math.pi-d
  300. d = d + 90/math.pi/2
  301.  
  302. else:
  303. a0 = ls[i-1]
  304. a1 = ls[i]
  305. a2 = ls[i+1]
  306. x1 = a0[0]-a1[0]
  307. y1 = a0[1]-a1[1]
  308. x2 = a2[0]-a1[0]
  309. y2 = a2[1]-a1[1]
  310. d1 = math.acos(x1/math.sqrt(x1*x1+y1*y1))
  311. d2 = math.acos(x2/math.sqrt(x2*x2+y2*y2))
  312.  
  313. if a0[1] < a1[1]:
  314. d1 = math.pi + math.pi-d1
  315. if a2[1] < a1[1]:
  316. d2 = math.pi + math.pi-d2
  317. #print "d1="+str(d1)+" "+"d2="+str(d2)
  318. if d1<d2:
  319. d = (d1+d2)/2 + math.pi
  320. else:
  321. d = (d1+d2)/2
  322. #point
  323. a = ls[i]
  324. px = a[2] * math.cos(d)
  325. py = a[2] * math.sin(d)
  326. a_t = [a[0]-px,a[1]-py]
  327. top_p_ls.append(a_t)
  328. a_b = [a[0]+px,a[1]+py]
  329. bottom_p_ls.append(a_b)
  330.  
  331. return [top_p_ls,bottom_p_ls]
  332.  
  333. def _change_to_bezier_point(self,anc_point_list):
  334. """
  335. argument point_list by create with width_point
  336. return point_list of bezier contorol point
  337. [[first,second,third,fourth],...]
  338. """
  339. ls = anc_point_list
  340. if len(ls) < 2:
  341. return False
  342. num = len(ls)-1
  343. last = len(ls)-2
  344. bezier_point_list = []
  345. for i in range(1,num):
  346. point = []
  347. #first point
  348. if i == 1:
  349. p = [ls[i-1][0],ls[i-1][1]]
  350. else:
  351. px = (ls[i-1][0] + ls[i][0])/2
  352. py = (ls[i-1][1] + ls[i][1])/2
  353. p = [px,py]
  354. point.append(p)
  355.  
  356. #second point
  357. if i == 1:
  358. px = (ls[i-1][0] + ls[i][0])/2
  359. py = (ls[i-1][1] + ls[i][1])/2
  360. p = [px,py]
  361. else:
  362. px = ls[i-1][0]*1/4 + ls[i][0]*3/4
  363. py = ls[i-1][1]*1/4 + ls[i][1]*3/4
  364. p = [px,py]
  365. point.append(p)
  366.  
  367. #third point
  368. if i == num-1:
  369. px = (ls[i][0] + ls[i+1][0])/2
  370. py = (ls[i][1] + ls[i+1][1])/2
  371. p = [px,py]
  372. else:
  373. px = ls[i][0]*3/4 + ls[i+1][0]*1/4
  374. py = ls[i][1]*3/4 + ls[i+1][1]*1/4
  375. p = [px,py]
  376. point.append(p)
  377.  
  378. #fourth point
  379. if i == num-1:
  380. p = [ls[i+1][0],ls[i+1][1]]
  381. else:
  382. px = (ls[i][0] + ls[i+1][0])/2
  383. py = (ls[i][1] + ls[i+1][1])/2
  384. p = [px,py]
  385. point.append(p)
  386. bezier_point_list.append(point)
  387.  
  388. #print bezier_point_list
  389. return bezier_point_list
  390.  
  391. def _change_to_bezier_point2(self,anc_point_list):
  392. """
  393. argument point_list by create with width_point
  394. return point_list of bezier contorol point
  395. [[first,second,third,fourth],...]
  396. """
  397. ls = anc_point_list
  398. if len(ls) < 2:
  399. return False
  400. num = len(ls)-1
  401. last = len(ls)-2
  402. bezier_point_list = []
  403. for i in range(1,num):
  404. point = []
  405. #first point
  406. p = [ls[i-1][0],ls[i-1][1]]
  407. point.append(p)
  408.  
  409.  
  410. #second point
  411. if i == 1:
  412. r1 = math.atan2(ls[i+1][1]-ls[i][1],ls[i+1][0]-ls[i][0])
  413. print("r1: "+str(r1))
  414. r2 = math.atan2(ls[i][1]-ls[i-1][1],ls[i][0]-ls[i-1][0])
  415. print("r2: "+str(r2))
  416. r1 = (r1+r2)/2 + math.pi
  417. print("r1: "+str(r1))
  418. r2 = math.atan2(ls[i][1]-ls[i-1][1],ls[i][0]-ls[i-1][0])
  419. print("r2: "+str(r2))
  420. r = (r1+r2)/2
  421. print("r: "+str(r))
  422. d = math.sqrt((ls[i][0]-ls[i-1][0])**2+(ls[i][1]-ls[i-1][0])**2)
  423. d = d/2
  424. print("--------")
  425. else:
  426. r1 = math.atan2(ls[i+1][1]-ls[i][1],ls[i+1][0]-ls[i][0])
  427. r2 = math.atan2(ls[i][1]-ls[i-1][1],ls[i][0]-ls[i-1][0])
  428. r = (r1+r2)/2 + math.pi
  429. d = math.sqrt((ls[i][0]-ls[i-1][0])**2+(ls[i][1]-ls[i-1][0])**2)
  430. d = d/4
  431. px = ls[i][0] + d * math.cos(r)
  432. py = ls[i][1] + d * math.sin(r)
  433. p = [px,py]
  434. point.append(p)
  435. self.canvas.create_oval(px-2,py-2,px+2,py+2,fill="green")
  436.  
  437. #third point
  438. if i == last:
  439. r1 = math.atan2(ls[i-2][1]-ls[i+1][1],ls[i-2][0]-ls[i+1][0])
  440. r2 = math.atan2(ls[i][1]-ls[i-1][1],ls[i][0]-ls[i-1][0])
  441. r1 = (r1+r2)/2-math.pi
  442. r2 = math.atan2(ls[i-1][1]-ls[i][1],ls[i-1][0]-ls[i][0])
  443. r = (r1+r2)/2
  444. d = math.sqrt((ls[i+1][0]-ls[i][0])**2+(ls[i+1][1]-ls[i][0])**2)
  445. d = d/2
  446. px = ls[i][0] + d * math.cos(r)
  447. py = ls[i][1] + d * math.sin(r)
  448. p = [px,py]
  449. else:
  450. r1 = math.atan2(ls[i+1][1]-ls[i][1],ls[i+1][0]-ls[i][0])
  451. r2 = math.atan2(ls[i-1][1]-ls[i][1],ls[i-1][0]-ls[i][0])
  452. r = (r1+r2)/2
  453. d = math.sqrt((ls[i+1][0]-ls[i][0])**2+(ls[i+1][1]-ls[i][0])**2)
  454. d = d/4
  455. px = ls[i][0] + d * math.cos(r)
  456. py = ls[i][1] + d * math.sin(r)
  457. p = [px,py]
  458. point.append(p)
  459. self.canvas.create_oval(px-2,py-2,px+2,py+2,fill="red")
  460.  
  461. #fourth point
  462. p = [ls[i+1][0],ls[i+1][1]]
  463. point.append(p)
  464.  
  465. bezier_point_list.append(point)
  466.  
  467. #print bezier_point_list
  468. return bezier_point_list
  469. return
  470.  
  471. def _calculate_steps(self,bezier_point_list,interval=5):
  472. """
  473. calculate step num from distance of anc_list
  474. return list of that
  475. """
  476. on_point_list = []
  477. for p in bezier_point_list:
  478. on_point_list.append([p[0],p[3]])
  479.  
  480. step_list = []
  481. for p in on_point_list:
  482. sx = p[0][0]
  483. sy = p[0][1]
  484. ex = p[1][0]
  485. ey = p[1][1]
  486. distance = math.sqrt((ex-sx)**2+(ey-sy)**2)
  487. step = int(distance/interval)
  488. if step < 1:
  489. step = 1
  490. step_list.append(step)
  491. return step_list
  492.  
  493. def _calculate_point(self,bezier_point_list,steps=15):
  494. """Using calculate_bezier within point_list"""
  495. n = 0
  496. ls = []
  497. for point in bezier_point_list:
  498. px = [point[0][0],point[1][0],point[2][0],point[3][0]]
  499. py = [point[0][1],point[1][1],point[2][1],point[3][1]]
  500. px = self.__calculate_bezier(px,steps[n])
  501. py = self.__calculate_bezier(py,steps[n])
  502. n += 1
  503. ll = []
  504. for j in range(len(px)-1):
  505. tl = [px[j],py[j],px[j+1],py[j+1]]
  506. ll= ll + tl
  507. ls = ls + ll
  508. return ls
  509.  
  510. def __calculate_bezier(self,p, steps = 15):
  511. """
  512. Calculate a bezier curve from 4 control points and return a
  513. list of the resulting points.
  514.  
  515. The function uses the forward differencing algorithm described here:
  516. http://www.niksula.cs.hut.fi/~hkankaan/Homepages/bezierfast.html
  517. """
  518. t = 1.0 / steps
  519. temp = t*t
  520.  
  521. f = p[0]
  522. fd = 3 * (p[1] - p[0]) * t
  523. fdd_per_2 = 3 * (p[0] - 2 * p[1] + p[2]) * temp
  524. fddd_per_2 = 3 * (3 * (p[1] - p[2]) + p[3] - p[0]) * temp * t
  525.  
  526. fddd = fddd_per_2 + fddd_per_2
  527. fdd = fdd_per_2 + fdd_per_2
  528. fddd_per_6 = fddd_per_2 * (1.0 / 3)
  529.  
  530. points = []
  531. for x in range(steps):
  532. points.append(f)
  533. f = f + fd + fdd_per_2 + fddd_per_6
  534. fd = fd + fdd + fddd_per_2
  535. fdd = fdd + fddd
  536. fdd_per_2 = fdd_per_2 + fddd_per_2
  537. points.append(f)
  538. return points
  539.  
  540. def _round_edge_point(self,x1,y1,x2,y2,steps=5):
  541. cx = (x1+x2)/2
  542. cy = (y1+y2)/2
  543. radian = math.atan2((y2-y1),(x2-x1))
  544. radius = math.sqrt((x2-cx)**2+(y2-cy)**2)
  545. d = math.pi/2/steps
  546. ls = []
  547. for i in range(1,steps+1):
  548. if d >0:
  549. x = cx + radius*math.cos(radian+d*i)
  550. y = cy + radius*math.sin(radian+d*i)
  551. else:
  552. x = cx + radius*math.cos(radian-d*i)
  553. y = cy + radius*math.sin(radian-d*i)
  554. x = cx + radius*math.cos(radian+d*i)
  555. y = cy + radius*math.sin(radian+d*i)
  556. ls.append(x)
  557. ls.append(y)
  558. print(ls)
  559. return ls
  560.  
  561. class BaseMethod():
  562.  
  563. def _set_base_var(self):
  564. #coord
  565. self.mx = None #set by _set_mouse_coord()
  566. self.my = None
  567. self.sx = None #set by _set_start_coord()
  568. self.sy = None
  569. self.cx = None #set by _set_center_coord()
  570. self.cy = None
  571. #put selectingObj & Anc
  572. self.selecting_objs = []
  573. self.selecting_ancs = []
  574. self.editing_objs = []
  575. self.editing_ancs = []
  576. self.undo_list = []
  577. self.msg = tk.StringVar() #set by _set_message()
  578.  
  579. def _save_init_info(self):
  580. self.init = []
  581. for a in self.selecting_ancs:
  582. ls = [a.x,a.y,a.width]
  583. self.init.append(ls)
  584.  
  585. def _load_init_info(self):
  586. n = 0
  587. for a in self.selecting_ancs:
  588. [a.x,a.y,a.width] = self.init[n]
  589. n += 1
  590.  
  591. def _draw_criterion_line(self):
  592. x = self.mx
  593. y = self.my
  594. width = self.canvas.winfo_width()
  595. height = self.canvas.winfo_height()
  596. tag = "Border"
  597. self.canvas.delete(tag)
  598. self.canvas.create_line(0,y,width,y,width=1,tags=tag,
  599. fill="black",stipple="gray50")
  600. self.canvas.create_line(x,0,x,height,width=1,tags=tag,
  601. fill="black",stipple="gray50")
  602. return
  603.  
  604. def _draw_adjusting_line(self):
  605. tag = "Border"
  606. self.canvas.delete(tag)
  607. self.canvas.create_line(self.cx,self.cy,self.mx,self.my,
  608. tags=tag,stipple="gray50",width=1)
  609.  
  610. def _draw_selecting_border(self):
  611. tag = "Border"
  612. self.canvas.delete(tag)
  613. self.canvas.create_rectangle(self.sx,self.sy,self.mx,self.my,
  614. fill="",width=1,stipple="gray50",
  615. tags=tag)
  616.  
  617.  
  618. def _set_center_coord(self,anc_list):
  619. if len(anc_list) < 1:
  620. return False
  621. if self.mode == "ObjMode":
  622. a = anc_list[0]
  623. [max_x,min_x,max_y,min_y] = [a.x,a.x,a.y,a.y]
  624. for a in anc_list:
  625. if max_x < a.x: max_x=a.x
  626. if min_x > a.x: min_x=a.x
  627. if max_y < a.y: max_y=a.y
  628. if min_y > a.y: min_y=a.y
  629. #print [max_x,min_x,max_y,min_y]
  630. self.cx = (max_x+min_x)/2
  631. self.cy = (max_y+min_y)/2
  632. return True
  633. else:
  634. [x,y,c] = [0,0,0]
  635. for a in anc_list:
  636. x += a.x
  637. y += a.y
  638. c += 1
  639. self.cx = x/c
  640. self.cy = y/c
  641. return True
  642.  
  643. def _set_start_coord(self,event):
  644. for o in self.obj_list:
  645. for a in o.anc_list:
  646. [a.sx,a.sy] = [event.x,event.y]
  647.  
  648. def _set_mouse_coord(self,event):
  649. self.mx = event.x
  650. self.my = event.y
  651.  
  652. def _set_selecting_items(self):
  653. self.selecting_objs = []
  654. self.selecting_ancs = []
  655.  
  656. if self.mode == "ObjMode":
  657. for o in self.obj_list:
  658. if o.selected:
  659. self.selecting_objs.append(o)
  660. for a in o.anc_list:
  661. self.selecting_ancs.append(a)
  662. return
  663.  
  664. if self.mode == "EditMode":
  665. for o in self.editing_objs:
  666. self.selecting_objs.append(o)
  667. for a in o.anc_list:
  668. if a.selected:
  669. self.selecting_ancs.append(a)
  670. return
  671.  
  672. def _set_editing_item(self):
  673. self.editing_objs = []
  674. self.editing_ancs = []
  675. if self.mode == "ObjMode":
  676. for o in self.obj_list:
  677. self.editing_objs.append(o)
  678. for a in o.anc_list:
  679. self.editing_ancs.append(a)
  680. return
  681.  
  682. if self.mode == "EditMode":
  683. for o in self.obj_list:
  684. if o.editable:
  685. self.editing_objs.append(o)
  686. for a in o.anc_list:
  687. self.editing_ancs.append(a)
  688. return
  689.  
  690. def _set_message(self,msg):
  691. self.msg.set(msg)
  692. #print self.msg.get()
  693.  
  694.  
  695. class ObjMethod(BaseMethod):
  696.  
  697. def _set_obj_var(self):
  698. return
  699.  
  700. def select_one_obj(self,event=None):
  701. for o in self.selecting_objs:
  702. o.deselect()
  703. if self.is_under_image:
  704. self.canvas.delete("under")
  705. id = self.canvas.find_closest(self.mx,self.my)
  706. id = id[0]
  707. for o in self.editing_objs:
  708. if o.id == id:
  709. o.select()
  710. msg = "selected! "+o.tag
  711. self._set_message(msg)
  712. if self.is_under_image:
  713. self._view_under_image()
  714. self._set_selecting_items()
  715.  
  716. def select_some_obj(self,event=None):
  717. if self.is_under_image:
  718. self.canvas.delete("under")
  719. id = self.canvas.find_closest(self.mx,self.my)
  720. id = id[0]
  721. for o in self.editing_objs:
  722. if o.id == id:
  723. o.select_switch()
  724. if self.is_under_image:
  725. self.under_image()
  726. self._set_selecting_items()
  727.  
  728. def create(self,event=None):
  729. #deselect all
  730. for o in self.obj_list:
  731. o.deselect()
  732. #create obj
  733. obj = DrawingObject()
  734. #print self.line_type.get()
  735. if self.line_type.get() == "SubLine1":
  736. obj.color = "#CC3300"
  737. elif self.line_type.get() == "SubLine2":
  738. obj.color = "#0033CC"
  739. self.obj_list.append(obj)
  740. self.editing_objs.append(obj)
  741. self._set_selecting_items()
  742. #print self.editing_objs
  743. print("create new object! tag="+str(obj.tag))
  744. self.change_mode()
  745. self.add()
  746.  
  747. def destroy(self):
  748. newList = []
  749. for o in self.obj_list:
  750. if o.selected == False:
  751. newList.append(o)
  752. else:
  753. o.canvas.delete(o.tag)
  754. self._set_message("delete! "+o.tag)
  755. del o
  756. self.obj_list = newList
  757. self.editing_objs = self.obj_list[:]
  758. self._set_selecting_items()
  759.  
  760. def duplicate(self):
  761.  
  762. count = len(self.selecting_objs)
  763. #print count
  764. #del self.editing_objs[:]
  765. for i in range(count):
  766. obj = DrawingObject()
  767. self.obj_list.append(obj)
  768. new_obj = self.obj_list[-1]
  769. src_obj = self.selecting_objs[i]
  770. for a in src_obj.anc_list:
  771. anc = DrawingAnchor(a.x,a.y)
  772. anc.width = a.width
  773. anc.hide()
  774. new_obj.anc_list.append(anc)
  775. new_obj.editable = False
  776. new_obj.selected = True
  777. new_obj.redraw()
  778. src_obj.selected = False
  779. src_obj.redraw()
  780.  
  781. #self.editing_objs[:] = self.obj_list[:]
  782. self._set_editing_item()
  783. self._set_selecting_items()
  784. self._set_message("duplicate!")
  785. self.drag()
  786.  
  787. def _save_obj_undo(self):
  788. if len(self.undo_list) > 20:
  789. self.undo_list.pop(0)
  790. data = []
  791. for o in self.obj_list:
  792. data.append(o.get_data())
  793. self.undo_list.append(data)
  794. #print data
  795. return
  796.  
  797. def _load_obj_undo(self):
  798. try:
  799. data = self.undo_list[-1]
  800. except:
  801. return False
  802. i = 0
  803. for d in data:
  804. try:
  805. obj = self.obj_list[i]
  806. except:
  807. obj = DrawingObject()
  808. obj.set_data(d)
  809. i += 1
  810. self.undo_list[-1]
  811. return True
  812.  
  813.  
  814. class EditMethod(BaseMethod):
  815.  
  816. def _set_edit_var(self):
  817. return
  818.  
  819. def select_one_anc(self,event=None):
  820. closest_anc = self._find_closest_anc()
  821. for a in self.editing_ancs:
  822. if a is closest_anc:
  823. a.select()
  824. else:
  825. a.deselect()
  826. self._set_selecting_items()
  827. self._set_message("selected! "+a.tag)
  828.  
  829. def select_some_anc(self,event=None):
  830. anc = self._find_closest_anc()
  831. anc.select_switch()
  832. self._set_selecting_items()
  833. self._set_message("selected! "+anc.tag)
  834.  
  835. def _find_closest_anc(self):
  836. min_d = float('inf')
  837. closest_anc = None
  838. for a in self.editing_ancs:
  839. d = (a.x-self.mx)**2 +(a.y-self.my)**2
  840. if d < min_d:
  841. min_d = d
  842. closest_anc = a
  843. if closest_anc is None:
  844. print('find_closest_anc error')
  845. return closest_anc
  846.  
  847. def add(self,event=None):
  848. #print main.editingObj
  849. if not len(self.editing_objs) == 1:
  850. self._set_message("please select only one Obj")
  851. return False
  852. for obj in self.editing_objs:
  853. for anc in obj.anc_list:
  854. if anc.x == self.mx and anc.y == self.my:
  855. self._set_message('cannot add same place')
  856. return False
  857. anc = DrawingAnchor(self.mx,self.my)
  858. obj = self.editing_objs[-1]
  859. #print obj
  860. anc.show()
  861. obj.anc_list.append(anc)
  862. self.editing_ancs.append(anc)
  863. #print obj.anc_list
  864. self.redraw()
  865. self.rebind()
  866. self._save_edit_undo()
  867. self._set_message("add anchor! "+str(anc.tag))
  868.  
  869. def delete(self):
  870. for o in self.editing_objs:
  871. new_anc_list = []
  872. for a in o.anc_list:
  873. a.hide()
  874. if a.selected == False:
  875. new_anc_list.append(a)
  876. o.anc_list = new_anc_list
  877.  
  878. del self.editing_ancs[:]
  879. for o in self.editing_objs:
  880. for a in o.anc_list:
  881. if a.selected == False:
  882. self.editing_ancs.append(a)
  883.  
  884. self.rebind()
  885. self._set_message("delete!")
  886.  
  887. def cut_in(self):
  888. editObj = self.editing_objs[-1]
  889.  
  890. for i in range(len(self.editing_ancs)):
  891. a = self.editing_ancs[i]
  892. if a.selected == True:
  893. no=i
  894. a1 = self.editing_ancs[no]
  895. a2 = self.editing_ancs[no-1]
  896. if a2.selected == False:
  897. self._set_message("please select 2 nearless ancour...")
  898. return
  899. anc = DrawingAnchor(0,0)
  900. anc.x = (a1.x+a2.x)/2
  901. anc.y = (a1.y+a2.y)/2
  902. anc.show()
  903. editObj.anc_list.insert(no,anc)
  904. self.editing_ancs.insert(no,anc)
  905. self.redraw()
  906. self.rebind()
  907. self._save_edit_undo()
  908. self._set_message("cut in!")
  909.  
  910. def reverse(self):
  911. for o in self.editing_objs:
  912. o.anc_list.reverse()
  913. self._save_edit_undo()
  914. self._set_message("reverse!")
  915.  
  916. def _save_edit_undo(self):
  917. for o in self.selecting_objs:
  918. if len(o.undo_list) > 10:
  919. o.undo_list.pop(0)
  920. data = []
  921. for a in o.anc_list:
  922. data.append(a.get_data())
  923. o.undo_list.append(data)
  924. #print data
  925. return
  926.  
  927. def _load_edit_undo(self):
  928. for o in self.selecting_objs:
  929. try:
  930. data = o.undo_list[-1]
  931. except:
  932. return False
  933. i = 0
  934. for d in data:
  935. try:
  936. anc = o.anc_list[i]
  937. except:
  938. anc = DrawingAnchor(0,0)
  939. anc.set_data(d)
  940. i += 1
  941. o.undo_list.pop(-1)
  942. return True
  943.  
  944. class ViewMethod(BaseMethod):
  945.  
  946. def _set_view_var(self):
  947. self.is_under_image = False
  948.  
  949. def scroll(self,event):
  950. for o in self.obj_list:
  951. for a in o.anc_list:
  952. [a.sx,a.sy] = [event.x,event.y]
  953. self.unbind()
  954. self.canvas.bind("<ButtonRelease-2>", self._finish_scroll)
  955. self.canvas.bind("<B2-Motion>", self._scrolling)
  956.  
  957. def _scrolling(self,event):
  958. for o in self.obj_list:
  959. for a in o.anc_list:
  960. self.canvas.move(a.tag, event.x-a.sx ,event.y-a.sy)
  961. a.x = a.x + event.x - a.sx
  962. a.y = a.y + event.y - a.sy
  963. a.sx = event.x
  964. a.sy = event.y
  965. o.redraw()
  966.  
  967. def _finish_scroll(self,event):
  968. self.rebind()
  969. self.repaint_all()
  970.  
  971. def zooming(self,event):
  972. self.cx = self.canvas.winfo_width()/2
  973. self.cy = self.canvas.winfo_height()/2
  974. self.value = math.sqrt((self.cx-event.x)**2+(self.cy-event.y)**2)
  975. radian = []
  976. distance = []
  977. for o in self.obj_list:
  978. for a in o.anc_list:
  979. dx = a.x-self.cx
  980. dy = a.y-self.cy
  981. radian.append(math.atan2(dy,dx))
  982. distance.append(math.sqrt(dx*dx + dy*dy))
  983. self.radian = radian
  984. self.distance = distance
  985. self.unbind()
  986. self.unbind()
  987. self.canvas.bind("<B2-Motion>", self._zooming)
  988. self.canvas.bind("<ButtonRelease-2>", self.finish_zooming)
  989.  
  990. def _zooming(self,event):
  991. value = math.sqrt((self.cx-event.x)**2+(self.cy-event.y)**2)-self.value
  992. value = value/self.value + 1.0
  993. radian = self.radian
  994. d = self.distance
  995. n = 0
  996. for o in self.obj_list:
  997. for a in o.anc_list:
  998. a.x = self.cx + value * d[n] * math.cos(radian[n])
  999. a.y = self.cy + value * d[n] * math.sin(radian[n])
  1000. print(round(value,3))
  1001. n += 1
  1002. o.redraw()
  1003. return
  1004.  
  1005. def _finish_zooming(self,event):
  1006. self.rebind()
  1007.  
  1008. def zoom(self,event): #By MouseWheel
  1009. self.cx = self.canvas.winfo_width()/2
  1010. self.cy = self.canvas.winfo_height()/2
  1011. #print event.delta/100.0
  1012. if event.delta>0:
  1013. value = event.delta/100.0
  1014. else:
  1015. value = 2.0 + event.delta/100.0
  1016. if value < 0:
  1017. value = 0.2
  1018. print(value)
  1019. for o in self.obj_list:
  1020. for a in o.anc_list:
  1021. dx = a.x-self.cx
  1022. dy = a.y-self.cy
  1023. r = math.atan2(dy,dx)
  1024. d = math.sqrt(dx*dx + dy*dy)
  1025. a.x = self.cx + value * d * math.cos(r)
  1026. a.y = self.cy + value * d * math.sin(r)
  1027. o.redraw()
  1028. if self.is_under_image:
  1029. self.canvas.scale(self.test,self.cx,self.cy,100,100)
  1030. return
  1031.  
  1032. def turn_over(self):
  1033. width = self.canvas.winfo_width()
  1034. for o in self.obj_list:
  1035. for a in o.anc_list:
  1036. a.x = width-a.x
  1037. o.redraw()
  1038. self._set_message("trun over!")
  1039.  
  1040. def view_all(self):
  1041. #find max&min
  1042. canvas_width = self.canvas.winfo_width()
  1043. canvas_height= self.canvas.winfo_height()
  1044. a = self.editing_ancs[0]
  1045. [min_x,min_y,max_x,max_y] = [a.x,a.y,a.x,a.y]
  1046. for a in self.editing_ancs:
  1047. if a.x < min_x:
  1048. min_x = a.x
  1049. if a.x > max_x:
  1050. max_x = a.x
  1051. if a.y < min_y:
  1052. min_y = a.y
  1053. if a.y > max_y:
  1054. max_y = a.y
  1055. self._zoomToRange(max_x,max_y,min_x,min_y,0.9)
  1056. return
  1057.  
  1058. def zoom_by_border(self):
  1059. self.unbind()
  1060. self.canvas.bind("<Motion>",self._ready_zoomBB)
  1061. self.canvas.bind("<ButtonPress-1>",self._start_zoomBB)
  1062. self.canvas.bind("<ButtonPress-2>",self.finish)
  1063. self.canvas.bind("<ButtonPress-3>",self._start_zoomBB)
  1064. self._draw_criterion_line()
  1065.  
  1066. def _ready_zoomBB(self,event):
  1067. self._set_mouse_coord(event)
  1068. self._draw_criterion_line()
  1069.  
  1070. def _start_zoomBB(self,event):
  1071. self.sx = event.x
  1072. self.sy = event.y
  1073. self.unbind()
  1074. self.canvas.bind("<B1-Motion>",self._bordering)
  1075. self.canvas.bind("<B2-Motion>",self._bordering)
  1076. self.canvas.bind("<B3-Motion>",self._bordering)
  1077. self.canvas.bind("<ButtonRelease-1>",self.finish_zoomBB)
  1078. self.canvas.bind("<ButtonRelease-2>",self.finish_zoomBB)
  1079. self.canvas.bind("<ButtonRelease-3>",self.finish_zoomBB)
  1080.  
  1081. def finish_zoomBB(self,event):
  1082. self.canvas.delete("Border")
  1083. self._zoomToRange(self.sx,self.sy,event.x,event.y)
  1084. self.rebind()
  1085. return
  1086.  
  1087. def _zoomToRange(self,x1,y1,x2,y2,rate_rev=1):
  1088. canvas_width = self.canvas.winfo_width()
  1089. canvas_height= self.canvas.winfo_height()
  1090. if x1 > x2:
  1091. max_x = x1
  1092. min_x = x2
  1093. else:
  1094. max_x = x2
  1095. min_x = x1
  1096. if y1 > y2:
  1097. max_y = y1
  1098. min_y = y2
  1099. else:
  1100. max_y = y2
  1101. min_y = y1
  1102. #value of revise to center
  1103. canvas_center = [canvas_width/2,
  1104. canvas_height/2]
  1105. draw_center = [(max_x+min_x)/2,
  1106. (max_y+min_y)/2]
  1107. revise_value = [canvas_center[0]-draw_center[0],
  1108. canvas_center[1]-draw_center[1]]
  1109. #calucurate value of revise scale
  1110. rate_x = float(canvas_width / (max_x-min_x))
  1111. rate_y = float(canvas_height/ (max_y-min_y))
  1112. if rate_x<rate_y:
  1113. rate = rate_x
  1114. else:
  1115. rate = rate_y
  1116. rate = rate * rate_rev
  1117. print(rate)
  1118. for o in self.obj_list:
  1119. for a in o.anc_list:
  1120. #revise coord
  1121. a.x = a.x+revise_value[0]
  1122. a.y = a.y+revise_value[1]
  1123. #revise scale
  1124. dx = a.x-canvas_center[0]
  1125. dy = a.y-canvas_center[1]
  1126. radian = math.atan2(dy,dx)
  1127. distance = math.sqrt(dx*dx + dy*dy)
  1128. a.x = canvas_center[0] + rate * distance * math.cos(radian)
  1129. a.y = canvas_center[1] + rate * distance * math.sin(radian)
  1130. o.redraw()
  1131.  
  1132. def under_image(self,event=None):
  1133. if self.is_under_image:
  1134. self.canvas.delete("under")
  1135. self.is_under_image = False
  1136. else:
  1137. self._view_under_image()
  1138. self.is_under_image = True
  1139.  
  1140. def _view_under_image(self):
  1141. #x = int(self.canvas.cget('width'))/2
  1142. #y = int(self.canvas.cget('height'))/2
  1143. x = self.canvas.winfo_width()/2
  1144. y = self.canvas.winfo_height()/2
  1145. try:
  1146. self.test=self.canvas.create_image(x,y,image=self.u_img,tags="under")
  1147. except:
  1148. self._set_message("please select image...")
  1149. self.canvas.tag_lower("under")
  1150.  
  1151. def select_under_image(self,event=None):
  1152. fTyp=[('GIF;JPG','*.gif;*.jpg;')]
  1153. fname = fd.askopenfilename(filetypes=fTyp)
  1154. self.u_img = tk.PhotoImage(file=fname)
  1155. self._view_under_image()
  1156. self.is_under_image = True
  1157.  
  1158. class CommonMethod(ObjMethod,EditMethod):
  1159.  
  1160. def _set_com_var(self):
  1161. #flags
  1162. self.showed_subwindow = False
  1163. return
  1164.  
  1165. def _ready(self,event):
  1166. self._set_mouse_coord(event)
  1167. self._draw_criterion_line()
  1168.  
  1169. def _bordering(self,event):
  1170. self._set_mouse_coord(event)
  1171. self._draw_selecting_border()
  1172.  
  1173. def _start(self):
  1174. if len(self.selecting_ancs)==0:
  1175. self._set_message("please select item...")
  1176. return False
  1177. self._set_center_coord(self.selecting_ancs)
  1178. self._save_init_info()
  1179. self.unbind()
  1180. self.canvas.bind("<Button-1>",self.finish)
  1181. self.canvas.bind("<Button-3>",self.cancel)
  1182. return True
  1183.  
  1184. def finish(self,event=None):
  1185. self.canvas.delete("Border")
  1186. self._save_undo()
  1187. self.redraw()
  1188. self.rebind()
  1189. self._set_message("done")
  1190.  
  1191. def cancel(self,event=None):
  1192. self._load_init_info()
  1193. self.finish(event)
  1194. self._set_message("cancel")
  1195.  
  1196. def drag(self):
  1197. if not self._start():
  1198. return
  1199. for a in self.selecting_ancs:
  1200. [a.sx,a.sy] = [self.mx,self.my]
  1201. self.canvas.bind("<Motion>",self._dragging)
  1202.  
  1203. def _dragging(self,event):
  1204. self._set_mouse_coord(event)
  1205. for a in self.selecting_ancs:
  1206. self.canvas.move(a.tag,self.mx-a.sx,self.my-a.sy)
  1207. a.x = a.x + self.mx - a.sx
  1208. a.y = a.y + self.my - a.sy
  1209. a.sx = self.mx
  1210. a.sy = self.my
  1211. self.redraw()
  1212. self._set_message("dragging")
  1213.  
  1214. def rotate(self):
  1215. if not self._start():
  1216. return
  1217. self.r = math.atan2(self.mx-self.cx,self.my-self.cy)
  1218. radian = []
  1219. distance = []
  1220. for a in self.selecting_ancs:
  1221. dx = a.x-self.cx
  1222. dy = a.y-self.cy
  1223. radian.append(math.atan2(dy,dx))
  1224. distance.append(math.sqrt(dx*dx + dy*dy))
  1225. self.radian = radian
  1226. self.distance = distance
  1227. self.canvas.bind("<Motion>",self._rotating)
  1228. self._draw_adjusting_line()
  1229.  
  1230. def _rotating(self,event):
  1231. self._set_mouse_coord(event)
  1232. r = math.atan2(self.mx-self.cx,self.my-self.cy)
  1233. r = self.r-r
  1234. radian = self.radian
  1235. d = self.distance
  1236. n = 0
  1237. for a in self.selecting_ancs:
  1238. a.x = self.cx + d[n] * math.cos(radian[n]+r)
  1239. a.y = self.cy + d[n] * math.sin(radian[n]+r)
  1240. n += 1
  1241. self._draw_adjusting_line()
  1242. self._set_message("rotate "+str(round(math.degrees(r),2)))
  1243. self.redraw()
  1244.  
  1245. def resize(self):
  1246. if not self._start():
  1247. return
  1248. self.sx,self.sy = self.mx,self.my
  1249. self.value = math.sqrt((self.cx-self.mx)**2+
  1250. (self.cy-self.my)**2)
  1251. radian = []
  1252. distance = []
  1253. for a in self.selecting_ancs:
  1254. dx = a.x-self.cx
  1255. dy = a.y-self.cy
  1256. radian.append(math.atan2(dy,dx))
  1257. distance.append(math.sqrt(dx*dx + dy*dy))
  1258. self.radian = radian
  1259. self.distance = distance
  1260. self.canvas.bind("<Motion>",self._resizing)
  1261. self._draw_adjusting_line()
  1262.  
  1263. def _resizing(self,event):
  1264. self._set_mouse_coord(event)
  1265. value = math.sqrt((self.cx-self.mx)**2+
  1266. (self.cy-self.my)**2)-self.value
  1267. value = value/self.value + 1.0
  1268. radian = self.radian
  1269. d = self.distance
  1270. n = 0
  1271. for a in self.selecting_ancs:
  1272. a.x = self.cx + value * d[n] * math.cos(radian[n])
  1273. a.y = self.cy + value * d[n] * math.sin(radian[n])
  1274. n += 1
  1275. num ='%3.3lf' % value
  1276. self._set_message("resize "+num)
  1277. self._draw_adjusting_line()
  1278. self.redraw()
  1279.  
  1280. def rewidth(self):
  1281. if not self._start():
  1282. return
  1283. self.value = math.sqrt((self.cx-self.mx)**2+
  1284. (self.cy-self.my)**2)
  1285. self.width_ls =[]
  1286. for a in self.selecting_ancs:
  1287. a.swidth = a.width
  1288. self.canvas.bind("<Motion>",self._rewidthing)
  1289. self._draw_adjusting_line()
  1290.  
  1291. def _rewidthing(self,event):
  1292. self._set_mouse_coord(event)
  1293. value = math.sqrt((self.cx-self.mx)**2+
  1294. (self.cy-self.my)**2)-self.value
  1295. value = value/self.value + 1.0
  1296. n = 0
  1297. for a in self.selecting_ancs:
  1298. a.width = value * a.swidth
  1299. if a.width < 0.1:
  1300. a.width = 0.1
  1301. n += 1
  1302. num ='%03lf' % value
  1303. self._set_message("rewidth "+num)
  1304. self._draw_adjusting_line()
  1305. self.redraw()
  1306.  
  1307. def mirror(self):
  1308. self._set_center_coord(self.selecting_ancs)
  1309. self.unbind()
  1310. self.window.bind("<KeyPress>",self._mirrored)
  1311. self._set_message("select axis (x,y)")
  1312.  
  1313. def _mirrored(self,event):
  1314. if event.keysym == "x":
  1315. width = self.cx*2
  1316. for a in self.selecting_ancs:
  1317. a.x = width-a.x
  1318. elif event.keysym == "y":
  1319. width = self.cy*2
  1320. for a in self.selecting_ancs:
  1321. a.y = width-a.y
  1322. else:
  1323. return
  1324.  
  1325. self.rebind()
  1326. self.redraw()
  1327. self._set_message("mirrored!")
  1328.  
  1329. def select_all(self):
  1330. if self.mode == "ObjMode":
  1331. items = self.editing_objs
  1332. elif self.mode == "EditMode":
  1333. items = self.editing_ancs
  1334. flag = True
  1335. for item in items:
  1336. if item.selected:
  1337. flag = False
  1338. if flag:
  1339. for item in items:
  1340. item.select()
  1341. else:
  1342. for item in items:
  1343. item.deselect()
  1344. self._set_selecting_items()
  1345. return
  1346.  
  1347. def select_by_border(self):
  1348. self.unbind()
  1349. self.canvas.bind("<Motion>",self._ready)
  1350. self.canvas.bind("<ButtonPress-1>",self._start_selecting)
  1351. self.canvas.bind("<ButtonPress-2>",self.finish)
  1352. self.canvas.bind("<ButtonPress-3>",self._start_selecting)
  1353. self._draw_criterion_line()
  1354. self._set_message("Border select")
  1355.  
  1356. def _start_selecting(self,event):
  1357. self.sx = event.x
  1358. self.sy = event.y
  1359. self.unbind()
  1360. self.canvas.bind("<B1-Motion>",self._bordering)
  1361. self.canvas.bind("<B3-Motion>",self._bordering)
  1362. self.canvas.bind("<ButtonRelease-1>",self._select_in_rect)
  1363. self.canvas.bind("<ButtonRelease-2>",self._select_in_rect)
  1364. self.canvas.bind("<ButtonRelease-3>",self._select_in_rect)
  1365.  
  1366. def _select_in_rect(self,event):
  1367. n=0
  1368. tag = "Border"
  1369. self.canvas.delete(tag)
  1370. if self.mode == "ObjMode":
  1371. items = self.editing_objs
  1372. s = " Obj"
  1373. elif self.mode == "EditMode":
  1374. items = self.editing_ancs
  1375. s = " Anc"
  1376. ls = self.canvas.find_overlapping(self.sx,self.sy,self.mx,self.my)
  1377. for item in items:
  1378. for id in ls:
  1379. if id == item.id:
  1380. if event.num == 1:
  1381. item.select()
  1382. n+=1
  1383. elif event.num == 2:
  1384. item.deselect()
  1385. elif event.num == 3:
  1386. item.deselect()
  1387. self._set_selecting_items()
  1388. self._set_message("selected! "+str(n)+s)
  1389. self.redraw()
  1390. self.rebind()
  1391. return
  1392.  
  1393. def redraw(self):
  1394. if self.mode == "EditMode":
  1395. for o in self.editing_objs:
  1396. o.redraw()
  1397.  
  1398. elif self.mode == "ObjMode":
  1399. for o in self.selecting_objs:
  1400. o.redraw()
  1401.  
  1402. def repaint_all(self):
  1403. for o in self.obj_list:
  1404. o.redraw()
  1405.  
  1406. def show_draw_type_window(self):
  1407. if not self.showed_subwindow:
  1408. import functools
  1409. f = tk.Frame(self.canvas,bg="gray")
  1410. tk.Label(f,text="Draw Type",bg="gray").pack(anchor=tk.NW)
  1411. draw_type = ['Original','Polygon','Spline','Arrow']
  1412. for dt in draw_type:
  1413. b = tk.Button(f,text=dt,relief=tk.FLAT,
  1414. command=functools.partial(self.change_draw_type,dt))
  1415. b.pack(anchor=tk.NW,fill=tk.X,pady=1,padx=2)
  1416. f.pack()
  1417. self.canvas.create_window(self.mx,self.my,window=f,anchor=tk.NW,
  1418. tags="window")
  1419. self.showed_subwindow = True
  1420. self.window_box = (self.mx-10,self.my-10,self.mx+70,self.my+130)
  1421. #self.canvas.create_rectangle(self.window_box)
  1422. self.canvas.bind("<Motion>",self._hide_popup)
  1423.  
  1424. def change_draw_type(self,draw_type):
  1425. for o in self.selecting_objs:
  1426. o.change_type(draw_type)
  1427. self.del_popup()
  1428. self.redraw()
  1429. print(draw_type)
  1430.  
  1431. def _hide_popup(self,event):
  1432. self._set_mouse_coord(event)
  1433. if (self.window_box[0] > self.mx or
  1434. self.window_box[1] > self.my or
  1435. self.window_box[2] < self.mx or
  1436. self.window_box[3] < self.my):
  1437. self.del_popup()
  1438.  
  1439. def del_popup(self):
  1440. self.canvas.delete("window")
  1441. del self.window_box
  1442. self.showed_subwindow = False
  1443. self.canvas.bind("<Motion>",self._set_mouse_coord)
  1444.  
  1445. def undo(self):
  1446. flag = False
  1447. if self.mode == "EditMode":
  1448. if self._load_edit_undo():
  1449. flag = True
  1450. elif self.mode == "ObjMode":
  1451. if self._load_obj_undo():
  1452. flag = True
  1453. if flag:
  1454. self._set_editing_item()
  1455. self._set_selecting_items()
  1456. self.redraw()
  1457. self._set_message("undo!")
  1458. else:
  1459. self._set_message("No more step to undo...")
  1460. return
  1461.  
  1462. def _save_undo(self):
  1463. if self.mode == "ObjMode":
  1464. self._save_obj_undo()
  1465. elif self.mode == "EditMode":
  1466. self._save_edit_undo
  1467.  
  1468. class DrawingMethod(ViewMethod,CommonMethod):
  1469.  
  1470. def set_vars(self):
  1471. self._set_base_var()
  1472. self._set_obj_var()
  1473. self._set_edit_var()
  1474. self._set_com_var()
  1475. self._set_view_var()
  1476.  
  1477. def change_mode(self,event=None):
  1478. if self.mode == "EditMode":
  1479. self.change_to_obj_mode()
  1480. else:
  1481. self.change_to_edit_mode()
  1482. self._set_selecting_items()
  1483.  
  1484. def change_to_obj_mode(self):
  1485. #check
  1486. if len(self.editing_ancs) < 2:
  1487. print("please add Anc more than 2...")
  1488. return False
  1489. #change
  1490. for o in self.editing_objs:
  1491. o.select()
  1492. o.editable = False
  1493. self.editing_ancs = []
  1494. self.editing_objs = []
  1495. for o in self.obj_list:
  1496. self.editing_objs.append(o)
  1497. for a in o.anc_list:
  1498. self.editing_ancs.append(a)
  1499. self.mode = "ObjMode"
  1500. self.redraw()
  1501. self.rebind()
  1502. print("Object Mode!")
  1503. return
  1504.  
  1505. def change_to_edit_mode(self):
  1506. #check
  1507. ls = []
  1508. for o in self.selecting_objs:
  1509. o.editable = True
  1510. ls.append(o)
  1511. if len(ls) == 0:
  1512. self._set_message("please select more than one object...")
  1513. return False
  1514. #change
  1515. self.editing_objs = ls
  1516. self.editing_ancs = []
  1517. for o in self.editing_objs:
  1518. for a in o.anc_list:
  1519. self.editing_ancs.append(a)
  1520. self.mode = "EditMode"
  1521. self.rebind()
  1522. self.redraw()
  1523. print("Edit Mode!")
  1524. return
  1525.  
  1526. class IOMethod:
  1527.  
  1528. def open(self):
  1529. #select file
  1530. fTyp=[('All','*.*;')]
  1531. fname = fd.askopenfilename(filetypes=fTyp)
  1532. fname=open(fname,"rb")
  1533. data=pickle.load(fname)
  1534. fname.close()
  1535. self.obj_list = []
  1536. #clean canvas
  1537. for o in self.obj_list:
  1538. o.select()
  1539. self._set_selecting_items()
  1540. self.destroy()
  1541. ls = self.canvas.find_all()
  1542. for id in ls:
  1543. self.canvas.delete(id)
  1544. del self.obj_list[:]
  1545. del self.editing_ancs[:]
  1546. #open
  1547. for obj_data in data:
  1548. o = DrawingObject()
  1549. o.set_data(obj_data)
  1550. self.obj_list.append(o)
  1551. self.editing_objs.append(o)
  1552. for a in o.anc_list:
  1553. self.editing_ancs.append(a)
  1554. self.repaint_all()
  1555. print("open!",fname)
  1556.  
  1557. def save(self):
  1558. fname = fd.asksaveasfilename()
  1559. data = []
  1560. for o in self.obj_list:
  1561. data.append(o.get_data())
  1562. fname=file(fname,"wb")
  1563. pickle.dump(data,fname)
  1564. fname.close()
  1565. print("save!", fname)
  1566.  
  1567. def import_(self,event=None):
  1568. #not yet
  1569. pass
  1570.  
  1571. def export(self,event=None):
  1572. self._export_raster_img()
  1573.  
  1574. def _export_postscript(self):
  1575. self.canvas.postscript(file="output.ps")
  1576.  
  1577. def _export_raster_img(self):
  1578. #now testing
  1579. from PIL import Image, ImageDraw
  1580.  
  1581. filename = fd.asksaveasfilename()
  1582. #width = int(self.canvas.cget('width'))
  1583. #height = int(self.canvas.cget('height'))
  1584. width = self.canvas.winfo_width()
  1585. height= self.canvas.winfo_height()
  1586. image = Image.new("RGB", (width, height),(255, 255, 255))
  1587. draw = ImageDraw.Draw(image)
  1588. for obj in self.obj_list:
  1589. ls = Curve(obj.anc_list)
  1590. draw.polygon(ls,fill="black")
  1591. try:
  1592. image.save(filename)
  1593. except KeyError:
  1594. filename = filename + ".png"
  1595. image.save(filename)
  1596. finally:
  1597. print("saved!")
  1598. return
  1599.  
  1600. class MainCanvas(DrawingMethod,IOMethod):
  1601. #setting data
  1602. window = None
  1603. canvas = None
  1604. mode = "ObjMode"
  1605.  
  1606. #property data
  1607. obj_list = []
  1608.  
  1609. #editting data
  1610. selecting_ancs = []
  1611. selecting_objs = []
  1612. editing_objs = []
  1613. editing_ancs = []
  1614.  
  1615. def __init__(self, window):
  1616. self.window = window
  1617. self.set_vars()
  1618. self.rebind()
  1619.  
  1620. def rebind(self):
  1621. self.unbind()
  1622.  
  1623. if self.mode == "ObjMode":
  1624. self.canvas.bind("<ButtonPress-1>", self.create)
  1625. self.canvas.bind("<ButtonPress-3>", self.select_one_obj)
  1626. self.canvas.bind("<Shift-ButtonPress-3>", self.select_some_obj)
  1627. elif self.mode == "EditMode":
  1628. self.canvas.bind("<ButtonPress-1>", self.add)
  1629. self.canvas.bind("<ButtonPress-3>", self.select_one_anc)
  1630. self.canvas.bind("<Shift-ButtonPress-3>", self.select_some_anc)
  1631. self.canvas.bind("<B2-Motion>", self.scroll)
  1632. self.canvas.bind("<Motion>",self._set_mouse_coord)
  1633. self.window.bind("<KeyPress>",self.press_key)
  1634. self.window.bind("<Control-KeyPress>",self.press_ctrl_key)
  1635. self.window.bind("<MouseWheel>",self.zoom)
  1636.  
  1637. def unbind(self):
  1638. self.canvas.unbind("<ButtonPress-1>")
  1639. self.canvas.unbind("<ButtonPress-2>")
  1640. self.canvas.unbind("<ButtonPress-3>")
  1641. self.canvas.unbind("<B1-Motion>")
  1642. self.canvas.unbind("<B2-Motion>")
  1643. self.canvas.unbind("<B3-Motion>")
  1644. self.canvas.unbind("<ButtonRelease-1>")
  1645. self.canvas.unbind("<ButtonRelease-2>")
  1646. self.canvas.unbind("<ButtonRelease-3>")
  1647. self.window.unbind("<KeyPress>")
  1648. self.window.unbind("<KeyRelease>")
  1649.  
  1650. if self.mode == "EditMode":
  1651. for a in self.editing_ancs:
  1652. self.canvas.tag_unbind(a.tag,"<ButtonPress-3>")
  1653.  
  1654. def press_key(self,event):
  1655. self._set_start_coord(event)
  1656.  
  1657. if event.keysym == "Tab":
  1658. self.change_mode()
  1659. elif event.keysym == "C":
  1660. self.view_all()
  1661. elif event.keysym == "a":
  1662. self.select_all()
  1663. elif event.keysym == "b":
  1664. self.select_by_border()
  1665. elif event.keysym == "g":
  1666. self.drag()
  1667. elif event.keysym == "s":
  1668. self.resize()
  1669. elif event.keysym == "r":
  1670. self.rotate()
  1671. elif event.keysym == "w":
  1672. self.rewidth()
  1673. elif event.keysym == "U":
  1674. self.under_image()
  1675. elif event.keysym == "z":
  1676. self.zoom_by_border()
  1677. elif event.keysym == "m":
  1678. self.mirror()
  1679. elif event.keysym == "d":
  1680. self.show_draw_type_window()
  1681.  
  1682. if self.mode == "ObjMode":
  1683.  
  1684. if event.keysym == "D":
  1685. self.duplicate()
  1686. elif event.keysym == "h":
  1687. self.turn_over()
  1688. elif event.keysym == "x":
  1689. self.destroy()
  1690.  
  1691. elif self.mode == "EditMode":
  1692.  
  1693. if event.keysym == "R":
  1694. self.reverse()
  1695. elif event.keysym == "k":
  1696. self.cut_in()
  1697. elif event.keysym == "x":
  1698. self.delete()
  1699.  
  1700. self.redraw()
  1701. return
  1702.  
  1703. def press_ctrl_key(self,event):
  1704.  
  1705. if event.keysym == "e":
  1706. self.export_raster_img()
  1707. elif event.keysym == "o":
  1708. self.open()
  1709. elif event.keysym == "s":
  1710. self.save()
  1711. elif event.keysym == "u":
  1712. self.select_under_image()
  1713. elif event.keysym == "z":
  1714. self.undo()
  1715. return
  1716.  
  1717. class DrawingObject:
  1718.  
  1719. #setting
  1720. canvas = None
  1721. color = "black"
  1722. select_color= "orange"
  1723.  
  1724. #editing data
  1725. selected = True
  1726. editable = True
  1727.  
  1728. #property data
  1729. anc_list = []
  1730. undo_list = []
  1731.  
  1732. def __init__(self):
  1733. self.tag = "obj_"+str(id(self))
  1734. #have to format
  1735. self.anc_list = []
  1736.  
  1737. def __del__(self):
  1738. print("bye",self.tag)
  1739.  
  1740. def get_data(self):
  1741. anc_list = []
  1742. for a in self.anc_list:
  1743. anc_data = a.get_data()
  1744. anc_list.append(anc_data)
  1745. return [anc_list,
  1746. self.tag,
  1747. self.selected,
  1748. self.editable]
  1749.  
  1750. def set_data(self,data):
  1751. del self.anc_list[:]
  1752. t = [0,0]
  1753. for anc_data in data[0]:
  1754. anc = DrawingAnchor(0,0)
  1755. anc.set_data(anc_data)
  1756. if t[0]==anc.x and t[1]==anc.y:
  1757. print("error "+ anc.tag)
  1758. else:
  1759. self.anc_list.append(anc)
  1760. t = [anc.x,anc.y]
  1761. self.tag = data[1]
  1762. self.selected = data[2]
  1763. self.editable = data[3]
  1764.  
  1765. def select_switch(self,event=None):
  1766. if self.selected == True:
  1767. self.deselect()
  1768. else:
  1769. self.select()
  1770.  
  1771. def select(self):
  1772. self.selected = True
  1773. self.redraw()
  1774.  
  1775. def deselect(self):
  1776. self.editable = False
  1777. self.selected = False
  1778. self.redraw()
  1779.  
  1780. def redraw(self):
  1781. self.canvas.delete(self.tag)
  1782. width = self.canvas.winfo_width()
  1783. height = self.canvas.winfo_height()
  1784. min_x,min_y = 9999,9999
  1785. max_x,max_y = 0,0
  1786.  
  1787. for a in self.anc_list:
  1788. a.hide()
  1789. if a.x < min_x: min_x = a.x
  1790. if a.x > max_x: max_x = a.x
  1791. if a.y < min_y: min_y = a.y
  1792. if a.y > max_y: max_y = a.y
  1793. if not (a.x < 0 or a.x > width or
  1794. a.y < 0 or a.y > height):
  1795. if self.editable:
  1796. a.redraw()
  1797. if (min_x > width or max_x < 0 or
  1798. min_y > height or max_y < 0):
  1799. return
  1800.  
  1801. if self.editable:
  1802. self._draw_line()
  1803. self._draw_curve(self.tag,self.color)
  1804. else:
  1805. if self.selected == True:
  1806. #self._drawHighLight()
  1807. self._draw_curve(self.tag,self.select_color)
  1808. else:
  1809. self._draw_curve(self.tag,self.color)
  1810.  
  1811. def change_type(self,draw_type):
  1812. if draw_type == "Original":
  1813. self._draw_curve = self._bezier
  1814. elif draw_type == "Spline":
  1815. self._draw_curve = self._spline
  1816. elif draw_type == "Polygon":
  1817. self._draw_curve = self._polygon
  1818. elif draw_type == "Arrow":
  1819. self._draw_curve = self._arrow
  1820. else:
  1821. self._draw_curve = self._bezier
  1822.  
  1823. def _draw_curve(self,tag,color):
  1824. self._bezier(tag,color)
  1825.  
  1826. def _draw_line(self):
  1827. if len(self.anc_list) < 2:
  1828. return
  1829. ls = []
  1830. tag = self.tag
  1831. for a in self.anc_list:
  1832. ls.append(a.x)
  1833. ls.append(a.y)
  1834. self.canvas.create_line(ls,fill="red",width=1,tags=tag)
  1835.  
  1836. def _spline(self,tag,color):
  1837. if len(self.anc_list) < 2:
  1838. return
  1839. width = self.anc_list[0].width*2
  1840. ls = []
  1841. for a in self.anc_list:
  1842. ls.append(a.x)
  1843. ls.append(a.y)
  1844. id = self.canvas.create_line(ls,width=width,fill=color,
  1845. tags=tag, smooth=True)
  1846. self.id = id
  1847. return
  1848.  
  1849. def _bezier(self,tag,color):
  1850. if len(self.anc_list) < 3:
  1851. self._spline(self.tag,color)
  1852. return
  1853. bl = Curve(self.anc_list)
  1854. bl.canvas = self.canvas
  1855. ls = bl.get_spline()
  1856. self.id = self.canvas.create_polygon(ls,fill=color,tags=tag)
  1857. """
  1858. try:
  1859. ls = calcuCurve.get_bezierList(self.anc_list,15)
  1860. id = self.canvas.create_polygon(ls,fill=color,
  1861. tags=tag)
  1862. self.id = id
  1863. except ZeroDivisionError:
  1864. print "ZeroDivisionError... please move anc"
  1865. return
  1866. """
  1867.  
  1868. def _polygon(self,tag,color):
  1869. ls = []
  1870. for a in self.anc_list:
  1871. ls.append([a.x,a.y,a.width])
  1872. ls = calcuCurve.width_point(ls)
  1873. #print ls
  1874. ls[1].reverse()
  1875. ls = ls[0]+ls[1]
  1876. lss = []
  1877. for l in ls:
  1878. lss.append(l[0])
  1879. lss.append(l[1])
  1880. self.id = self.canvas.create_polygon(lss,width=0,fill=color,
  1881. tags=tag, smooth=True)
  1882. return
  1883.  
  1884. def _arrow(self,tag,color):
  1885. if len(self.anc_list) < 2:
  1886. return
  1887. else:
  1888. width = self.anc_list[0].width*2
  1889. ls = []
  1890. for a in self.anc_list:
  1891. ls.append(a.x)
  1892. ls.append(a.y)
  1893. id = self.canvas.create_line(ls,width=width,fill=color,
  1894. tags=tag, smooth=True,arrow='last')
  1895. self.id = id
  1896.  
  1897.  
  1898. class DrawingAnchor:
  1899.  
  1900. canvas = None
  1901. selected = False
  1902.  
  1903. def __init__(self,x,y):
  1904. self.x = x
  1905. self.y = y
  1906. self.sx = x
  1907. self.sy = y
  1908. self.width = 1.0
  1909. self.tag = "anc_"+str(id(self))
  1910. self.stag= self.tag+"_selecting"
  1911.  
  1912. def __del__(self):
  1913. print("bye",self.tag)
  1914.  
  1915. def get_data(self):
  1916. return [self.x,
  1917. self.y,
  1918. self.width,
  1919. self.tag,
  1920. self.selected]
  1921.  
  1922. def set_data(self,data):
  1923. self.x = data[0]
  1924. self.y = data[1]
  1925. self.sx = data[0]
  1926. self.sy = data[1]
  1927. self.width = data[2]
  1928. self.tag = data[3]
  1929. self.stag = self.tag+"_selecting"
  1930. self.selected = data[4]
  1931.  
  1932. def select_switch(self):
  1933. if self.selected == True:
  1934. self.deselect()
  1935. else:
  1936. self.select()
  1937.  
  1938. def select(self):
  1939. self.selected = True
  1940. self.redraw()
  1941.  
  1942. def deselect(self):
  1943. self.selected = False
  1944. self.redraw()
  1945.  
  1946. def redraw(self):
  1947. self.hide()
  1948. self.show()
  1949.  
  1950. def show(self):
  1951. if self.selected == True:
  1952. self._draw_select()
  1953. self._draw_anc()
  1954.  
  1955. def hide(self):
  1956. self.canvas.delete(self.tag)
  1957. self.canvas.delete(self.tag+"_selecting")
  1958.  
  1959. def _draw_anc(self):
  1960. fill = "white"
  1961. if self.selected:
  1962. fill = "red"
  1963. id =self.canvas.create_oval(self.x-2,self.y-2,self.x+2,self.y+2,
  1964. outline="red",width=1,
  1965. tags = self.tag,fill=fill)
  1966. self.id = id
  1967.  
  1968. def _draw_select(self):
  1969. size = 10
  1970. self.canvas.create_oval(self.x-size,self.y-size,
  1971. self.x+size,self.y+size,
  1972. tags=self.stag,fill="yellow",outline="")
  1973. self.canvas.tag_lower(self.stag)
  1974.  
  1975.  
  1976. class DrawApp(tk.Tk):
  1977.  
  1978. def __init__(self):
  1979. super().__init__()
  1980.  
  1981. self.canvas = tk.Canvas(self, bg="white")
  1982. self.canvas.pack(fill=tk.BOTH,expand=True)
  1983. DrawingAnchor.canvas = self.canvas
  1984. DrawingObject.canvas = self.canvas
  1985. Curve.canvas = self.canvas
  1986. MainCanvas.canvas = self.canvas
  1987.  
  1988. self.main = MainCanvas(self)
  1989. self.set_gui()
  1990. self.main.msg = self.msg
  1991. self.main.line_type = self.line_type
  1992.  
  1993. def set_gui(self):
  1994.  
  1995. frame = tk.Frame(self)
  1996. frame.pack(fill=tk.BOTH)
  1997. self.base_menu = tk.Frame(frame)
  1998. self.message_menu = tk.Frame(frame)
  1999.  
  2000. #option_menu
  2001. LINES = ["MainLine", "SubLine1", "SubLine2"]
  2002. self.line_type = tk.StringVar()
  2003. self.line_type.set(LINES[0])
  2004. b = tk.OptionMenu(self.base_menu, self.line_type, *LINES)
  2005. b.pack(side=tk.LEFT)
  2006.  
  2007. #menu
  2008. file_btn = tk.Menubutton(self.base_menu,text='File')
  2009. menu = tk.Menu(file_btn,tearoff=False)
  2010. menu.add_command(label='Open...',command=self.main.open)
  2011. menu.add_command(label='Save...',command=self.main.save)
  2012. menu.add_command(label='Import', command=self.main.import_)
  2013. menu.add_command(label='Export', command=self.main.export)
  2014. file_btn.configure(menu=menu)
  2015. file_btn.pack(side=tk.LEFT)
  2016.  
  2017. view_btn = tk.Menubutton(self.base_menu,text='View')
  2018. menu = tk.Menu(view_btn,tearoff=False)
  2019. menu.add_command(label='Zoom')
  2020. menu.add_command(label='View All')
  2021. menu.add_command(label='Backgraund Image...',
  2022. command=self.main.select_under_image)
  2023. view_btn.configure(menu=menu)
  2024. view_btn.pack(side=tk.LEFT)
  2025.  
  2026. option_btn = tk.Menubutton(self.base_menu,text='Option')
  2027. menu = tk.Menu(option_btn,tearoff=False)
  2028. menu.add_command(label='Setting')
  2029. option_btn.configure(menu=menu)
  2030. option_btn.pack(side=tk.LEFT)
  2031.  
  2032. #make_message(self):
  2033. self.msg = tk.StringVar()
  2034. m = tk.Label(self.base_menu,textvariable=self.msg,fg='#666666')
  2035. m.pack(side=tk.RIGHT)
  2036.  
  2037. self.base_menu.pack(side=tk.LEFT,fill=tk.X)
  2038. self.message_menu.pack_forget()
  2039.  
  2040. def main():
  2041. app = DrawApp()
  2042. app.mainloop()
  2043.  
  2044.  
  2045. if __name__ == '__main__':
  2046. main()
  2047.  
ページトップへ