1
0

board.py 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. import time
  2. import os
  3. import logging
  4. import pygame
  5. from pygame.locals import *
  6. from draftboard.toolbox import tool_box
  7. from system import basicConfig, QueueController
  8. queue_controller = QueueController()
  9. logging.basicConfig(**basicConfig)
  10. # 定义一些变量
  11. pen_color = [0, 0, 0] # 画笔颜色
  12. increasing_color = [0, 0, 255]
  13. subtraction_color = [255, 0, 0]
  14. pen_weight = 2 # 圆形的粗细(线条*2)=中笔
  15. previous_x = None
  16. previous_y = None # 为画图所准备的
  17. continuous_draw = False # 设置免按
  18. coordinate_system_drawing_method = 0
  19. coordinate_click_point = [0, 0, 0] # 根据点击中键记录坐标系的点,没有记录则为数字0,记录则为数组
  20. record_origin_x = 0
  21. record_origin_y = 0 # 原点坐标
  22. horizontal_pixels = [] # X点
  23. ordinate_pixels = [] # Y点
  24. horizontal_scale = [] # X个数
  25. ordinate_scale = [] # Y个数
  26. anchor_x = []
  27. anchor_y = []
  28. span = 60 # 坐标系跨度调节
  29. middle_key = 0 # 中键模式
  30. line = [] # 画线列表
  31. rect = [] # 画矩阵和圆列表
  32. poly = [] # 画多边形列表
  33. tips = '' # 设置备注
  34. save_dir = '' # 保存路径
  35. bottom_tip = [0, 0, 0, 0, 0] # 底部显示信息[x,y,左键,中间,右键]
  36. mode = {1: '绘制坐标系', 2: '绘制直线(g)', 3: '填充矩形(f)', 4: '线条矩形(s)',
  37. 5: '绘制横线(k)', 6: '绘制竖线(l)', 7: '绘制多段线(j)',
  38. 8: '绘制横打点多段线(i)', 9: '绘制竖打点多段线(u)', 10: '坐标测绘(h)',
  39. 11: '绘制虚线(q)', 12: '填充圆形(c)', 13: '线条圆形(v)', 14: '多边形(n-填充,m-线条)',
  40. 15: '填充椭圆形(e)', 16: '线条椭圆形(r)', 0: 'None'} # 快捷键名字
  41. SCREEN_X = 900
  42. SCREEN_Y = 700
  43. init_done = None
  44. FONT = None
  45. SCREEN = None
  46. SCREEN_CAPTION = None
  47. def start_gui():
  48. global init_done, FONT, SCREEN, SCREEN_CAPTION
  49. init_done = pygame.init() # 初始化所有模块
  50. FONT = pygame.font.Font(fr'Font{os.sep}ZKST.ttf', 16) # 设置字体(Linux下应该用\而不是/)
  51. SCREEN = pygame.display.set_mode((SCREEN_X, SCREEN_Y), 0) # 创建屏幕
  52. SCREEN_CAPTION = pygame.display.set_caption('CoTan草稿板') # 定义标题(后期加上定义Logo)
  53. SCREEN.fill([255, 255, 255]) # 默认用白色填充窗口
  54. pygame.display.set_icon(pygame.image.load(f'Pic{os.sep}favicon.ico'))
  55. def func_draw(func_list, pixel_accuracy=1000):
  56. global horizontal_pixels, horizontal_scale, ordinate_pixels, ordinate_scale, anchor_y, anchor_x, pen_color
  57. global increasing_color, subtraction_color
  58. c = [0, 0, 0] # 增函数颜色
  59. def x_convert_pixels(x_coordinate):
  60. return ((x_coordinate - horizontal_scale[0]) / (horizontal_scale[1] - horizontal_scale[0]) *
  61. (horizontal_pixels[1] - horizontal_pixels[0]) + horizontal_pixels[0])
  62. def y_convert_pixels(y_coordinate):
  63. return ((y_coordinate - ordinate_scale[0]) / (ordinate_scale[1] - ordinate_scale[0]) *
  64. (ordinate_pixels[1] - ordinate_pixels[0]) + ordinate_pixels[0])
  65. for i in func_list:
  66. last_x = None # 上一组X和Y
  67. last_y = None
  68. if func_list is None:
  69. continue
  70. func = func_list[i]
  71. try:
  72. for x in range((horizontal_scale[0] - 1) * pixel_accuracy, (horizontal_scale[1] + 1) * pixel_accuracy, 1):
  73. x /= pixel_accuracy
  74. try:
  75. y = func(x)
  76. except ValueError:
  77. last_x = None
  78. last_y = None
  79. continue
  80. try:
  81. now_x = x_convert_pixels(x)
  82. now_y = y_convert_pixels(y)
  83. if now_y > anchor_y[0] or now_y < anchor_y[1] or now_x < anchor_x[0] or now_x > anchor_x[1]:
  84. last_x = None
  85. last_y = None
  86. continue
  87. except TypeError: # 预防复数
  88. continue
  89. if last_x is not None:
  90. if last_y > now_y:
  91. c = increasing_color # 增函数
  92. elif last_y < now_y:
  93. c = subtraction_color # 减函数#改为检查Y数值而不是坐标
  94. pygame.draw.line(
  95. SCREEN, c, (int(last_x), int(last_y)), (int(now_x), int(now_y)), pen_weight)
  96. last_x = now_x
  97. last_y = now_y
  98. except IndexError:
  99. break
  100. def draw_line(xy_coordinates: (list, tuple), with_point=False):
  101. global previous_x, previous_y
  102. if with_point:
  103. pygame.draw.circle(SCREEN, pen_color, xy_coordinates, pen_weight, 0)
  104. if previous_x is not None:
  105. pygame.draw.line(SCREEN, pen_color, (previous_x, previous_y), xy_coordinates, pen_weight)
  106. previous_x = xy_coordinates[0]
  107. previous_y = xy_coordinates[1]
  108. def coordinate_draw(origin_x, origin_y, x_interval=(-100, 100), # 三个点中,两边的两个点距离原点距离的一个list
  109. y_interval=(-200, 100), scale_span=10, width=3, arrow=3, origin=3):
  110. scale_span = abs(scale_span) # kd大于0
  111. global pen_weight, record_origin_x, record_origin_y, horizontal_scale, horizontal_pixels, ordinate_scale
  112. global ordinate_pixels, anchor_x, anchor_y
  113. record_origin_x = origin_x
  114. record_origin_y = origin_y # 存储原点坐标
  115. anchor_x = [origin_x + x_interval[0], origin_x + x_interval[1]] # 定位点
  116. anchor_y = [origin_y + y_interval[1], origin_y + y_interval[0]]
  117. pygame.draw.circle(SCREEN, pen_color, (origin_x, origin_y), origin, 0) # 绘制原点
  118. pygame.draw.line(
  119. SCREEN, pen_color, (origin_x + x_interval[0], origin_y), (origin_x + x_interval[1], origin_y), pen_weight)
  120. pygame.draw.line(
  121. SCREEN, pen_color, (origin_x, origin_y + y_interval[0]), (origin_x, origin_y + y_interval[1]), pen_weight)
  122. negative_scale = 0 # 刻度统计
  123. negative_pixels = 0
  124. for i in range(origin_x, origin_x + x_interval[0], -scale_span): # 右
  125. negative_scale -= 1
  126. pygame.draw.line(SCREEN, pen_color, (i, origin_y + width), (i, origin_y), pen_weight)
  127. negative_pixels = i
  128. positive_scale = 0
  129. positive_pixels = 0
  130. for i in range(origin_x, origin_x + x_interval[1], scale_span): # 刻度#左
  131. positive_scale += 1
  132. pygame.draw.line(SCREEN, pen_color, (i, origin_y + width), (i, origin_y), pen_weight)
  133. positive_pixels = i
  134. horizontal_scale = [negative_scale + 1, positive_scale - 1]
  135. horizontal_pixels = [negative_pixels, positive_pixels]
  136. negative_scale = 0
  137. negative_pixels = 0
  138. for i in range(origin_y, origin_y + y_interval[0], -scale_span): # 上
  139. negative_scale += 1
  140. pygame.draw.line(SCREEN, pen_color, (origin_x + width, i), (origin_x, i), pen_weight)
  141. negative_pixels = i
  142. positive_scale = 0
  143. positive_pixels = 0
  144. for i in range(origin_y, origin_y + y_interval[1], scale_span): # 下
  145. positive_scale -= 1
  146. pygame.draw.line(SCREEN, pen_color, (origin_x + width, i), (origin_x, i), pen_weight)
  147. positive_pixels = i
  148. ordinate_scale = [positive_scale + 1, negative_scale - 1]
  149. ordinate_pixels = [positive_pixels, negative_pixels]
  150. # 箭头
  151. pygame.draw.line(
  152. SCREEN,
  153. pen_color,
  154. (origin_x + x_interval[1],
  155. origin_y),
  156. (origin_x + x_interval[1] - arrow,
  157. origin_y + arrow),
  158. pen_weight) # X上
  159. pygame.draw.line(
  160. SCREEN,
  161. pen_color,
  162. (origin_x + x_interval[1],
  163. origin_y),
  164. (origin_x + x_interval[1] - arrow,
  165. origin_y - arrow),
  166. pen_weight) # X下
  167. pygame.draw.line(
  168. SCREEN,
  169. pen_color,
  170. (origin_x,
  171. origin_y + y_interval[0]),
  172. (origin_x - arrow,
  173. origin_y + y_interval[0] + arrow),
  174. pen_weight) # y左
  175. pygame.draw.line(
  176. SCREEN,
  177. pen_color,
  178. (origin_x,
  179. origin_y + y_interval[0]),
  180. (origin_x + arrow,
  181. origin_y + y_interval[0] + arrow),
  182. pen_weight) # X下
  183. def top_draw():
  184. # 绘制顶部
  185. global pen_weight, FONT, bottom_tip, SCREEN_X, SCREEN_Y, middle_key, save_dir, mode, continuous_draw, tips, line
  186. global record_origin_x, record_origin_y, rect, poly, pen_color, increasing_color, subtraction_color
  187. global coordinate_click_point, span
  188. if continuous_draw:
  189. key_d = '启动无点击画线(点击d关闭)'
  190. else:
  191. key_d = '关闭无点击画线'
  192. pygame.draw.rect(SCREEN, [255, 255, 255], [0, 0, SCREEN_X, 16], 0)
  193. pygame.draw.rect(
  194. SCREEN, [
  195. 255, 255, 255], [
  196. 0, SCREEN_Y - 16, SCREEN_X, SCREEN_Y], 0)
  197. point = ''
  198. if middle_key == 0:
  199. tips = ''
  200. if coordinate_click_point != [0, 0, 0]:
  201. a = []
  202. for i in coordinate_click_point:
  203. if i != 0:
  204. a.append(i)
  205. point += f'坐标端点:{str(a)} '
  206. if line:
  207. point += f'端点:{str(line)} '
  208. if rect:
  209. point += f'顶点(圆心):{str(rect)} '
  210. if poly:
  211. point += f'多顶点:{str(poly)} '
  212. if continuous_draw or middle_key != 0:
  213. model_tip = FONT.render(
  214. f'模式:{key_d} , {mode[middle_key]} {tips}', True, (0, 0, 0))
  215. else:
  216. s = ''
  217. if save_dir:
  218. s = f'保存路径(w):{save_dir}'
  219. model_tip = FONT.render(
  220. f'{time.strftime("%Y/%m/%d %I:%M")} {s}', True, (0, 0, 0))
  221. point = ''
  222. if point == '':
  223. point = f'主色调:{pen_color} 增函数颜色:{increasing_color} 减函数颜色:{subtraction_color}'
  224. mouse_tip = FONT.render(f'鼠标:{bottom_tip[0]},{bottom_tip[1]}', True, (0, 0, 0))
  225. status_tip = FONT.render(
  226. f'{bottom_tip[2]},{bottom_tip[3]},{bottom_tip[4]} ; 大小:{pen_weight} ; '
  227. f'原点:{record_origin_x},{record_origin_y}'
  228. f' ; 跨度:{span} ; {point}',
  229. True,
  230. (0,
  231. 0,
  232. 0))
  233. SCREEN.blit(mouse_tip, (0, 0))
  234. SCREEN.blit(status_tip, (100, 0))
  235. SCREEN.blit(model_tip, (0, SCREEN_Y - 16))
  236. def draw_main(in_queue, out_queue):
  237. global previous_x, previous_y, pen_color, pen_weight, coordinate_system_drawing_method
  238. global coordinate_click_point, record_origin_x
  239. global record_origin_y, span, line
  240. global continuous_draw, middle_key, rect, poly, SCREEN, SCREEN_CAPTION, init_done, previous_x, previous_y, save_dir
  241. global increasing_color, subtraction_color, bottom_tip, FONT, SCREEN_X, SCREEN_Y, tips
  242. start_gui()
  243. queue_controller.set_queue(in_queue, out_queue)
  244. queue_controller()
  245. flat = True # 循环条件(不是全局)
  246. while flat:
  247. top_draw()
  248. pygame.display.update() # 屏幕刷新
  249. for event in pygame.event.get(): # 事件检查
  250. if event.type == QUIT: # 退出事件
  251. pygame.quit()
  252. flat = False
  253. break
  254. elif event.type == MOUSEMOTION: # 鼠标移动事件
  255. bottom_tip[0], bottom_tip[1] = event.pos
  256. bottom_tip[2], bottom_tip[3], bottom_tip[4] = event.buttons
  257. if event.buttons == (1, 0, 0): # 左键点击
  258. draw_line(event.pos)
  259. elif event.buttons == (0, 0, 0): # 无点击绘图(启动快捷键d)
  260. if continuous_draw:
  261. draw_line(event.pos)
  262. else: # m_x和m_y是指上一点的xy,用于画线系统
  263. previous_x = None
  264. previous_y = None
  265. elif event.type == MOUSEBUTTONDOWN: # 鼠标按下
  266. event.pos = list(event.pos)
  267. if event.button == 3: # 右键点击
  268. bottom_tip[4] = 1
  269. pygame.image.save(SCREEN, '$CoTanCC.png') # 保存当前环境
  270. SCREEN = pygame.display.set_mode(
  271. (SCREEN_X, SCREEN_Y), pygame.NOFRAME) # 隐藏关闭按钮
  272. background_image = pygame.image.load('$CoTanCC.png').convert() # 加载位图
  273. SCREEN.blit(background_image, (0, 0)) # 绘制位图
  274. pygame.display.update() # 更新屏幕
  275. tool_set = tool_box() # 启动工具箱
  276. SCREEN = pygame.display.set_mode((SCREEN_X, SCREEN_Y), 0) # 显示关闭按钮
  277. background_image = pygame.image.load('$CoTanCC.png').convert() # 加载位图
  278. SCREEN.blit(background_image, (0, 0)) # 绘制位图
  279. pygame.display.update() # 更新屏幕
  280. os.remove('$CoTanCC.png')
  281. if tool_set[0] is not None:
  282. pen_color = tool_set[0] # 设置颜色
  283. if tool_set[1] is not None:
  284. pen_weight = tool_set[1] # 设置笔的粗细
  285. if tool_set[2] is not None:
  286. SCREEN.fill(tool_set[2]) # 设置背景填充
  287. if tool_set[3] == 1: # 绘制坐标系
  288. tips = '选择坐标三个端点'
  289. middle_key = 1
  290. coordinate_system_drawing_method = 3
  291. span = 60
  292. elif tool_set[3] == 2: # 绘制坐标系2(小跨度)
  293. tips = '选择坐标三个端点'
  294. middle_key = 1
  295. coordinate_system_drawing_method = 3
  296. span = 20
  297. elif tool_set[3] == 3: # 绘制坐标系3(大跨度)
  298. tips = '选择坐标三个端点'
  299. middle_key = 1
  300. coordinate_system_drawing_method = 3
  301. span = 120 # 坐标系跨度(字定义跨度再下面)
  302. else:
  303. middle_key = 0
  304. coordinate_system_drawing_method = 0 # 恢复选项
  305. if tool_set[6] is not None:
  306. increasing_color = tool_set[6] # 增函数颜色(要在函数绘制之前设置好)
  307. if tool_set[7] is not None:
  308. subtraction_color = tool_set[7] # 减函数颜色
  309. if tool_set[4] != {}:
  310. func_draw(tool_set[4]) # 函数绘制
  311. if tool_set[5] is not None:
  312. pygame.image.save(SCREEN, tool_set[5]) # 保存当前环境
  313. save_dir = tool_set[5]
  314. if tool_set[8] is not None:
  315. span = tool_set[8] # 自定义跨度
  316. if tool_set[9] is not None:
  317. try:
  318. bg_im = pygame.image.load(tool_set[9]).convert() # 加载位图
  319. SCREEN.blit(bg_im, (0, 0)) # 绘制位图
  320. except BaseException as e:
  321. logging.warning(str(e))
  322. # 恢复参数
  323. previous_x = None
  324. previous_y = None
  325. continuous_draw = False
  326. pygame.event.clear()
  327. elif event.button == 2: # 中键点击,ZJ是指中键的模式,来自快捷键和工具箱
  328. bottom_tip[3] = 1
  329. if middle_key == 1: # 坐标系模式
  330. tips = '选择下一个端点(共3个)'
  331. coordinate_click_point[coordinate_system_drawing_method - 1] = event.pos # 存储
  332. coordinate_system_drawing_method -= 1
  333. if coordinate_system_drawing_method == 0:
  334. x = []
  335. y = []
  336. for i in coordinate_click_point:
  337. x.append(i[0])
  338. y.append(i[1])
  339. x.sort()
  340. y.sort() # 排序
  341. s_x = x[1]
  342. s_y = y[1]
  343. p = (-abs(x[0] - x[1]), abs(x[1] - x[2]))
  344. c = (-abs(y[0] - y[1]), abs(y[1] - y[2]))
  345. b = 2 * pen_weight
  346. r = 2 * pen_weight
  347. jt = 3 * pen_weight
  348. coordinate_draw(s_x, s_y, p, c, span, b, jt, r)
  349. coordinate_click_point = [0, 0, 0]
  350. middle_key = 0
  351. elif middle_key == 2: # 画线模式
  352. line.append(event.pos)
  353. # pygame.draw.circle(root, pen_C, event.pos, d, 0)
  354. if len(line) == 2:
  355. pygame.draw.line(
  356. SCREEN, pen_color, line[0], line[1], pen_weight)
  357. middle_key = 0
  358. elif middle_key == 3 or middle_key == 4: # 画矩形模式
  359. rect.append(event.pos)
  360. if len(rect) == 2:
  361. x = [rect[0][0], rect[1][0]]
  362. y = [rect[0][1], rect[1][1]]
  363. x.sort()
  364. y.sort()
  365. if middle_key == 3:
  366. dx = 0
  367. else:
  368. dx = pen_weight
  369. pygame.draw.rect(
  370. SCREEN, pen_color, [
  371. x[0], y[0], x[1] - x[0], y[1] - y[0]], dx)
  372. middle_key = 0
  373. elif middle_key == 5: # 画横线模式
  374. line.append(event.pos)
  375. if len(line) == 2:
  376. pygame.draw.line(
  377. SCREEN, pen_color, line[0], (line[1][0], line[0][1]), pen_weight)
  378. middle_key = 0
  379. elif middle_key == 6: # 画竖线模式
  380. line.append(event.pos)
  381. if len(line) == 2:
  382. pygame.draw.line(
  383. SCREEN, pen_color, line[0], (line[0][0], line[1][1]), pen_weight)
  384. middle_key = 0
  385. elif middle_key == 7: # 画线多段线
  386. line.append(event.pos)
  387. if len(line) == 2:
  388. pygame.draw.line(
  389. SCREEN, pen_color, line[0], line[1], pen_weight)
  390. del line[0]
  391. elif middle_key == 8: # 画横线多段线
  392. line.append(event.pos)
  393. if len(line) == 2:
  394. pygame.draw.line(
  395. SCREEN, pen_color, line[0], (line[1][0], line[0][1]), pen_weight)
  396. pygame.draw.circle(
  397. SCREEN, pen_color, (line[1][0], line[0][1]), pen_weight * 2, 0)
  398. del line[1]
  399. else:
  400. pygame.draw.circle(
  401. SCREEN, pen_color, event.pos, pen_weight, 0)
  402. elif middle_key == 9: # 画竖线多段线
  403. line.append(event.pos)
  404. if len(line) == 2:
  405. pygame.draw.line(
  406. SCREEN, pen_color, line[0], (line[0][0], line[1][1]), pen_weight)
  407. pygame.draw.circle(
  408. SCREEN, pen_color, (line[0][0], line[1][1]), pen_weight * 2, 0)
  409. del line[1]
  410. else:
  411. pygame.draw.circle(
  412. SCREEN, pen_color, event.pos, pen_weight, 0)
  413. elif middle_key == 10: # 画竖线和横线多段线
  414. line.append(event.pos)
  415. if len(line) == 2:
  416. pygame.draw.line(
  417. SCREEN, pen_color, line[0], (line[1][0], line[0][1]), pen_weight) # 横线
  418. pygame.draw.circle(
  419. SCREEN, pen_color, (line[1][0], line[0][1]), pen_weight * 2, 0)
  420. pygame.draw.circle(
  421. SCREEN, pen_color, (line[1][0], line[1][1]), pen_weight * 2, 0)
  422. pygame.draw.line(
  423. SCREEN, pen_color, line[0], (line[0][0], line[1][1]), pen_weight) # 竖线
  424. pygame.draw.circle(
  425. SCREEN, pen_color, (line[0][0], line[1][1]), pen_weight * 2, 0)
  426. # 垂直于横线的虚线
  427. p = sorted([line[1][1], line[0][1]])
  428. y1 = p[0]
  429. y2 = p[1]
  430. a = list(range(y1, y2, 10))
  431. for i in range(
  432. int(len(a) / 2)): # 向下取整,可用math.ceil代替
  433. i += 1
  434. i = 2 * i - 1
  435. y1 = a[i - 1] # 计算两点的y坐标
  436. y2 = a[i]
  437. pygame.draw.line(
  438. SCREEN, pen_color, (line[1][0], y1), (line[1][0], y2), pen_weight) # 横线
  439. # 垂直于竖线的虚线
  440. p = [line[1][0], line[0][0]]
  441. p.sort()
  442. x1 = p[0]
  443. x2 = p[1]
  444. a = list(range(x1, x2, 10))
  445. for i in range(
  446. int(len(a) / 2)): # 向下取整,可用math.ceil代替
  447. i += 1
  448. i = 2 * i - 1
  449. x1 = a[i - 1] # 计算两点的x坐标
  450. x2 = a[i]
  451. pygame.draw.line(
  452. SCREEN, pen_color, (x1, line[1][1]), (x2, line[1][1]), pen_weight) # 横线
  453. del line[1]
  454. else:
  455. pygame.draw.circle(
  456. SCREEN, pen_color, event.pos, pen_weight, 0)
  457. elif middle_key == 11: # 画虚线线模式
  458. line.append(event.pos)
  459. pygame.draw.circle(
  460. SCREEN, pen_color, event.pos, pen_weight, 0)
  461. if len(line) == 2:
  462. if abs(line[0][0] - line[1][0]) >= 100:
  463. p1 = [line[0][0], line[1][0]]
  464. p2 = {
  465. line[0][0]: line[0][1],
  466. line[1][0]: line[1][1]}
  467. p1.sort()
  468. x1 = p1[0]
  469. y1 = p2[x1]
  470. x2 = p1[1]
  471. y2 = p2[x2]
  472. a = list(range(x1, x2, 10))
  473. for i in range(
  474. int(len(a) / 2)): # 向下取整,可用math.ceil代替
  475. i += 1
  476. i = 2 * i - 1
  477. x1 = a[i - 1] # 计算两点的x坐标
  478. x2 = a[i]
  479. y1 = (x1 - x1) / (x2 - x1) * (y2 - y1) + y1
  480. y2 = (x2 - x1) / (x2 - x1) * (y2 - y1) + y1
  481. pygame.draw.line(
  482. SCREEN, pen_color, (x1, y1), (x2, y2), pen_weight) # 横线
  483. elif abs(line[0][1] - line[1][1]) >= 100:
  484. p1 = [line[0][1], line[1][1]]
  485. p2 = {
  486. line[0][1]: line[0][0],
  487. line[1][1]: line[1][0]}
  488. p1.sort()
  489. y1 = p1[0]
  490. x1 = p2[y1]
  491. y2 = p1[1]
  492. x2 = p2[y2]
  493. a = list(range(y1, y2, 10))
  494. for i in range(
  495. int(len(a) / 2)): # 向下取整,可用math.ceil代替
  496. i += 1
  497. i = 2 * i - 1
  498. y1 = a[i - 1] # 计算两点的x坐标
  499. y2 = a[i]
  500. x1 = (y1 - y1) / (y2 - y1) * (x2 - x1) + x1
  501. x2 = (y2 - y1) / (y2 - y1) * (x2 - x1) + x1
  502. pygame.draw.line(
  503. SCREEN, pen_color, (x1, y1), (x2, y2), pen_weight) # 横线
  504. else:
  505. pygame.draw.line(
  506. SCREEN, pen_color, line[1], line[0], pen_weight)
  507. middle_key = 0
  508. elif middle_key == 12: # 画圆模式
  509. rect.append(event.pos)
  510. if len(rect) == 2:
  511. # 两点间求距离
  512. r = int(
  513. ((rect[0][0] - rect[1][0]) ** 2 + (rect[0][1] - rect[1][1]) ** 2) ** (1 / 2))
  514. pygame.draw.circle(SCREEN, pen_color, rect[0], r, 0)
  515. middle_key = 0
  516. else:
  517. pygame.draw.circle(
  518. SCREEN, pen_color, rect[0], pen_weight * 2, 0)
  519. elif middle_key == 13: # 画圆线框模式
  520. rect.append(event.pos)
  521. if len(rect) == 2:
  522. # 两点间求距离
  523. r = int(
  524. ((rect[0][0] - rect[1][0]) ** 2 + (rect[0][1] - rect[1][1]) ** 2) ** (1 / 2))
  525. pygame.draw.circle(
  526. SCREEN, pen_color, rect[0], r, pen_weight)
  527. middle_key = 0
  528. else:
  529. pygame.draw.circle(
  530. SCREEN, pen_color, rect[0], pen_weight, 0)
  531. elif middle_key == 14: # 画多边形模式
  532. line.append(event.pos)
  533. if len(line) == 2:
  534. pygame.draw.line(
  535. SCREEN, pen_color, line[0], line[1], pen_weight)
  536. del line[0]
  537. poly.append(event.pos)
  538. elif middle_key == 15: # 画椭圆模式
  539. rect.append(event.pos)
  540. if len(rect) == 2:
  541. x = [rect[0][0], rect[1][0]]
  542. y = [rect[0][1], rect[1][1]]
  543. x.sort()
  544. y.sort()
  545. pygame.draw.ellipse(
  546. SCREEN, pen_color, [
  547. x[0], y[0], x[1] - x[0], y[1] - y[0]], 0)
  548. middle_key = 0
  549. elif middle_key == 16: # 画椭圆边框模式
  550. rect.append(event.pos)
  551. if len(rect) == 2:
  552. x = [rect[0][0], rect[1][0]]
  553. y = [rect[0][1], rect[1][1]]
  554. x.sort()
  555. y.sort()
  556. pygame.draw.ellipse(
  557. SCREEN, pen_color, [
  558. x[0], y[0], x[1] - x[0], y[1] - y[0]], pen_weight)
  559. middle_key = 0
  560. elif event.button == 1:
  561. bottom_tip[2] = 1
  562. pygame.draw.circle(
  563. SCREEN, pen_color, event.pos, pen_weight, 0)
  564. previous_x = event.pos[0]
  565. previous_y = event.pos[1]
  566. elif event.type == KEYDOWN: # 键盘按下(长按不算)快捷键
  567. if event.key == K_d: # 不用点击左键画线
  568. if continuous_draw:
  569. continuous_draw = False
  570. else:
  571. continuous_draw = True
  572. previous_x = None
  573. previous_y = None
  574. elif event.key == K_g: # 画直线
  575. tips = '根据两个端点画直线'
  576. middle_key = 2
  577. line = []
  578. rect = []
  579. poly = []
  580. elif event.key == K_f: # 画矩阵
  581. middle_key = 3
  582. tips = '根据两个相对的顶点绘制矩形'
  583. line = []
  584. rect = []
  585. poly = []
  586. elif event.key == K_s: # 画矩阵边框
  587. middle_key = 4
  588. tips = '根据两个相对的顶点绘制矩形'
  589. line = []
  590. rect = []
  591. poly = []
  592. elif event.key == K_k: # 画横线
  593. middle_key = 5
  594. tips = '选择起点和与终点y坐标相同的点'
  595. line = []
  596. rect = []
  597. poly = []
  598. elif event.key == K_l: # 画竖线
  599. middle_key = 6
  600. tips = '选择起点和与终点x坐标相同的点'
  601. line = []
  602. rect = []
  603. poly = []
  604. elif event.key == K_j: # 多段线
  605. if middle_key == 7:
  606. middle_key = 0
  607. else:
  608. middle_key = 7
  609. tips = '依次选择多段线的顶点'
  610. line = []
  611. rect = []
  612. poly = []
  613. elif event.key == K_i: # 多段线横线打点
  614. if middle_key == 8:
  615. middle_key = 0
  616. else:
  617. middle_key = 8
  618. tips = '选择终点,依次选择与其他端点y坐标相同的点(点击i结束)'
  619. line = []
  620. rect = []
  621. poly = []
  622. elif event.key == K_u: # 多段线竖线打点
  623. if middle_key == 9:
  624. middle_key = 0
  625. else:
  626. middle_key = 9
  627. tips = '选择终点,依次选择与其他端点x坐标相同的点(点击u结束)'
  628. line = []
  629. rect = []
  630. poly = []
  631. elif event.key == K_h: # 多段横竖线打点
  632. if middle_key == 10:
  633. middle_key = 0
  634. else:
  635. middle_key = 10
  636. tips = '选择参考点,再选择研究对象(点击h结束)'
  637. line = []
  638. rect = []
  639. poly = []
  640. elif event.key == K_q: # 绘制虚线
  641. middle_key = 11
  642. tips = '选择虚线的两个端点'
  643. line = []
  644. rect = []
  645. poly = []
  646. elif event.key == K_c: # 绘制圆形
  647. middle_key = 12
  648. tips = '选择圆形和圆上任意一点(确定半径)'
  649. line = []
  650. rect = []
  651. poly = []
  652. elif event.key == K_v: # 绘制圆形线框
  653. middle_key = 13
  654. tips = '选择圆形和圆上任意一点(确定半径)'
  655. line = []
  656. rect = []
  657. poly = []
  658. elif event.key == K_o: # 捕捉
  659. tips = '起点已经捕捉到坐标系原点了'
  660. line = [[record_origin_x, record_origin_y]]
  661. rect = [[record_origin_x, record_origin_y]]
  662. poly = [[record_origin_x, record_origin_y]]
  663. elif event.key == K_y: # 捕捉上y轴
  664. if len(line) >= 1:
  665. tips = '起点已经移动到坐标系y轴上了'
  666. line[0][0] = record_origin_x
  667. if len(rect) >= 1:
  668. tips = '起点已经移动到坐标系y轴上了'
  669. rect[0][0] = record_origin_x
  670. if len(poly) >= 1:
  671. tips = '起点已经移动到坐标系y轴上了'
  672. rect[0][0] = record_origin_x
  673. elif event.key == K_x: # 捕捉上x轴
  674. if len(line) >= 1:
  675. tips = '起点已经移动到坐标系x轴上了'
  676. line[0][1] = record_origin_y
  677. if len(rect) >= 1:
  678. tips = '起点已经移动到坐标系x轴上了'
  679. rect[0][1] = record_origin_y
  680. if len(poly) >= 1:
  681. tips = '起点已经移动到坐标系x轴上了'
  682. rect[0][1] = record_origin_y
  683. elif event.key == K_n: # 画多边形
  684. if middle_key == 14:
  685. middle_key = 0
  686. pygame.draw.polygon(SCREEN, pen_color, poly, 0)
  687. else:
  688. tips = '依次选择多边形的各个端点(点击n闭合并填充)'
  689. middle_key = 14
  690. elif event.key == K_m: # 画多边形边框
  691. if middle_key == 14:
  692. middle_key = 0
  693. pygame.draw.polygon(SCREEN, pen_color, poly, pen_weight)
  694. else:
  695. tips = '依次选择多边形的各个端点(点击m闭合)'
  696. middle_key = 14
  697. line = []
  698. rect = []
  699. poly = []
  700. elif event.key == K_e: # 绘制填充椭圆
  701. middle_key = 15
  702. tips = '选择椭圆外界矩形的两个相对的顶点'
  703. line = []
  704. rect = []
  705. poly = []
  706. elif event.key == K_r: # 绘制椭圆边框
  707. middle_key = 16
  708. tips = '选择椭圆外界矩形的两个相对的顶点'
  709. line = []
  710. rect = []
  711. poly = []
  712. elif event.key == K_w: # 保存
  713. if save_dir != '':
  714. pygame.image.save(SCREEN, save_dir) # 保存当前环境
  715. elif event.key == K_b: # 清空当前操作
  716. middle_key = 0
  717. line = []
  718. rect = []
  719. poly = []
  720. queue_controller.stop_process()
  721. # 快捷键操作指南
  722. # d-不用点击左键画线(再次点击关闭)
  723. # g-画直线
  724. # f-画填充矩阵
  725. # s-画矩阵边框
  726. # k-画横线
  727. # l-画竖线
  728. # j-画多段线
  729. # i-横线多段线打点(再次点击结束绘制)
  730. # u-竖线多段线打点(再次点击结束绘制)
  731. # h-横线和竖线多段线打点并由虚线标注(再次点击结束绘制)
  732. # q-绘制虚线
  733. # c-绘制填充圆形
  734. # v-绘制圆形边框
  735. # n和m-绘制多边形
  736. # n-再次点击完成填充多边形绘制
  737. # m-再次点击完成多边形边框绘制
  738. # o-捕捉坐标原点(请先点击功能快捷键)
  739. # x-捕捉坐标x轴(请先点击功能快捷键并选择起点)
  740. # y-捕捉坐标y轴(同上)
  741. # b-关闭当前所有快捷键操作
  742. # e-绘制填充椭圆
  743. # r-绘制椭圆边框