board.py 36 KB

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