Прикреплённый файл «grap_7.py»
Загрузка 1 #!/usr/bin/env python
2 # -*- coding: UTF-8 -*-
3 # vim: expandtab shiftwidth=4
4 '''
5 Проект "Построение графика"
6 Графический редактор в возможностью рисовать графики
7 см. диаграммы PyGameState_*.dia
8 '''
9
10 from math import *
11 import sys
12
13 import pygame
14 pygame.init()
15 pygame.font.init()
16 # Векторы, указывающие на соседнюю точку
17 dxy=[(-1,-1),(-1,0),(-1,1),(0,1),(1,1),(1,0),(1,-1),(0,-1)]
18 dxyW=len(dxy)
19
20 def distance(M1,M2):
21 'Расстояние от точки до точки'
22 return sqrt(float(M1[0]-M2[0])**2+float(M1[1]-M2[1])**2)
23
24 def dxydist(M1, M2, M, R, ind):
25 '''Вспомогательная функция. Вычисляет координаты точек, соседних с M,
26 соответствующих векторам, индексы которых в dxy перечислены в ind;
27 вычисляет, насколько отличается заданное значение R
28 от суммы расстояний от каждой из этих точек до центров эллипса.
29 Возвращает список вида [ (отличие, точка, индекс в dxy), ...]'''
30 return [(abs((R-distance(m,M1)-distance(m,M2))),m,i) for m,i in [((M[0]+dxy[i][0],M[1]+dxy[i][1]),i) for i in ind]]
31
32 def Ellipse(screen, M1, M2, M0, pen, width):
33 'Рисование эллипса по двум центрам и точке M0'
34 L=distance(M1,M2)
35 R=distance(M0,M1)+distance(M0,M2)
36 if int(R)<=int(L):
37 D=[M1,M2]
38 elif L<3:
39 pygame.draw.circle(screen, pen, M1, max(R/2, width), width)
40 return
41 else:
42 D=[M0]
43 r,M,v=min(dxydist(M1, M2, M0, R, range(dxyW)))
44 # здесь иногда вечный цикл: какая-то неточность в расчётах
45 c=0
46 while M!=M0 and c <10020:
47 c+=1
48 if c > 10000: print r,M,v, R, M1, M2
49 D.append(M)
50 r,M,v=min(dxydist(M1, M2, M, R, ((dxyW+v-1)%dxyW,v,(dxyW+v+1)%dxyW)))
51 pygame.draw.polygon(screen, pen, D, width)
52
53 def scale(x, X0, X1, Z0, Z1):
54 'Преобразует координату x в диапазоне [X0, X1] в координату z в диапазоне [Z0, Z1]'
55 return Z0 + (x!=X0 and (Z1-Z0)*(x-X0)/float(X1-X0)) or 0
56
57 def Function(screen, M1, M2, pen, width):
58 'Рисование графика функции fml в диапазоне fml(X0)..fml(X1)'
59 global X0, X1, fml
60 mw,mh=min(M1[0],M2[0]),min(M1[1],M2[1])
61 Mw,Mh=max(M1[0],M2[0]),max(M1[1],M2[1])
62 count=max(Mw-mw,2)
63 dots=[(x,eval(fml)) for x in [scale(i,0,count-1,X0,X1) for i in range(count)]]
64 Y0,Y1=min([e[1] for e in dots]), max([e[1] for e in dots])
65 gr=[(round(scale(x,X0,X1,mw,Mw)),round(scale(y,Y0,Y1,mh,Mh))) for x,y in dots]
66 pygame.draw.lines(screen, pen, False, gr, width)
67
68 def Draw(screen, pen, width, center, pos, figure, center2=None):
69 if figure == "Line":
70 pygame.draw.line(screen, pen, center, pos, width)
71 elif figure == "Rect":
72 pygame.draw.rect(screen, pen, (center, (pos[0]-center[0],pos[1]-center[1])), width)
73 elif figure == "Function":
74 Function(screen, center, pos, pen, width)
75 elif figure == "Circle":
76 r=int(round(distance(center, pos)))
77 pygame.draw.circle(screen, pen, center, max(r, width), width)
78 elif figure == "Ellipse":
79 if center2: # финальная фигура
80 Ellipse(screen, center, center2, pos, pen, width)
81 else: # фигура второй стадии
82 Ellipse(screen, center, (center[0]*.2+pos[0]*.8, center[1]*.2+pos[1]*.8), pos, pen, width)
83
84 def DrawState(screen, event, stages):
85 'Рисование фигуры по точкам'
86 global State, Stage, Center, Copy, pen, width, Action, Center2
87 if event.type == pygame.MOUSEMOTION:
88 if Stage == 2:
89 screen.blit(Copy, (0,0)) # восстанавливаем
90 Draw(screen, pen, width, Center, event.pos, Action)
91 if Stage == 3:
92 screen.blit(Copy, (0,0)) # восстанавливаем
93 Draw(screen, pen, width, Center, event.pos, Action, Center2)
94 elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
95 if Stage == 1: # первое нажатие
96 Stage += 1
97 Center = event.pos
98 Copy = screen.copy() # состояние экрана без нарисованной линии
99 elif Stage == stages: # Последнее нажатие
100 Stage = 1
101 elif Stage == 2: # второе нажатие из более чем двух
102 Stage += 1
103 Center2 = event.pos
104 elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 3:
105 if Stage > 1: # Нарисовано что-то резиновое
106 screen.blit(Copy, (0,0)) # восстанавливаем
107 Stage = 1
108 elif event.type == pygame.KEYDOWN and event.key == 27:
109 screen.blit(Copy, (0,0))
110 State = "Base"
111
112 def ScrInput(screen, prompt, pos):
113 '''Ввести строку с клавиатуры, отображая её.
114 Backspace -- удалить один символ, ESC -- вернуть None'''
115 global Copy
116 res = ""
117 Copy = screen.copy()
118 while True:
119 text = font.render(prompt+": "+res, 1, (255,255,255))
120 screen.blit(Copy, (0,0))
121 screen.blit(text, pos)
122 pygame.display.flip()
123 event = pygame.event.wait()
124 if event.type == pygame.KEYDOWN:
125 if event.unicode: # real characters
126 if event.unicode == u"\033": # ESC
127 res = None
128 break
129 elif event.unicode == "\010": # Backspace
130 res=res[:-1]
131 elif event.unicode in u"\r\n": # Enter
132 break
133 elif event.unicode > u" ": # printable characters
134 res += event.unicode
135 #print event.unicode.__repr__()
136 screen.blit(Copy, (0,0))
137 pygame.display.flip()
138 return res
139
140 def Ask_n_Do(screen, what, prompt):
141 '''Ввести строку, проверить, и сделать с ней что полагается.
142 Вернуть True или False в зависимости от успешности'''
143 global width, pen, fml, X0, X1
144 str_res=ScrInput(screen,u"Введите "+prompt, (10,10))
145 if str_res is None: return False # ввод был прерван
146 try:
147 res = eval(str_res)
148 except: # неизвестно что, пусть это остаётся строкой
149 res = str_res
150 if what == "Width":
151 if type(res) != int:
152 print what, "must be integer"
153 return False
154 width = res
155 elif what == "Color":
156 if type(res) not in (list, tuple) or len(res) != 3:
157 print what, "must be 3-element list"
158 return False
159 pen = [r%256 for r in res] # лень проверять ещё и < 256
160 elif what == "Absc":
161 try:
162 X0,X1=float(res[0]),float(res[1])
163 except:
164 print sys.exc_value
165 return False
166 elif what == "Funct":
167 try:
168 x=X0
169 y=eval(str(res))
170 fml=str(res)
171 print "FML:",fml
172 except:
173 print sys.exc_value
174 return False
175 elif what == "Save":
176 try:
177 pygame.image.save(screen,res)
178 except:
179 print sys.exc_value
180 return False
181 elif what == "Edit":
182 try:
183 newscr = pygame.image.load(res)
184 screen.blit(newscr,(0,0))
185 except:
186 print sys.exc_value
187 return False
188 else:
189 print "Unknown", what
190 return True
191
192 # Основной экран
193 W,H=640,480
194 screen=pygame.display.set_mode((W,H))
195
196 pen,width=(10,100,200),2
197 X0,X1=1,8
198 fml="sin(x)"
199 font = pygame.font.Font(None, W/24)
200 States=("Draw", "Input", "Base")
201 Figures={"o":"Circle", "l":"Line", "r":"Rect", "y":"Function"}
202 Figures3={"d":"Ellipse"}
203 Inputs={"w": ("Width", u"ширину линии"),
204 "c": ("Color", u"цвет линии"),
205 "f": ("Funct", u"функцию для рисования"),
206 "x": ("Absc", u"минимальное, максимальное значение X"),
207 "s": ("Save", u"имя файла для сохранения"),
208 "e": ("Edit", u"имя файла для чтения"),
209 }
210 Center=(0,0)
211 Copy=None
212
213 State, Stage, Action = "Base", 1, "Line"
214 while True:
215 pygame.display.flip()
216 event = pygame.event.wait()
217 # Выход по закрытию окна
218 if event.type == pygame.QUIT: sys.exit()
219 if State == "Base": # основное состояние
220 if event.type == pygame.KEYDOWN:
221 key = event.unicode.lower()
222 if key == "q":
223 sys.exit()
224 elif key in Figures.keys(): # Начать рисование фигуры
225 State,Stage,Action = "Draw", 1, Figures[event.unicode.lower()]
226 Copy = screen.copy()
227 elif key in Figures3.keys(): # Начать рисование фигуры
228 State,Stage,Action = "Draw3", 1, Figures3[event.unicode.lower()]
229 Copy = screen.copy()
230 elif key in Inputs.keys(): # Что-то ввести и обработать результат
231 Ask_n_Do(screen, *Inputs[key])
232 elif State == "Draw": # рисование фигуры
233 DrawState(screen, event, 2)
234 elif State == "Draw3": # рисование фигуры
235 DrawState(screen, event, 3)
Прикреплённые файлы
Для ссылки на прикреплённый файл в тексте страницы напишите attachment:имяфайла, как показано ниже в списке файлов. Не используйте URL из ссылки «[получить]», так как он чисто внутренний и может измениться.- [получить | показать] (2011-09-26 11:35:27, 1.6 KB) [[attachment:Oval.seg]]
- [получить | показать] (2011-09-26 11:35:27, 2.4 KB) [[attachment:PyGameState_Editor.dia]]
- [получить | показать] (2011-09-26 11:35:27, 2.8 KB) [[attachment:PyGameState_Ellipse.dia]]
- [получить | показать] (2011-09-26 11:35:27, 2.8 KB) [[attachment:PyGameState_Figure.dia]]
- [получить | показать] (2011-09-26 11:35:27, 1.5 KB) [[attachment:PyGameState_Input.dia]]
- [получить | показать] (2011-09-26 11:35:27, 0.4 KB) [[attachment:grap_0.py]]
- [получить | показать] (2011-09-26 11:35:27, 1.4 KB) [[attachment:grap_1-1.py]]
- [получить | показать] (2011-09-26 11:35:27, 1.1 KB) [[attachment:grap_1.py]]
- [получить | показать] (2011-09-26 11:35:27, 1.8 KB) [[attachment:grap_2.py]]
- [получить | показать] (2011-09-26 11:35:27, 2.4 KB) [[attachment:grap_3.py]]
- [получить | показать] (2011-09-26 11:35:27, 2.6 KB) [[attachment:grap_4.py]]
- [получить | показать] (2011-09-26 11:35:27, 2.0 KB) [[attachment:grap_5-0.py]]
- [получить | показать] (2011-09-26 11:35:27, 4.8 KB) [[attachment:grap_5-1.py]]
- [получить | показать] (2011-09-26 11:35:27, 3.6 KB) [[attachment:grap_5.py]]
- [получить | показать] (2011-09-26 11:35:27, 3.5 KB) [[attachment:grap_6-0.py]]
- [получить | показать] (2011-09-26 11:35:27, 4.7 KB) [[attachment:grap_6.py]]
- [получить | показать] (2011-09-26 11:35:27, 9.7 KB) [[attachment:grap_7.py]]
- [получить | показать] (2011-09-26 11:35:27, 0.8 KB) [[attachment:pygame_0.py]]
- [получить | показать] (2011-09-26 11:35:27, 2.2 KB) [[attachment:pygame_1-1.py]]
- [получить | показать] (2011-09-26 11:35:27, 1.9 KB) [[attachment:pygame_1.py]]
- [получить | показать] (2011-09-26 11:35:27, 2.5 KB) [[attachment:pygame_2-0.py]]
- [получить | показать] (2011-09-26 11:35:27, 1.3 KB) [[attachment:pygame_2-1-0.py]]
- [получить | показать] (2011-09-26 11:35:27, 5.6 KB) [[attachment:pygame_2-1.py]]
Вам нельзя прикреплять файлы к этой странице.