board.py 36 KB

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